429 lines
24 KiB
Plaintext
429 lines
24 KiB
Plaintext
---
|
|
name: cubemx-min-prj
|
|
description: Create an STM32CubeMX minimum project (CMake/VS Code ready) matching STM32F407ZGTx clocks and debug setup. Use when generating a new CubeMX-based STM32 project or updating this workflow; confirm the locally installed CubeMX version before creating or editing any `.ioc` so the project stays openable on the user's machine.
|
|
metadata:
|
|
author: bowei-local
|
|
version: "1.5"
|
|
compatibility: Requires STM32CubeMX at C:/Program Files/STMicroelectronics/STM32Cube/STM32CubeMX/STM32CubeMX.exe and STM32CubeCLT available for VS Code debug.
|
|
---
|
|
|
|
# STM32CubeMX Project Creator
|
|
|
|
Teach Claude to create a new STM32CubeMX project for `STM32F407ZGTx`, output a CMake build for VS Code, and prep debug tasks. The generated project must preserve the required `USART2` behavior exactly, including DMA-based idle reception and the supporting user-code hooks in `usart.c`, `main.c`, and `syscalls.c`.
|
|
|
|
The skill must be self-contained. Do not inspect, copy from, diff against, or otherwise rely on other user projects as templates or references when generating a new project.
|
|
|
|
## Preconditions
|
|
- Confirm CubeMX exists at `C:/Program Files/STMicroelectronics/STM32Cube/STM32CubeMX/STM32CubeMX.exe`; otherwise stop and report.
|
|
- Confirm the installed CubeMX version before generating or editing the project. If the local version cannot be determined, stop and report instead of guessing.
|
|
- REQUIRED VERSION LOCK: local STM32CubeMX must be exactly `6.11.1`. If the detected version is not exactly `6.11.1`, stop immediately and report an error; do not proceed. Note: `6.11.1-*` is equal to `6.11.1`.
|
|
- Ensure written `.ioc` metadata is `MxCube.Version=6.11.1` for this skill.
|
|
- Use only the installed CubeMX, its bundled databases, and the requested project directory as inputs. Do not use another workspace or existing STM32 project as a reference.
|
|
- Have an output directory where the new project folder will be created.
|
|
- Ask the user for the project name.
|
|
- VS Code STM32 extensions are available (CMake Tools, Cortex-Debug, STM32 VS Code Extension).
|
|
|
|
## Strict IOC acceptance gates
|
|
- The generated `.ioc` must match this skill's required configuration exactly (MCU, clock tree, RCC/NVIC/DMA/GPIO/USART2 settings, and pin map). No partial match is acceptable.
|
|
- Re-check the final `.ioc` against the required values before finishing; if any field differs, treat as failure and fix/regenerate.
|
|
- For `USART2` compatibility, do not hand-write `WordLength/Parity/StopBits` enum lines in `.ioc`. Keep `USART2.IPParameters` minimal (`VirtualMode,BaudRate,Mode,OverSampling`) and let CubeMX resolve 8N1 defaults during load/generation.
|
|
- Opening the `.ioc` must not show `Not a valid ioc file` or required-field incompatibility errors.
|
|
- If any IOC gate fails, stop, fix in IOC, regenerate, and re-validate before any further edits.
|
|
|
|
## MCU + clock configuration
|
|
- MCU: `STM32F407ZGTx`, package `LQFP144`.
|
|
- Clock source: HSE crystal = `25_000_000 Hz` on `PH0/PH1`.
|
|
- PLL: source HSE, `PLLM=25`, `PLLN=168`, `PLLP=2`, `PLLQ=4`.
|
|
- Resulting clocks: `SYSCLK=84 MHz`, `HCLK=84 MHz`, `APB1=42 MHz`, `APB2=84 MHz`, `I2S=96 MHz`, `MCO2=84 MHz`, `Systick=1 ms`.
|
|
- Ensure RCC: `SYSCLK source = PLLCLK`, `LSI = 32000`, and keep the divider values listed here.
|
|
|
|
## Generation targets
|
|
- Toolchain/IDE: CMake (Ninja or Make). Enable `CMAKE_EXPORT_COMPILE_COMMANDS`.
|
|
- Languages: C + ASM, C standard C11.
|
|
- Linker script: device-generated `STM32F407ZGTx_FLASH.ld`.
|
|
- Peripherals to enable by default: RCC, SYS, NVIC, GPIO, DMA, USART2.
|
|
- GPIO baseline:
|
|
- SWD: `PA13` = `SYS_JTMS-SWDIO`, `PA14` = `SYS_JTCK-SWCLK`
|
|
- Oscillators: `PH0/PH1` for HSE
|
|
- USART pins: `PD5` = `USART2_TX`, `PD6` = `USART2_RX`
|
|
- Remove all other GPIO assignments unless the user explicitly asks for them
|
|
- NVIC baseline:
|
|
- `NVIC_PRIORITYGROUP_4`
|
|
- System handlers enabled as generated by CubeMX
|
|
- `SysTick_IRQn` enabled with priority `15`
|
|
- Enable `DMA1_Stream5_IRQn` and `DMA1_Stream6_IRQn`
|
|
- DMA baseline:
|
|
- `USART2_RX`: `DMA1_Stream5`, `DMA_CHANNEL_4`, `DMA_PERIPH_TO_MEMORY`, `DMA_NORMAL`, byte alignment, memory increment enabled, peripheral increment disabled, priority low, FIFO disabled
|
|
- `USART2_TX`: `DMA1_Stream6`, `DMA_CHANNEL_4`, `DMA_MEMORY_TO_PERIPH`, `DMA_NORMAL`, byte alignment, memory increment enabled, peripheral increment disabled, priority low, FIFO disabled
|
|
- USART2 baseline:
|
|
- Virtual mode: `VM_ASYNC`
|
|
- Parameters in generated init: `115200`, `8N1`, `TX_RX`, `UART_HWCONTROL_NONE`, `UART_OVERSAMPLING_16`
|
|
- `HAL_UART_MspInit()` must configure `PD5/PD6` as `GPIO_AF7_USART2` and link both DMA handles with `__HAL_LINKDMA`
|
|
- `stm32f4xx_it.c` must keep `DMA1_Stream5_IRQHandler()` and `DMA1_Stream6_IRQHandler()` calling `HAL_DMA_IRQHandler(&hdma_usart2_rx)` and `HAL_DMA_IRQHandler(&hdma_usart2_tx)`
|
|
- Do not add other peripherals unless the user explicitly requests them.
|
|
|
|
## USART2 runtime behavior
|
|
- `printf` redirection pattern:
|
|
- Keep `syscalls.c` with `extern int __io_putchar(int ch) __attribute__((weak));`
|
|
- Do not implement `__io_putchar()` in `syscalls.c`
|
|
- Re-define `int __io_putchar(int ch)` in `Core/Src/usart.c`
|
|
- Implementation must call `HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, 1000);` and return `ch`
|
|
- DMA receive flow:
|
|
- In `main.c`, after `MX_GPIO_Init();`, `MX_DMA_Init();`, and `MX_USART2_UART_Init();`, call `HAL_UARTEx_ReceiveToIdle_DMA(&huart2, receiveBuf50, sizeof(receiveBuf50));`
|
|
- Implement `HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)` in user code, not the legacy `HAL_UART_RxCpltCallback()`
|
|
- In that callback, when `huart->Instance == USART2`, terminate the buffer safely, process the received command, then immediately re-arm `HAL_UARTEx_ReceiveToIdle_DMA(&huart2, receiveBuf50, sizeof(receiveBuf50));`
|
|
- Ensure the generated project includes all symbols used by this flow:
|
|
- `UART_HandleTypeDef huart2`
|
|
- `DMA_HandleTypeDef hdma_usart2_rx`
|
|
- `DMA_HandleTypeDef hdma_usart2_tx`
|
|
- a receive buffer such as `uint8_t receiveBuf50[50]`
|
|
|
|
## VS Code integration (mirror reference patterns)
|
|
Create `.vscode/` with:
|
|
- `settings.json`:
|
|
- `"cmake.configurePreset": "Debug"`
|
|
- `"cmake.buildPreset": "Debug"`
|
|
- `"STM32VSCodeExtension.cubeCLT.path": "C:/ST/STM32CubeCLT_1.19.0"` (or user path)
|
|
- `c_cpp_properties.json`: `configurationProvider` = `ms-vscode.cmake-tools`
|
|
- `tasks.json`: include
|
|
- A fixed `CMake: configure` task that runs `cmake --preset Debug`
|
|
- A fixed default build task that runs `cmake --build --preset Debug`
|
|
- A fixed clean rebuild task that runs `cmake --build --preset Debug --clean-first`
|
|
- Mark the fixed build task as the default build group so VS Code `Ctrl+Shift+B` works immediately
|
|
- Flash task: `STM32_Programmer_CLI --connect port=swd --download ${workspaceFolder}/build/Debug/<proj>.elf -hardRst -rst --start`
|
|
- Aggregate "Build + Flash" task depending on rebuild + flash
|
|
- Avoid depending on `${command:cmake.activeBuildPresetName}`, `${command:cmake.activeConfigurePresetName}`, or `${command:cmake.launchTargetPath}` for the default build path, because `Ctrl+Shift+B` may fail before CMake Tools initializes those values
|
|
- `launch.json`: Cortex-Debug launch + attach configs:
|
|
- `servertype: stlink`, `device: STM32F407ZGTx`, `interface: swd`
|
|
- `executable: ${workspaceFolder}/build/Debug/<proj>.elf`
|
|
- `svdFile: ${config:STM32VSCodeExtension.cubeCLT.path}/STMicroelectronics_CMSIS_SVD/STM32F407.svd`
|
|
- `serverpath`/`stlinkPath`: `${config:STM32VSCodeExtension.cubeCLT.path}/STLink-gdb-server/bin/ST-LINK_gdbserver`
|
|
- `armToolchainPath`: `${config:STM32VSCodeExtension.cubeCLT.path}/GNU-tools-for-STM32/bin`
|
|
- `gdbPath`: `${config:STM32VSCodeExtension.cubeCLT.path}/GNU-tools-for-STM32/bin/arm-none-eabi-gdb`
|
|
- `preLaunchTask`: `CMake: clean rebuild` (for launch config)
|
|
|
|
## CMake scaffolding (root)
|
|
- `CMakeLists.txt`: include toolchain `cmake/gcc-arm-none-eabi.cmake`, set `CMAKE_C_STANDARD 11`, enable C & ASM, create executable `${CMAKE_PROJECT_NAME}`, `add_subdirectory(cmake/stm32cubemx)`, add user sources, link `stm32cubemx`.
|
|
- `CMakePresets.json`: generator Ninja, binary dir `build/${presetName}`, presets Debug/RelWithDebInfo/Release/MinSizeRel inheriting default.
|
|
- `cmake/gcc-arm-none-eabi.cmake`: set `TOOLCHAIN_PREFIX=arm-none-eabi-`, compilers, target flags `-mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard`, link script `STM32F407ZGTx_FLASH.ld`, typical link flags with gc-sections and map file.
|
|
- `cmake/stm32cubemx/CMakeLists.txt`: interface lib with `USE_HAL_DRIVER`, `STM32F407xx`, includes for `Core/Inc` and `Drivers`, and CubeMX-generated sources for the minimal setup (at minimum `main.c`, `gpio.c`, `dma.c`, `usart.c`, `stm32f4xx_it.c`, `stm32f4xx_hal_msp.c`, `system_stm32f4xx.c`, `startup_stm32f407xx.s`, and required HAL driver files). Keep it aligned with CubeMX output; regenerate if peripherals differ.
|
|
|
|
## Execution steps
|
|
1) Verify CubeMX binary exists; if missing, stop.
|
|
2) Detect and record the installed CubeMX version before doing any `.ioc` work. Use that exact version when validating compatibility and when writing `MxCube.Version` / related metadata.
|
|
- Hard stop unless the detected version is exactly `6.11.1`.
|
|
3) Do not handcraft a full STM32 project when CubeMX generation is available locally. Generate with the installed CubeMX first, then patch only the required user sections and build files.
|
|
4) Do not inspect or copy from any other project on disk. This skill must work independently from CubeMX metadata, generated output, and the instructions in this file only.
|
|
5) Ask user for project name and target directory.
|
|
6) Create project folder and open CubeMX:
|
|
- Set MCU to STM32F407ZGTx (LQFP144).
|
|
- Configure RCC: HSE 25 MHz on `PH0/PH1`, `PLLM=25`, `PLLN=168`, `PLLP=2`, `PLLQ=4`, `SYSCLK` from PLL.
|
|
- Enable required peripherals for the default template: SYS, RCC, NVIC, GPIO, DMA, USART2.
|
|
- Configure only these GPIO entries by default: `PH0`, `PH1`, `PA13`, `PA14`, `PD5`, `PD6`.
|
|
- Configure `USART2` as asynchronous on `PD5/PD6`.
|
|
- Configure DMA requests exactly as specified here: `USART2_RX -> DMA1_Stream5`, `USART2_TX -> DMA1_Stream6`.
|
|
- Set `NVIC_PRIORITYGROUP_4`, keep `SysTick_IRQn` at priority `15`, and enable both DMA stream IRQs.
|
|
- Project Manager -> Toolchain/IDE: CMake; set project name and path.
|
|
- Code Generator: Generate peripheral initialization as "HAL", keep user sections.
|
|
- Generate code.
|
|
7) Validate the generated output before patching:
|
|
- Confirm `main.c` exists and `SystemClock_Config()` uses `HSE`, `PLL_ON`, `PLLM=25`, `PLLN=168`, `PLLP=RCC_PLLP_DIV2`, `PLLQ=4`, `SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK`, `AHB = DIV1`, `APB1 = DIV2`, `APB2 = DIV1`.
|
|
- Confirm the generated project includes `USART2`, `DMA1_Stream5`, `DMA1_Stream6`, and `USART2_IRQn`.
|
|
- Confirm the generated `.ioc` does not report required-field incompatibilities for RCC, DMA, SYS, GPIO, or USART2.
|
|
- Confirm `.ioc` loads without `Not a valid ioc file`.
|
|
- Confirm `.ioc` does not contain hand-written `USART2.WordLength`, `USART2.Parity`, `USART2.StopBits` lines and `USART2.IPParameters` remains `VirtualMode,BaudRate,Mode,OverSampling` before generation.
|
|
- If CubeMX output falls back to `HSI`, `PLL_NONE`, missing DMA streams, or missing USART2 init, treat generation as failed and fix generation inputs before patching.
|
|
8) Patch the generated sources to preserve the required `USART2` runtime behavior:
|
|
- In `Core/Src/usart.c`, add `__io_putchar()` in user code and keep it bound to `HAL_UART_Transmit(&huart2, ...)`.
|
|
- In `Core/Src/syscalls.c`, leave `__io_putchar()` as a weak external declaration only.
|
|
- In `Core/Src/main.c`, declare a receive buffer, call `HAL_UARTEx_ReceiveToIdle_DMA(&huart2, receiveBuf50, sizeof(receiveBuf50));` during initialization, and implement `HAL_UARTEx_RxEventCallback()` to process and re-arm reception.
|
|
- In `Core/Src/stm32f4xx_it.c`, keep both DMA IRQ handlers for `USART2`.
|
|
- This step is the only allowed direct source-code modification step.
|
|
9) Normalize the generated layout to the required root structure if CubeMX emits a different but equivalent layout:
|
|
- Required end state is root `Core/Inc`, `Core/Src`, `Drivers`, `cmake`, `.vscode`, linker script, startup file, and root `.ioc`.
|
|
- If CubeMX emits `Inc/` and `Src/` at the root, move them to `Core/Inc` and `Core/Src` before patching build files.
|
|
10) Add/adjust the CMake scaffolding files (root CMakeLists, presets, toolchain, stm32cubemx CMakeLists) to match the templates above if CubeMX did not emit them.
|
|
11) Add `.vscode` files as above; set `executable` paths to the chosen project name.
|
|
12) Validate VS Code build behavior:
|
|
- Confirm the default VS Code build task maps to `cmake --build --preset Debug`.
|
|
- Confirm build tasks do not rely on unresolved CMake Tools command substitutions for the default build path.
|
|
- If needed, prefer fixed `Debug` preset names and fixed `${workspaceFolder}/build/Debug/<proj>.elf` paths over dynamic commands.
|
|
13) Before finishing, re-check the generated `.ioc` header and confirm its CubeMX version metadata still matches the local installation. Fix it if it drifted.
|
|
- For this skill, it must be exactly `MxCube.Version=6.11.1`.
|
|
14) Enforce no-manual-edit rule:
|
|
- Except for `USART2 runtime behavior` source edits in step 8, do not directly modify generated source code to fix config mismatches.
|
|
- All non-runtime configuration fixes must be made in `.ioc`, then regenerated from CubeMX.
|
|
15) Run `cmake --preset Debug` then `cmake --build --preset Debug` to verify build; ensure `${workspaceFolder}/build/Debug/<proj>.elf` exists.
|
|
16) Verify VS Code `Ctrl+Shift+B` can invoke the generated default build task without manual preset reselection.
|
|
17) For flashing, run VS Code task "Build + Flash" or `STM32_Programmer_CLI --connect port=swd --download build/Debug/<proj>.elf -hardRst -rst --start`.
|
|
18) For debugging, launch "Build & Debug Microcontroller - ST-Link" in VS Code (Cortex-Debug).
|
|
|
|
## Notes & guardrails
|
|
- Prefer using commands listed in `Reference commands` whenever possible. If a listed command cannot be used, use an equivalent command and briefly state why.
|
|
- Keep `SKILL.md` concise; move verbose reference to separate files if added.
|
|
- If user chooses another MCU, re-derive clocks accordingly instead of using the above constants.
|
|
- Version policy for this skill is strict: only `6.11.1` is allowed. Any other detected version is a hard error.
|
|
- Do not continue from an invalid CubeMX load that logs missing required RCC, DMA, SYS, GPIO, or USART fields. Fix the `.ioc` / generation inputs first.
|
|
- For `USART2`, avoid hardcoding enum text values in `.ioc` for `WordLength/Parity/StopBits`; rely on CubeMX defaults and generated init checks instead.
|
|
- Do not finish if IOC cannot be opened cleanly by CubeMX.
|
|
- Do not continue patching if generated `main.c` shows `HSI` or `PLL_NONE` instead of the required `HSE + PLL` clock tree.
|
|
- This skill must remain independent. Do not read another STM32 project to discover valid `.ioc` keys, clock parameters, or file layouts.
|
|
- Prefer deterministic VS Code tasks. Do not assume VS Code `Ctrl+Shift+B` will work if the tasks depend on unresolved extension-provided command variables.
|
|
- Do not refer to the VS Code build shortcut as `Ctrl+B`; in standard VS Code usage the build shortcut is `Ctrl+Shift+B`.
|
|
- For the default build path, prefer fixed `Debug` preset tasks over dynamic `${command:...}` substitutions unless those substitutions are explicitly verified in the current workspace.
|
|
- Unless the user asks for more peripherals, remove any auto-enabled middleware or peripheral blocks beyond DMA, GPIO, NVIC, RCC, SYS, and USART2 from both the CubeMX configuration and generated build files.
|
|
- When stripping peripherals from a copied `.ioc`, also remove their dependent pins, DMA requests, NVIC entries, generated source files, and middleware references so the result stays internally consistent.
|
|
- For GPIO specifically, keep only these default pins: `PH0`, `PH1`, `PA13`, `PA14`, `PD5`, `PD6`.
|
|
- Do not replace the required `HAL_UARTEx_ReceiveToIdle_DMA()` + `HAL_UARTEx_RxEventCallback()` flow with polling, interrupt-only receive, or `HAL_UART_Receive_DMA()`.
|
|
- Do not move `__io_putchar()` into `syscalls.c`; keep the actual implementation in `usart.c` so `printf` stays coupled to `USART2`.
|
|
- Except for the explicit `USART2 runtime behavior` edits, do not directly edit generated C sources for configuration purposes; enforce configuration via IOC + regenerate.
|
|
|
|
## Reference commands
|
|
Use these commands as operational references for this skill. Adapt `<proj>` / paths as needed.
|
|
|
|
1) Check CubeMX binary and version
|
|
```powershell
|
|
$mx='C:/Program Files/STMicroelectronics/STM32Cube/STM32CubeMX/STM32CubeMX.exe'
|
|
Test-Path $mx
|
|
(Get-Item $mx).VersionInfo
|
|
```
|
|
|
|
2) Set CubeMX CLI runtime (required by later commands)
|
|
```powershell
|
|
$java='C:/Program Files/STMicroelectronics/STM32Cube/STM32CubeMX/jre/bin/java.exe'
|
|
$jar='C:/Program Files/STMicroelectronics/STM32Cube/STM32CubeMX/STM32CubeMX.exe'
|
|
```
|
|
|
|
3) Probe CLI command capabilities (optional, useful when syntax differs by install)
|
|
```powershell
|
|
@'
|
|
help
|
|
project
|
|
config
|
|
set
|
|
get
|
|
generate
|
|
exit
|
|
'@ | Set-Content -Encoding ascii .mx_probe_cmd.txt
|
|
|
|
& $java -jar $jar -q .mx_probe_cmd.txt
|
|
```
|
|
|
|
4) Create a brand new project + IOC (empty workspace case)
|
|
```powershell
|
|
@'
|
|
load STM32F407ZGTx
|
|
project name <proj>
|
|
project toolchain CMake
|
|
generate code .
|
|
config saveas <proj>.ioc
|
|
exit
|
|
'@ | Set-Content -Encoding ascii .mx_create_cmd.txt
|
|
|
|
& $java -jar $jar -q .mx_create_cmd.txt
|
|
```
|
|
|
|
5) Configure existing IOC then regenerate code (already-created IOC case)
|
|
```powershell
|
|
@'
|
|
config load <proj>.ioc
|
|
generate code .
|
|
exit
|
|
'@ | Set-Content -Encoding ascii .mx_cmd.txt
|
|
|
|
& $java -jar $jar -q .mx_cmd.txt
|
|
```
|
|
|
|
6) Apply minimum required pin/peripheral modes before regeneration
|
|
```powershell
|
|
@'
|
|
config load <proj>.ioc
|
|
set mode RCC HSE-External-Oscillator
|
|
set mode SYS Serial_Wire
|
|
set mode USART2 Asynchronous
|
|
set pin PH0 RCC_OSC_IN
|
|
set pin PH1 RCC_OSC_OUT
|
|
set pin PA13 SYS_JTMS-SWDIO
|
|
set pin PA14 SYS_JTCK-SWCLK
|
|
set pin PD5 USART2_TX
|
|
set pin PD6 USART2_RX
|
|
config save
|
|
generate code .
|
|
exit
|
|
'@ | Set-Content -Encoding ascii .mx_set_basic_cmd.txt
|
|
|
|
& $java -jar $jar -q .mx_set_basic_cmd.txt
|
|
```
|
|
|
|
7) Apply RCC clock parameters required by this skill, then regenerate
|
|
```powershell
|
|
@'
|
|
config load <proj>.ioc
|
|
set ip parameters RCC OscillatorType RCC_OSCILLATORTYPE_HSE
|
|
set ip parameters RCC OscillatorTypeHSE RCC_OSCILLATORTYPE_HSE
|
|
set ip parameters RCC HSEState RCC_HSE_ON
|
|
set ip parameters RCC HSEStateARG RCC_HSE_ON
|
|
set ip parameters RCC HSEUsed 1
|
|
set ip parameters RCC PLLState RCC_PLL_ON
|
|
set ip parameters RCC PLLStateARG RCC_PLL_ON
|
|
set ip parameters RCC PLLUsed 1
|
|
set ip parameters RCC PLLUsedForSys 1
|
|
set ip parameters RCC PLLSource RCC_PLLSOURCE_HSE
|
|
set ip parameters RCC PLLSourceARG RCC_PLLSOURCE_HSE
|
|
set ip parameters RCC PLLSourceVirtual RCC_PLLSOURCE_HSE
|
|
set ip parameters RCC PLLM 25
|
|
set ip parameters RCC PLLN 168
|
|
set ip parameters RCC PLLP PLLP_DIV2
|
|
set ip parameters RCC PLLQ 4
|
|
set ip parameters RCC SYSCLKSource RCC_SYSCLKSOURCE_PLLCLK
|
|
set ip parameters RCC SYSCLKSourceARG RCC_SYSCLKSOURCE_PLLCLK
|
|
set ip parameters RCC AHBCLKDivider RCC_SYSCLK_DIV1
|
|
set ip parameters RCC AHBCLKDividerARG RCC_SYSCLK_DIV1
|
|
set ip parameters RCC APB1CLKDivider RCC_HCLK_DIV2
|
|
set ip parameters RCC APB1CLKDividerARG RCC_HCLK_DIV2
|
|
set ip parameters RCC APB2CLKDivider RCC_HCLK_DIV1
|
|
set ip parameters RCC APB2CLKDividerARG RCC_HCLK_DIV1
|
|
set ip parameters RCC FLatency FLASH_LATENCY_2
|
|
set ip parameters RCC HCLKFreq_Value 84000000
|
|
set ip parameters RCC AHBFreq_Value 84000000
|
|
set ip parameters RCC APB1Freq_Value 42000000
|
|
set ip parameters RCC APB2Freq_Value 84000000
|
|
set ip parameters RCC APB1TimFreq_Value 84000000
|
|
set ip parameters RCC APB2TimFreq_Value 84000000
|
|
set ip parameters RCC SYSCLKFreq_VALUE 84000000
|
|
set ip parameters RCC CortexFreq_Value 84000000
|
|
set ip parameters RCC FCLKCortexFreq_Value 84000000
|
|
set ip parameters RCC PLLCLKFreq_Value 84000000
|
|
set ip parameters RCC PLLQCLKFreq_Value 42000000
|
|
set ip parameters RCC VCOInputFreq_Value 1000000
|
|
set ip parameters RCC VCOOutputFreq_Value 168000000
|
|
set ip parameters RCC HSE_VALUE 25000000
|
|
set ip parameters RCC LSI_VALUE 32000
|
|
set ip parameters USART2 VirtualMode VM_ASYNC
|
|
set ip parameters USART2 BaudRate 115200
|
|
set ip parameters USART2 Mode MODE_TX_RX
|
|
set ip parameters USART2 OverSampling UART_OVERSAMPLING_16
|
|
config save
|
|
generate code .
|
|
exit
|
|
'@ | Set-Content -Encoding ascii .mx_clock_uart_cmd.txt
|
|
|
|
& $java -jar $jar -q .mx_clock_uart_cmd.txt
|
|
```
|
|
|
|
7b) Apply DMA baseline using IOC `Dma.*` keys (CubeMX CLI does not accept `USART2_RxDMA/USART2_TxDMA` as valid `set ip parameters`)
|
|
```powershell
|
|
$ioc='<proj>.ioc'
|
|
$lines=Get-Content $ioc
|
|
|
|
# Remove invalid/legacy USART2 DMA keys and existing Dma section before rewriting
|
|
$lines=$lines | Where-Object {
|
|
$_ -notmatch '^USART2\.USART2_RxDMA=' -and
|
|
$_ -notmatch '^USART2\.USART2_TxDMA=' -and
|
|
$_ -notmatch '^Dma\.'
|
|
}
|
|
|
|
# Keep USART2 IP parameters minimal per skill gate
|
|
$lines=$lines | ForEach-Object {
|
|
if($_ -match '^USART2\.IPParameters='){ 'USART2.IPParameters=VirtualMode,BaudRate,Mode,OverSampling' }
|
|
elseif($_ -match '^USART2\.BaudRate='){ 'USART2.BaudRate=115200' }
|
|
elseif($_ -match '^USART2\.Mode='){ 'USART2.Mode=MODE_TX_RX' }
|
|
elseif($_ -match '^USART2\.OverSampling='){ 'USART2.OverSampling=UART_OVERSAMPLING_16' }
|
|
elseif($_ -match '^USART2\.VirtualMode='){ 'USART2.VirtualMode=VM_ASYNC' }
|
|
else { $_ }
|
|
}
|
|
|
|
# Ensure required USART2 fields exist
|
|
if(-not ($lines -match '^USART2\.BaudRate=')){ $lines += 'USART2.BaudRate=115200' }
|
|
if(-not ($lines -match '^USART2\.IPParameters=')){ $lines += 'USART2.IPParameters=VirtualMode,BaudRate,Mode,OverSampling' }
|
|
if(-not ($lines -match '^USART2\.Mode=')){ $lines += 'USART2.Mode=MODE_TX_RX' }
|
|
if(-not ($lines -match '^USART2\.OverSampling=')){ $lines += 'USART2.OverSampling=UART_OVERSAMPLING_16' }
|
|
if(-not ($lines -match '^USART2\.VirtualMode=')){ $lines += 'USART2.VirtualMode=VM_ASYNC' }
|
|
|
|
# DMA request block for USART2 RX/TX
|
|
$dma=@(
|
|
'Dma.Request0=USART2_RX',
|
|
'Dma.Request1=USART2_TX',
|
|
'Dma.RequestsNb=2',
|
|
'Dma.USART2_RX.0.Direction=DMA_PERIPH_TO_MEMORY',
|
|
'Dma.USART2_RX.0.FIFOMode=DMA_FIFOMODE_DISABLE',
|
|
'Dma.USART2_RX.0.Instance=DMA1_Stream5',
|
|
'Dma.USART2_RX.0.MemDataAlignment=DMA_MDATAALIGN_BYTE',
|
|
'Dma.USART2_RX.0.MemInc=DMA_MINC_ENABLE',
|
|
'Dma.USART2_RX.0.Mode=DMA_NORMAL',
|
|
'Dma.USART2_RX.0.PeriphDataAlignment=DMA_PDATAALIGN_BYTE',
|
|
'Dma.USART2_RX.0.PeriphInc=DMA_PINC_DISABLE',
|
|
'Dma.USART2_RX.0.Priority=DMA_PRIORITY_LOW',
|
|
'Dma.USART2_RX.0.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode',
|
|
'Dma.USART2_TX.1.Direction=DMA_MEMORY_TO_PERIPH',
|
|
'Dma.USART2_TX.1.FIFOMode=DMA_FIFOMODE_DISABLE',
|
|
'Dma.USART2_TX.1.Instance=DMA1_Stream6',
|
|
'Dma.USART2_TX.1.MemDataAlignment=DMA_MDATAALIGN_BYTE',
|
|
'Dma.USART2_TX.1.MemInc=DMA_MINC_ENABLE',
|
|
'Dma.USART2_TX.1.Mode=DMA_NORMAL',
|
|
'Dma.USART2_TX.1.PeriphDataAlignment=DMA_PDATAALIGN_BYTE',
|
|
'Dma.USART2_TX.1.PeriphInc=DMA_PINC_DISABLE',
|
|
'Dma.USART2_TX.1.Priority=DMA_PRIORITY_LOW',
|
|
'Dma.USART2_TX.1.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode'
|
|
)
|
|
|
|
# Place DMA block near top for readability
|
|
$out=@()
|
|
$inserted=$false
|
|
foreach($l in $lines){
|
|
$out+=$l
|
|
if(-not $inserted -and $l -eq 'CAD.provider='){
|
|
$out+=$dma
|
|
$inserted=$true
|
|
}
|
|
}
|
|
if(-not $inserted){ $out=$dma + $lines }
|
|
|
|
if(-not ($out -match '^NVIC\.DMA1_Stream5_IRQn=')){ $out += 'NVIC.DMA1_Stream5_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true' }
|
|
if(-not ($out -match '^NVIC\.DMA1_Stream6_IRQn=')){ $out += 'NVIC.DMA1_Stream6_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true' }
|
|
|
|
$out | Set-Content -Encoding ascii $ioc
|
|
|
|
@'
|
|
config load <proj>.ioc
|
|
generate code .
|
|
exit
|
|
'@ | Set-Content -Encoding ascii .mx_dma_fix_cmd.txt
|
|
|
|
& $java -jar $jar -q .mx_dma_fix_cmd.txt
|
|
```
|
|
|
|
8) Validate IOC can be loaded cleanly
|
|
```powershell
|
|
@'
|
|
config load <proj>.ioc
|
|
exit
|
|
'@ | Set-Content -Encoding ascii .mx_validate_cmd.txt
|
|
|
|
& $java -jar $jar -q .mx_validate_cmd.txt
|
|
```
|
|
|
|
9) Inspect workspace and key files
|
|
```powershell
|
|
Get-ChildItem -Recurse -Force
|
|
Get-Content -Raw <proj>.ioc
|
|
rg -n "<pattern>" .
|
|
```
|
|
|
|
10) Verify generated clock/USART code quickly
|
|
```powershell
|
|
rg -n "OscillatorType|HSEState|PLLState|PLLM|PLLN|PLLP|PLLQ|SYSCLKSource|APB1CLKDivider|APB2CLKDivider|FLASH_LATENCY" Src/main.c
|
|
rg -n "huart2.Init.BaudRate|huart2.Init.Mode|huart2.Init.OverSampling" Src/main.c
|
|
```
|
|
|
|
11) Configure and build with CMake
|
|
```powershell
|
|
cmake --preset Debug
|
|
cmake --build --preset Debug
|
|
```
|
|
|
|
12) VS Code default build task target (Ctrl+Shift+B)
|
|
```powershell
|
|
cmake --build --preset Debug
|
|
```
|