Firmware STM32 (CubeMX/HAL + PlatformIO, ST-Link)
Cargue también embedded-c-cpp para estándares de codificación, arquitectura, pruebas unitarias y depuración general. Esta habilidad contiene las partes específicas de STM32.
Primero, identifique el proyecto
Lea el repositorio antes de escribir código. Estos hechos cambian la respuesta:
| Encontrar | Dónde |
|---|---|
| Parte exacta (ej. STM32G431KBT6) y familia (F0/F1/F4/G0/G4/L4/H7/U5...) | .ioc (Mcu.UserName), platformio.ini board =, nombre del archivo de inicio |
| Tipo de proyecto | .ioc + .project/.cproject → CubeIDE; .ioc + CMakeLists.txt/CMakePresets.json → CubeMX CMake; platformio.ini → PlatformIO |
| HAL vs LL vs registros | Drivers/STM32xx_HAL_Driver, #include "stm32xx_ll_*.h", "Advanced settings" de CubeMX por periférico |
| RTOS | Middlewares/Third_Party/FreeRTOS, cmsis_os.h |
| Clocks | SystemClock_Config() en main.c, sección RCC del .ioc; las placas Nucleo suelen alimentar HSE 8 MHz desde el ST-Link (HSE bypass) |
| Sonda | ST-Link (integrada en Nucleo/Discovery, o ST-Link V2/V3 independiente) |
La familia importa mucho: núcleos (M0+/M3/M4F/M7/M33), FPU o no, granularidad de escritura flash (half-word en F1, double-word en G4/L4, flash-word en H7), DMA (DMAMUX en G0/G4/L4+/H7), cachés (F7/H7). Cuando no esté seguro de un registro o detalle de periférico, indique qué verificar en el manual de referencia (RM) en lugar de adivinar.
Las reglas de CubeMX que evitan pérdida de trabajo
CubeMX regenera main.c, stm32xx_it.c, stm32xx_hal_msp.c y los archivos de inicialización cada vez. Solo sobrevive el texto entre /* USER CODE BEGIN x */ y /* USER CODE END x */.
- Coloque la lógica de aplicación en sus propios archivos (
App/app.c,App/app.h, oapp.cpppara C++) y llame aapp_init()/app_loop()desdeUSER CODE BEGIN 2y el bloque USER CODE dentro dewhile (1). - Cambie pines, clocks, DMA, interrupciones y parámetros de periféricos en el
.ioc, luego regenere — no editandoMX_xxx_Init()(se sobrescribe, y el.iocdeja de coincidir con el código). - Haga commit del archivo
.ioc. Es la fuente de verdad para la configuración del hardware. - Active "Generate peripheral initialization as a pair of .c/.h files per peripheral" en Project Manager → Code Generator:
main.cmás pequeño, diffs más limpios. - Detalles e integración C++:
references/cubemx-hal.md.
Compilación, flasheo, depuración
Elija la ruta que coincida con el proyecto; comandos completos en references/build-flash-debug.md.
| Proyecto | Compilar | Flashear (ST-Link) | Depurar |
|---|---|---|---|
| CubeIDE | IDE, o headless stm32cubeide ... -build | IDE, o STM32_Programmer_CLI -c port=SWD -w app.elf -v -rst | Depurador de CubeIDE (servidor GDB ST-LINK) |
| CubeMX CMake (VS Code) | cmake --preset Debug && cmake --build --preset Debug | STM32_Programmer_CLI o OpenOCD | Extensión STM32 de VS Code / OpenOCD + GDB |
| PlatformIO | pio run -e <env> | pio run -e <env> -t upload (upload_protocol = stlink) | pio debug / VS Code (debug_tool = stlink) |
Flashear cambia la placa: confirme con el usuario qué placa/sonda está conectada antes de ejecutar una subida, y nunca ejecute borrado masivo, option bytes o comandos de protección de lectura sin confirmación explícita (RDP nivel 2 es permanente).
Uso de HAL — los errores que más tiempo cuestan
- Direcciones I2C se pasan desplazadas a la izquierda:
HAL_I2C_Master_Transmit(&hi2c1, 0x76 << 1, ...). - Los callbacks de HAL se ejecutan en contexto de interrupción (
HAL_UART_RxCpltCallback,HAL_GPIO_EXTI_Callback,HAL_TIM_PeriodElapsedCallback): manténgalos cortos, sinHAL_Delay, sin transmisiones bloqueantes. HAL_Delay/HAL_GetTicknecesitan SysTick: llamarlos desde una ISR de mayor prioridad o con interrupciones deshabilitadas cuelga el sistema. Con FreeRTOS, configure SYS → Timebase Source a un temporizador básico (TIM6/TIM7) en CubeMX.- Recepción UART: use
HAL_UARTEx_ReceiveToIdle_DMA(tramas de longitud variable) o modo interrupción con un buffer circular; reinicie la recepción en el callback y enHAL_UART_ErrorCallback(un overrun detiene la recepción silenciosamente). - Buffers DMA en F7/H7 (caché de datos): limpiar antes de TX, invalidar después de RX, alineados y de tamaño múltiplo de 32 bytes; en H7, DMA1/2 no pueden acceder a DTCM RAM — coloque los buffers en D2/AXI SRAM.
- Verifique el valor de retorno de cada llamada HAL (
HAL_OK,HAL_ERROR,HAL_BUSY,HAL_TIMEOUT); unHAL_BUSYgeneralmente significa que una transferencia anterior nunca terminó. - Timeouts: nunca use
HAL_MAX_DELAYen rutas de producción. - Más patrones (UART DMA, ADC DMA, timers/PWM, EXTI, bajo consumo, escrituras flash, watchdog, causa de reset):
references/cubemx-hal.md.
Cuando se cuelga o no arranca
- HardFault / MemManage / BusFault / UsageFault →
references/faults-and-recovery.md(leer CFSR/HFSR, PC apilado, decodificar conaddr2line). - ST-Link no puede conectar ("No target found", "DEV_TARGET_HELD_UNDER_RESET") → conectar bajo reset; verificar que los pines SWD no se hayan reconfigurado como GPIO en el
.ioc; BOOT0; nivel RDP →references/faults-and-recovery.md. - Cuelgue en
SystemClock_Config→ HSE no presente/discrepancia de bypass, PLL incorrecto, latencia flash demasiado baja. - Periférico silencioso → ¿reloj habilitado? ¿AF de pin correcto? ¿
MX_xxx_Initrealmente llamado y en el orden correcto (inicializar DMA antes que el periférico que lo usa)?
Archivos de referencia
| Archivo | Leer cuando |
|---|---|
references/cubemx-hal.md | Escribir/revisar código en un proyecto CubeMX, integración C++, patrones de periféricos, bajo consumo, emulación flash/EEPROM, watchdog, causa de reset |
references/build-flash-debug.md | Instalación de toolchain, compilación desde CLI, configuración de PlatformIO para STM32, flasheo, GDB/OpenOCD, registro printf/SWV, análisis de tamaño |
references/faults-and-recovery.md | HardFault y otras fallas, la placa no conecta, option bytes y protección de lectura, recuperación de una placa que parece bricked |