6.4 KiB
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
<workspace>/reproduction
1. Verify tools
Use explicit local paths for CubeMX and fail early if they do not exist.
$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.
$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.
$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.
@'
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.
$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.
7. Validate the reproduction
cmake --preset Debug
cmake --build --preset Debug
Required checks:
BMSv4.iocreopens cleanly in CubeMX.Core/Src/usart.ccontains the__io_putcharuser patch.Core/Src/main.ccontains the DMA receive-to-idle user patch.build/Debug/BMSv4.elfexists after build.