Cargador de arranque e interrupciones STM32F4xx

Estoy tratando de escribir un gestor de arranque para un STM32F4xx (actualmente para la placa de descubrimiento STM32F429). Mi aplicación debería comenzar en la dirección 0x08020000 mientras que el cargador de arranque comienza en 0x08000000 (inicio de flash).

Creé la aplicación con CubeMX, cambié FLASH ORIGIN en el archivo del enlazador a 0x08020000 y VECT_TAB_OFFSET a 0x20000 en el archivo system_stm32f4xx.c (esto cambia el VTOR a 0x08020000). Mi aplicación solo parpadea un LED y funciona como se esperaba en esta nueva dirección cuando se inicia desde el IDE.

while(true) {
    HAL_Delay(200);
    HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_13);
}

En lugar de escribir el cargador de arranque de inmediato (en realidad lo hice y no funcionó), usé la utilidad ST-Link e hice algunas cosas: verifiqué que todo, además de la aplicación, se borrara (0xff). Restablecí la CPU y configuré manualmente la PC en 0x08021924 (este es el Reset_Handler según el archivo de mapa de la aplicación). Cuando paso/ejecuto lentamente la aplicación, puedo ver lo siguiente: El SP está escrito correctamente (ya que es parte del código del ensamblador de inicio de CubeMX). El VTOR está configurado correctamente en 0x08020000 (leí el SCB manualmente en la dirección 0xE000ED00, el tercer valor es el VTOR) y después de un tiempo la aplicación realiza un bucle dentro de la función HAL_GetTick & HAL_Delay (leí la PC y la comparé con el mapa archivo). Incluso veo que la aplicación lee el uwTick (en la dirección 0x20000020 en mi caso), que nunca aumenta y, por lo tanto, HAL_Delay se repite para siempre. entonces mi conclusión es:

Las interrupciones parecen no funcionar correctamente.

en este caso el SysTick... A pesar de un VTOR correcto y la aplicación parece funcionar bien. Cuando reemplazo HAL_Delay con Busy_Delay (que simplemente consiste en un ciclo de millones de NOP), el LED parpadea. Cuando lo inicio manualmente a través del método mencionado (o un cargador de arranque escrito manualmente con saltos a la dirección correcta), la aplicación se ejecuta normalmente (porque es muy probable que nada dependa de las interrupciones en este breve ejemplo).

¿Qué me falta para escribir un cargador de arranque que funcione (con interrupciones que funcionen)?

¿ Has intentado buscar en el foro STM32 ? No estoy seguro, pero creo que se han hecho y respondido preguntas similares varias veces.
Tienes razón, el foro está lleno de este tipo de preguntas, pero muchas de ellas sin respuesta y no he podido encontrar una solución a mi problema particular hasta el momento, o algunas personas tienen problemas similares y lo eluden.

Respuestas (1)

Creo que yo mismo encontré un eslabón perdido.

En lugar de saltar al Reset_Handler en sí, saltar al Reset_Handler + 1 ayuda. Esto establece el LSB en 1 y da una indicación de que es un código de pulgar. Para los controladores de IRQ, está documentado en el Centro de información de ARM .

La mayoría (si no todos) los saltos en el código generado desde C tienen un LSB 0 de cero (y las interrupciones aún funcionan), no entiendo completamente por qué es necesario configurar el LSB en mi caso. Quizás: normalmente los saltos son relativos (pero dentro del depurador se traducen en direcciones con un LSB de 0), pero el salto al cargador de arranque es una dirección que se carga primero con un registro y luego salta también.