I working on my first ChibiOS project. First I want to make a very simple bootloader. Writing something over serial and jumping to main.
I'm working with a Nucleo F411RE and F446RE now for over 2 years with bare metal.
So I started with HAL and made a bootloader. Jump to my bare metal firmware. Everything seems to work.
Next step bootloader HAL jumping to HAL. But I had issues.
Looks like the main application start to hang.
So first I thought, that the problem is with the main app. Starting this app without bootloader at 0x8000000 works fine.
Making an app with NIL is also working as standalone. But jumping from bootloader makes always issues. After flashing all of them are working.
So now I start to think it's not the main app, it's the bootloader. And... BINGO.
My bootloader makes always problems, or only, when using a xxxSleepxxx(). So reading some other stuff, also some guidance to shutdown the RT I found my problem with the SysTick. So what kind of pitfalls could I miss also?
So currently my bootloader looks like this:
Code: Select all
#include <stdbool.h>
#include "hal.h"
typedef void (*pFunction)(void);
pFunction Jump_To_Application;
uint32_t JumpAddress;
#define APP_OFFSET 0x4000
#define NVIC_VectTab_FLASH 0x08000000
#define APP_ADDRESS (NVIC_VectTab_FLASH | APP_OFFSET)
/*
* Application entry point.
*/
int main(void) {
static const SerialConfig uart_cfg =
{
38400,
0,
USART_CR2_STOP1_BITS,
0
};
halInit();
osalSysEnable();
sdStart(&SD2, &uart_cfg);
palSetPadMode(GPIOA, 2, PAL_MODE_ALTERNATE(7));
palSetPadMode(GPIOA, 3, PAL_MODE_ALTERNATE(7));
palSetPadMode(GPIOC, GPIOC_BUTTON, PAL_MODE_INPUT);
palSetPadMode(GPIOA, GPIOA_LED_GREEN, PAL_MODE_OUTPUT_PUSHPULL);
sdWrite(&SD2, (uint8_t *)"\r\nLet's jump!\r\n", 15);
// while pressing the user button on the nucleo, we could later add
// some flashing stuff or so.
while (!palReadPad(GPIOC, GPIOC_BUTTON)) {
static uint8_t counter = 0;
counter++;
palTogglePad(GPIOA, GPIOA_LED_GREEN);
osalThreadSleepMilliseconds(1000/(counter + 1));
if (counter > 9) counter = 0;
sdPut(&SD2, '0'+counter);
sdWrite(&SD2, (uint8_t *)"\r\n", 2);
}
JumpAddress = *(__IO uint32_t *)(APP_ADDRESS + 4);
Jump_To_Application = (pFunction)JumpAddress;
sdStop(&SD2);
osalSysDisable();
/* Clear pending interrupts just to be on the safe side */
SCB->ICSR = SCB_ICSR_PENDSVCLR_Msk;
/* Disable the SysTick */
SysTick->CTRL = 0;
/* Disable all interrupts */
for(uint8_t i=0; i<8; i++)
NVIC->ICER[i] = NVIC->IABR[i];
SCB->VTOR = APP_ADDRESS;
__set_MSP(*(__IO uint32_t *)APP_ADDRESS);
Jump_To_Application();
while (true)
{
};
}
Disabling the SysTick is from me. The pendSV handler and disabling other interrupts is copied from another bootloader:
https://github.com/fpoussin/ChibiOS-Boo ... .c#L22-L27
But when comment out the pendSV and disabling all interrupts, my program still works. So when do I need to disable all these things? Do I?