# STM32CubeMX Minimal Reproduction Guide Use this guide when the task is to recreate the known `BMSv4` minimal project for `STM32F407ZGTx` in a clean workspace and prove that the generated project still builds. ## Scope - CubeMX version: `6.11.1` - MCU: `STM32F407ZGTx` - Project name: `BMSv4` - Toolchain: `CMake` - Output folder: default to `/reproduction` ## 1. Verify tools Use explicit local paths for CubeMX and fail early if they do not exist. ```powershell $mxRoot = "C:/Program Files/STMicroelectronics/STM32Cube/STM32CubeMX" $mxExe = Join-Path $mxRoot "STM32CubeMX.exe" $javaExe = Join-Path $mxRoot "jre/bin/java.exe" $mxInfo = Get-Item $mxExe | Select-Object FullName,@{N="Version";E={$_.VersionInfo.ProductVersion}} $mxInfo if ($mxInfo.Version -notmatch '^6\.11\.1(?:-.+)?$') { throw "Unsupported STM32CubeMX version: $($mxInfo.Version). Required: 6.11.1 or 6.11.1-*" } ``` If the version is not `6.11.1` or `6.11.1-*`, stop immediately. Do not create the project, patch the `.ioc`, or generate code. ## 2. Create the base project Generate the initial `.ioc` from CubeMX CLI instead of copying an existing project. ```powershell $workspace = (Get-Location).Path $projDir = Join-Path $workspace "reproduction" New-Item -ItemType Directory -Force -Path $projDir | Out-Null Set-Location $projDir @' load STM32F407ZGTx project name BMSv4 project toolchain CMake project path __PROJECT_PATH__ config saveas BMSv4.ioc exit '@.Replace("__PROJECT_PATH__", $projDir) | Set-Content -Encoding ascii .mx_init.txt & $javaExe -jar $mxExe -q .mx_init.txt ``` ## 3. Patch `.ioc` metadata that CubeMX CLI does not encode reliably This reproduction needs precise clock, DMA, and NVIC entries. Apply them directly, then regenerate code. ```powershell $ioc = "BMSv4.ioc" $content = Get-Content $ioc $fixes = @( "RCC.EthernetFreq_Value=84000000", "RCC.PLLP=RCC_PLLP_DIV2", "Dma.Request0=USART2_RX", "Dma.Request1=USART2_TX", "Dma.RequestsNb=2", "Dma.USART2_RX.0.Direction=DMA_PERIPH_TO_MEMORY", "Dma.USART2_RX.0.Instance=DMA1_Stream5", "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.Instance=DMA1_Stream6", "Dma.USART2_TX.1.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode", "Mcu.IP0=DMA", "Mcu.IP1=NVIC", "Mcu.IP2=RCC", "Mcu.IP3=SYS", "Mcu.IP4=USART2", "Mcu.IPNb=5", "NVIC.DMA1_Stream5_IRQn=true\\:0\\:0\\:false\\:false\\:true\\:false\\:true\\:true", "NVIC.DMA1_Stream6_IRQn=true\\:0\\:0\\:false\\:false\\:true\\:false\\:true\\:true", "NVIC.ForceEnableDMAVector=true", "NVIC.USART2_IRQn=true\\:0\\:0\\:false\\:false\\:true\\:false\\:false\\:true", "ProjectManager.UnderRoot=true", "ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_DMA_Init-DMA-false-HAL-true,4-MX_USART2_UART_Init-USART2-false-HAL-true" ) $newLines = $content | Where-Object { $_ -notmatch '^RCC\.EthernetFreq_Value' -and $_ -notmatch '^RCC\.PLLP' -and $_ -notmatch '^Dma\.' -and $_ -notmatch '^Mcu\.IP' -and $_ -notmatch '^NVIC\.DMA' -and $_ -notmatch '^NVIC\.USART2_IRQn' -and $_ -notmatch '^NVIC\.ForceEnableDMAVector' -and $_ -notmatch '^ProjectManager\.functionlistsort' -and $_ -notmatch '^ProjectManager\.UnderRoot' } $newLines += $fixes $newLines | Set-Content -Encoding ascii $ioc ``` ## 4. Configure peripheral modes and generate code Use CubeMX script mode for the main project shape, then generate. ```powershell @' config load BMSv4.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 set ip parameters RCC OscillatorType RCC_OSCILLATORTYPE_HSE, OscillatorTypeHSE RCC_OSCILLATORTYPE_HSE, HSEState RCC_HSE_ON, PLLState RCC_PLL_ON, PLLSource RCC_PLLSOURCE_HSE, PLLM 25, PLLN 168, PLLP PLLP_DIV2, PLLQ 4, SYSCLKSource RCC_SYSCLKSOURCE_PLLCLK, AHBCLKDivider RCC_SYSCLK_DIV1, APB1CLKDivider RCC_HCLK_DIV2, APB2CLKDivider RCC_HCLK_DIV1 set ip parameters USART2 VirtualMode VM_ASYNC, BaudRate 115200, Mode MODE_TX_RX, OverSampling UART_OVERSAMPLING_16 config save generate code . exit '@ | Set-Content -Encoding ascii .mx_config.txt & $javaExe -jar $mxExe -q .mx_config.txt ``` ## 5. Add the minimal user code needed for reproduction Apply only small, isolated changes inside user-code regions. ```powershell $usartFile = "Core/Src/usart.c" $usart = Get-Content $usartFile -Raw $usartPatch = "/* USER CODE BEGIN 1 */`r`nint __io_putchar(int ch)`r`n{`r`n HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, 1000);`r`n return ch;`r`n}`r`n/* USER CODE END 1 */" $usart = $usart -replace '(?s)/\* USER CODE BEGIN 1 \*/.*?/\* USER CODE END 1 \*/', $usartPatch $usart | Set-Content -Encoding utf8 $usartFile $mainFile = "Core/Src/main.c" $main = Get-Content $mainFile -Raw $main = $main -replace '(?s)/\* USER CODE BEGIN PV \*/.*?/\* USER CODE END PV \*/', "/* USER CODE BEGIN PV */`r`nuint8_t receiveBuf50[50];`r`n/* USER CODE END PV */" $main = $main -replace '(?s)/\* USER CODE BEGIN 2 \*/.*?/\* USER CODE END 2 \*/', " /* USER CODE BEGIN 2 */`r`n HAL_UARTEx_ReceiveToIdle_DMA(&huart2, receiveBuf50, sizeof(receiveBuf50));`r`n /* USER CODE END 2 */" $main = $main -replace '(?s)/\* USER CODE BEGIN 4 \*/.*?/\* USER CODE END 4 \*/', "/* USER CODE BEGIN 4 */`r`nvoid HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)`r`n{`r`n if (huart->Instance == USART2)`r`n {`r`n HAL_UART_Transmit_DMA(&huart2, receiveBuf50, Size);`r`n HAL_UARTEx_ReceiveToIdle_DMA(&huart2, receiveBuf50, sizeof(receiveBuf50));`r`n }`r`n}`r`n/* USER CODE END 4 */" $main = $main -replace 'PLLP_DIV2', 'RCC_PLLP_DIV2' $main | Set-Content -Encoding utf8 $mainFile ``` ## 6. Restore the VS Code workflow only if needed If the reproduction must match the existing debug flow, rebuild the `.vscode` files using the patterns in [DEBUG_SETUP.md](./DEBUG_SETUP.md). ## 7. Validate the reproduction ```powershell cmake --preset Debug cmake --build --preset Debug ``` Required checks: - `BMSv4.ioc` reopens cleanly in CubeMX. - `Core/Src/usart.c` contains the `__io_putchar` user patch. - `Core/Src/main.c` contains the DMA receive-to-idle user patch. - `build/Debug/BMSv4.elf` exists after build.