Las interrupciones de STM32 y C++ no van bien juntas [duplicar]

Configuré TIM3 para disparar una interrupción en mi proyecto y simplemente no funcionó. Intenté todo lo que pude y todavía no pude encontrar cuál es el problema. Luego creé un proyecto limpio y copié/pegué solo el código que configura TIM3 e interrumpe y funcionó mágicamente. Literalmente perdí medio día tratando de encontrar la causa del problema y resulta que... a las interrupciones no les gusta C++.

Escribí mi código en C++ porque necesitaba clases en mi proyecto, así que, naturalmente, cambié el nombre de todos mis archivos prject .c a .cpp y también compilé con la directiva --cpp. Todo funcionó bien, sin problemas hasta ahora hasta que decidí usar interrupciones. Así que cambié el nombre de todo a .c y todo funcionó, cambié el nombre de todo a cpp y dejó de funcionar.

Uso Keil uVision5 y mis proyectos se generan con STM32CubeMX (solo configuración RCC).

¿A alguien le ha pasado esto? ¿Alguna solución?

Es posible que tenga problemas con la vinculación entre C y C++: su controlador de interrupciones probablemente esté sujeto a la manipulación de nombres de C++, por lo que no está reemplazando el controlador de interrupciones débil predeterminado que proporciona CubeMX.
Acabo de encontrar la solución, y es exactamente lo que dijiste. Es curioso cómo perdí medio día buscando una solución solo para encontrarla unos minutos después de publicar la pregunta.
En realidad, este es un problema muy conocido en Embedded. Me sorprende un poco que los términos de búsqueda elegidos apropiadamente no dieron de inmediato ninguna de las docenas de enlaces de Keil-Fora, TI-fora, StackOverflow, etc. que parezco obtener cuando lo intento.

Respuestas (1)

Estuve buscando una solución durante medio día, solo para encontrarla unos minutos después de publicar esta pregunta. La respuesta la da este post:

¿Error en el compilador Keil ARM con controladores de interrupción y C++?

La referencia "débil" solo significa que la rutina será reemplazada por una rutina en su código del mismo nombre. Cuando se usa C, esto es simple, los nombres siempre serán idénticos, pero el nombre de C ++ altera las funciones (para la sobrecarga de funciones, etc.), por lo que el nombre compilado probablemente no coincida con el nombre ISR predeterminado. Debe envolver la función (o al menos una referencia directa, no estoy seguro de los detalles que trabajo principalmente en C) en un envoltorio "C" externo para obligar al compilador a no alterar el nombre.

extern "C" { void SysTick_Handler(void) { // hacer lo que sea } }

O simplemente puede declararlo como

extern "C" void SysTick_Handler(void);

Así que no tienes que envolverlo.