Estoy tratando de implementar un salto al gestor de arranque STM32F091 USART1 desde mi aplicación.
Estoy usando la siguiente función (basada en https://community.st.com/thread/40238-stm32l476rg-jump-to-bootloader-from-software ):
void SB_SystemBootloaderJump()
{
typedef void (*pFunction)(void);
pFunction JumpToApplication;
HAL_RCC_DeInit();
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
/**
* Step: Disable all interrupts
*/
__disable_irq();
/* ARM Cortex-M Programming Guide to Memory Barrier Instructions.*/
__DSB();
// __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH()
// ;
// /* Remap is bot visible at once. Execute some unrelated command! */
// __DSB();
// __ISB();
JumpToApplication = (void (*)(void)) (*((uint32_t *) ((0x1FFFD800 + 4))));
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) 0x1FFFD800);
JumpToApplication();
}
Desde la nota de la aplicación AN2606: dirección de la memoria del sistema como en la imagen: https://i.imgur.com/nVcgoBg.png
Desde SWD Utility, contenido de la memoria en System Memory: https://i.imgur.com/PeepkrX.png
Desde el depurador, SP y el controlador de reinicio como se muestra en la imagen: https://i.imgur.com/PagQng0.png
Ejecución del programa hasta el punto de interrupción en la dirección del cargador de arranque: https://i.imgur.com/koKfObe.png
Teniendo en cuenta: A - Usando un puente a VCC en el pin BOOT0, puedo acceder con éxito al cargador de arranque del sistema a través de la demostración del cargador flash STM32. No sucede lo mismo si salto al gestor de arranque desde mi aplicación. B - Estoy usando un puente FTDI FT230x USBxSerial.
Preguntas:
1 - Como estoy usando la dirección de memoria absoluta del sistema, no hay necesidad de usar __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH()
. ¿Correcto?
2 - ¿Me estoy perdiendo algo en esta función?
3 - ¿Hay un tiempo de espera entre el inicio del gestor de arranque y la recepción del byte "0x7F" en USART1?
4 - ¿Abrir/cerrar el puerto serie afectará al gestor de arranque? ¿Tengo que restablecer la MCU si cierro el puerto serie y lo abro de nuevo?
El problema estaba en el estado periférico de USART1. Los valores del registro de configuración USART1 se llevaban a la ejecución del cargador de arranque, lo que posiblemente causaba problemas para el cargador de arranque propietario. La solución fue restablecer USART1 a través de RCC_APB2RSTR.
La función ahora es:
void SB_SystemBootloaderJump()
{
typedef void (*pFunction)(void);
pFunction JumpToApplication;
__HAL_RCC_USART1_FORCE_RESET();
HAL_Delay(5);
__HAL_RCC_USART1_RELEASE_RESET();
HAL_Delay(5);
HAL_RCC_DeInit();
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
/**
* Step: Disable all interrupts
*/
__disable_irq();
/* ARM Cortex-M Programming Guide to Memory Barrier Instructions.*/
__DSB();
__HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH()
;
/* Remap is bot visible at once. Execute some unrelated command! */
__DSB();
__ISB();
JumpToApplication = (void (*)(void)) (*((uint32_t *) ((0x1FFFD800 + 4))));
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) 0x1FFFD800);
JumpToApplication();
}
Como estoy usando la dirección de memoria absoluta del sistema, no hay necesidad de usar __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH().
... si su programa definitivamente no accede a la memoria "baja". No olvide reasignar la tabla de interrupciones.
¿Abrir/cerrar el puerto serie afectará al gestor de arranque? ¿Tengo que restablecer la MCU si cierro el puerto serie y lo abro de nuevo?
Si realmente está utilizando los pines USART (no la emulación de serie USB): abrir/cerrar el puerto serie solo debería afectar las líneas de control, no las líneas de datos. En la mayoría de los casos, las líneas de control ni siquiera estarán conectadas a la CPU.
inserte "__enable_irq();" después de su "__ISB();". Debería funcionar bien.
MarcelNubi