Files
skills-win/cubemx-min-prj/REPRODUCTION_GUIDE.md
T

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.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.