Estoy tratando de hacerlo para que mi STM32L011 pueda saltar del código de usuario al cargador de arranque ST que permite reprogramar el flash a través de USART2. Esta es hipotéticamente la misma pregunta que STM32F091 Jump to Bootloader from application , pero no estoy teniendo suerte con las correcciones de desactivación de periféricos de esa pregunta. ST rehizo sus foros y rompió todos los enlaces antiguos a los hilos, por lo que me está costando mucho encontrar pistas sobre otros posibles problemas y estoy bastante perplejo en cuanto a dónde buscar a continuación.
Mi función de salto es la siguiente (modificada de la pregunta anterior para mi aplicación y usando las bibliotecas ST LL). El código de mi aplicación usa LPUART en PA2/PA3, que luego debería poder usar USART2 para el gestor de arranque. Se recibe un comando en el LPUART en el código de la aplicación del usuario, que llama a la función de salto. El código de la aplicación reconoce el comando correctamente según mi protocolo serial, pero luego el cargador de arranque USART no responde a ninguna utilidad intermitente. Envían el byte inicial 0x7F por AN2606 pero el cargador de arranque no devuelve el ACK.
#define STM32L01_SYSTEM_MEMORY 0x1FF00000
void jump_to_bootloader()
{
// Disable global interrupts
__disable_irq();
// Disable interrupt requests from peripherals
NVIC_DisableIRQ(SysTick_IRQn);
NVIC_DisableIRQ(LPUART1_IRQn);
NVIC_DisableIRQ(EXTI0_1_IRQn);
NVIC_DisableIRQ(DMA1_Channel2_3_IRQn);
NVIC_DisableIRQ(I2C1_IRQn);
typedef void (*pFunction)(void);
volatile uint32_t addr = STM32L01_SYSTEM_MEMORY;
uint32_t jumpaddr = *(__IO uint32_t*) (STM32L01_SYSTEM_MEMORY + 4);
pFunction jump_to_application;
// Application-specific shutdown of HSE and switch to MSI
clock_HSE_to_MSI();
// Reset ALL peripherals
LL_AHB1_GRP1_ForceReset(LL_AHB1_GRP1_PERIPH_ALL);
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_ALL);
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_ALL);
LL_mDelay(5);
LL_AHB1_GRP1_ReleaseReset(LL_AHB1_GRP1_PERIPH_ALL);
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_ALL);
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_ALL);
LL_mDelay(5);
// Fully reset RCC to power-up state
LL_RCC_DeInit();
// Zero out SysTick
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
// Remap memory to system flash
SYSCFG->CFGR1 = 0x01;
jump_to_application = (pFunction)jumpaddr;
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) addr);
jump_to_application();
}
He descartado estos problemas:
Teorías de trabajo:
Antes de __set_MSP():
Después de llegar al final de la función de salto (los botones de paso del depurador ya no están habilitados):
Si luego hago clic en suspender la ejecución en el depurador, me devuelve a un punto de interrupción generado por Eclipse al comienzo de main(). No entiendo cómo podría ser este el caso, ya que el código de mi aplicación ya no funciona correctamente, con y sin el depurador presente.
Podría intentar saltar a 0x1FF00FFE en lugar de 0x1FF00000. (dirección del gestor de arranque integrado según AN2606 Rev 35, p 26)
Mi comentario inicial estaba completamente equivocado. Pero de acuerdo con los comentarios anteriores, el iniciador del tema encontró lo que estaba mal. Debido al mecanismo de verificación vacío presentado en el dispositivo L011, no puede saltar a la memoria del sistema desde el código de usuario y permanecer allí. Encontré problemas similares en mi dispositivo L07x con mecanismo de banca dual (problema similar https://stackoverflow.com/questions/42020893/stm32l073rz-rev-z-iap-jump-to-bootloader-system-memory ). Resultó que el cargador de arranque vuelve al código de usuario sin importar qué, siempre que haya un código válido en uno de los bancos. Por supuesto, es posible omitirlo saltando a la dirección después del cheque vacío, pero es difícil encontrar la dirección correcta y no hay garantía de que STM no cambie esa dirección en la próxima impresión del chip.
chris stratton
usuario72833
filo
joe panadero
Deván