8 votos

Las interrupciones de STM32 y C++ no van bien juntas

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 era el problema. Entonces creé un proyecto limpio y copié/pegué sólo el código que configura TIM3 y las interrupciones y mágicamente funcionó. 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 renombré todos mis archivos .c del proyecto a .cpp y también compilé con la directiva --cpp. Todo funcionaba bien, sin problemas hasta que decidí usar interrupciones. Así que renombré todo a .c y todo funcionó, renombré todo de nuevo a cpp y dejó de funcionar.

Utilizo Keil uVision5 y mis proyectos son generados con STM32CubeMX (sólo configuración RCC).

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

5 votos

Es posible que tengas problemas con la vinculación C vs C++ - tu manejador de interrupción probablemente está siendo sometido a la manipulación de nombres de C++, por lo que no está reemplazando el manejador de interrupción débil por defecto que CubeMX proporciona.

0 votos

Acabo de encontrar la solución, y es exactamente lo que has dicho. Es curioso que haya perdido medio día buscando una solución para encontrarla unos minutos después de publicar la pregunta.

0 votos

En realidad, se trata de un problema muy conocido en el ámbito de la incrustación. Me sorprende un poco que los términos de búsqueda elegidos apropiadamente no dieran inmediatamente ninguna de las docenas de enlaces Keil-Fora, TI-fora, StackOverflow, etc. que parece que obtengo cuando lo intento.

10voto

John Puntos 137

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

¿Fallo en el compilador Keil ARM con manejadores de interrupción y C++?

La referencia "débil" sólo significa que la rutina será reemplazada por una rutina en su código con el mismo nombre. Cuando se usa C esto es simple, los nombres siempre serán idénticos, pero el nombre de C++ manipula las funciones (para la sobrecarga de funciones, etc.) por lo que el nombre compilado probablemente no nombre compilado no coincidirá con el nombre por defecto del ISR. Es necesario envolver la función (o al menos una referencia hacia adelante, no estoy seguro de los detalles, ya que la mayoría de las veces trabajo en C) en una envoltura externa "C" para forzar al compilador a no manipular el nombre.

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

O simplemente puedes declararlo como

extern "C" void SysTick_Handler(void);

Así que no tienes que envolverlo.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X