Jump to Bootloader to UART Programming - Timeout error
Hi, I need to create a system for which it is possible to update the firmware remotely.
My system communicates with a serial port (RS422) with a PC, and through this serial I would also like to update the firmware. Obviously without moving the BOOT0 pin, I'm talking about a finished product closed in a case.
What I would like to achieve is that when a specific command is received on the serial port, for example "FUP\r" the MCU goes into a mode where it is possible to update the FW via the serial port.
I tried this code found in various forums that talk about this topic:
void JumpToBootloader (void) {
void (*SysMemBootJump)(void);
volatile uint32_t addr = 0x1FFF0000;
/**
* Step: Disable RCC, set it to default (after reset) settings
* Internal clock, no PLL, etc.
*/
HAL_RCC_DeInit();
HAL_DeInit(); // add by ctien
/* Disable all interrupts */
__disable_irq();
/* Disable Systick timer */
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
__HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH(); //Call HAL macro to do this for you
/* Clear Interrupt Enable Register & Interrupt Pending Register */
for (uint32_t i=0;i<5;i++)
{
NVIC->ICER[i]=0xFFFFFFFF;
NVIC->ICPR[i]=0xFFFFFFFF;
}
/* Re-enable all interrupts */
__enable_irq();
/* Set up the jump to boot loader address + 4 */
SysMemBootJump = (void (*)(void)) (*((uint32_t *)(addr + 4)));
/* Set the main stack pointer to the boot loader stack */
__set_MSP(*(uint32_t *)addr);
/* Call the function to jump to boot loader location */
SysMemBootJump();
}
Then in main loop:
memset(cmdRxBuffer, 0x00, sizeof(cmdRxBuffer));
HALtmp_Status = HAL_UART_Receive(&DATA_INTERFACE, cmdRxBuffer, 4, 100);
if(HALtmp_Status == HAL_OK ) {
printf("Received: %s\r\n", cmdRxBuffer);
if( cmdRxBuffer[0] == 'F' &&
cmdRxBuffer[1] == 'U' &&
cmdRxBuffer[2] == 'P' &&
cmdRxBuffer[3] == '\r') {
printf("Update FW\r\n");
JumpToBootloader();
}
}
Indeed, when the command is received, the MCU enters the memory area 0x1FFFxxxx, so in theory it is in the boot loader zone.
In that situation I tried using STM32CubeProgrammer, but I always get a timeout error if I try to program the FW.
I have several doubts:
1 - Is the code I wrote correct? Do I need to change something?
2 - Is the procedure I use correct? What I do is: I connect with a serial terminal (Realterm) -> I send the command "FUP\r" -> I disconnect the serial terminal to leave the serial port free for the CUbeProgrammer -> Open STM32CubeProgrammer and try to program the MCU.
3 - Are there any constraints on the configuration of the serial port, for example I would like to use DMA in my application, does this conflict with programming via the serial port? Should I use a UART dedicated only to FW updating?
4 - Is there an easier way to do what I need to do?
I'm using a NUCLEO-L432KC board and UART2.
Someone can help me?
