I’m using FreeRTOS Kernel V11.1.0
Cortex-M4 ATSAM microcontroller
I have a bootloader that runs FreeRTOS. My main application also runs FreeRTOS.
I have one task that performs ota update and another task that monitors update process. If no update is happening it jumps to main app after a few seconds.
The issue is that without performing any update the timer expires the bootloader tries to jump to main application and it hangs.
I randomly change the size of some buffer arrays and the issue dissapears.
I’m not confident of what is going on.
I have used very similar code in bootloader without FreeRTOS and I didn’t have any issues.
I tried to disable interrupts before jump. No success.
If I call jump before scheduler starts it works fine.
One key thing to remember when writing a boot loader, is that you need to be sure you have put the processor back into the state the loaded program is expecting.
Particularly with FreeRTOS, that means that interrupts should be disabled when you go to the application, and something needs to be handling the change of the location of the interrupt vectors from the boot loader to the application.
Remember starting the schedule changed the system state by enabling interrupts, and you need to undo that when you go to the application.
I’m not sure about this.
I have a linker script from another project. That uses the same microcontroller.
And I build the project using that linker script.
That project works fine with bootloader (without freertos)
when the bootloader passes control to the application, very likely the interrupt handlers of the application are not the same as those for the bootloader, so before jumping to the application, you need to rebase the ivt to one that contains the correct absolute addresses of your apps interrupt handlers. This has been discussed on this forum many times before, just query the forum for bootloader.
void jump_to_main_app(void)
{
pmc_disable_all_periph_clk();
__disable_irq();
NVIC->ICER[0] = 0xFFFFFFFF; // Disable all IRQs in NVIC
NVIC->ICPR[0] = 0xFFFFFFFF; // Clear pending IRQs
uint32_t main_stack_pointer = *(volatile uint32_t*)MAIN_APP_ADDRESS;
void (*main_app_entry)(void) = (void (*)(void))(*(volatile uint32_t*)(MAIN_APP_ADDRESS + 4));
// Set the vector table to the main application
SCB->VTOR = MAIN_APP_ADDRESS;
__DSB(); // Data Synchronization Barrier
__ISB(); // Instruction Synchronization Barrier
// Set the main stack pointer
__set_MSP(main_stack_pointer);
// Set the program counter to the application start address
// just for remainder: Vector table's second entry is the system reset value
main_app_entry();
while(true);
}
This worked for me in similar circumstances:
Setting a unique code in the RAM and restart MCU.
When waking, redirect the code according to RAM content.
Use __no_init