cancel
Showing results for 
Search instead for 
Did you mean: 

Bootloader with FreeRTOS

mmercan
Associate II

Dear friends

I am trying to develop a bootloader with STM32F469BIT mcu. First of all, I divided the 2048K flash area allocated to me into zones according to certain sector addresses. These areas;

Bootloader -> FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 32K App1 -> FLASH (rx) : ORIGIN = 0x08008000, LENGTH = 1008K App2 -> FLASH (rx) : ORIGIN = 0x08104000, LENGTH = 1008K

After separating these areas;

App1 -> #define VECT_TAB_OFFSET 0x00008000U App2 -> #define VECT_TAB_OFFSET 0x00104000U

I have a task in the bootloader and I control a button with an EXTI in this task. I specify that the jump operation will be performed when the button is pressed. 

typedef StaticTask_t osStaticThreadDef_t; typedef void (*pFunction)(void); #define APP1_ADDRESS ((uint32_t)0x08008000) #define NVIC_IRQ_COUNT 240 #define BASEPRI_MASK ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << \ (8 - configPRIO_BITS) ) extern TIM_HandleTypeDef htim6; extern TIM_HandleTypeDef htim2; static void prvSafeGPIODeInit(void) { GPIO_InitTypeDef init = { 0 }; const uint32_t keepA = GPIO_PIN_13 | GPIO_PIN_14; /* SWD */ HAL_GPIO_DeInit(GPIOA, ~keepA); HAL_GPIO_DeInit(GPIOB, GPIO_PIN_All); HAL_GPIO_DeInit(GPIOC, GPIO_PIN_All); HAL_GPIO_DeInit(GPIOD, GPIO_PIN_All); HAL_GPIO_DeInit(GPIOE, GPIO_PIN_All); HAL_GPIO_DeInit(GPIOF, GPIO_PIN_All); HAL_GPIO_DeInit(GPIOG, GPIO_PIN_All); HAL_GPIO_DeInit(GPIOH, GPIO_PIN_All); HAL_GPIO_DeInit(GPIOI, GPIO_PIN_All); HAL_GPIO_DeInit(GPIOJ, GPIO_PIN_All); HAL_GPIO_DeInit(GPIOK, GPIO_PIN_All); init.Pin = keepA; init.Mode = GPIO_MODE_AF_PP; init.Pull = GPIO_NOPULL; init.Speed = GPIO_SPEED_FREQ_VERY_HIGH; init.Alternate = GPIO_AF0_SWJ; HAL_GPIO_Init(GPIOA, &init); } static void prvNVIC_Reset(void) { for (uint32_t i = 0; i < NVIC_IRQ_COUNT; ++i) { NVIC_DisableIRQ((IRQn_Type) i); NVIC_ClearPendingIRQ((IRQn_Type) i); } } static void prvPeriph_DeInit(void) { HAL_TIM_Base_DeInit(&htim6); HAL_TIM_Base_DeInit(&htim2); } static void prvBoot_DeInit(void) { __disable_irq(); __set_BASEPRI(0xf0); SysTick->CTRL = 0; SysTick->LOAD = 0; SysTick->VAL = 0; prvSafeGPIODeInit(); prvNVIC_Reset(); prvPeriph_DeInit(); HAL_RCC_DeInit(); HAL_DeInit(); } static void prvJumpToApp(uint32_t appAddr) { uint32_t newSP = *(uint32_t*)appAddr; pFunction entry = (pFunction)*(uint32_t*)(appAddr + 4); prvBoot_DeInit(); SCB->VTOR = appAddr; __DSB(); __ISB(); __set_MSP(newSP); __enable_irq(); entry(); while (1) { __NOP(); } } void StartupEntry(void *argument) { /* USER CODE BEGIN StartupEntry */ /* Infinite loop */ (void) argument; for (;;) { HAL_GPIO_TogglePin(BM83_EN_GPIO_Port, BM83_EN_Pin); if (HAL_GPIO_ReadPin(ENC2_SW_GPIO_Port, ENC2_SW_Pin) == GPIO_PIN_SET) { prvJumpToApp(APP1_ADDRESS); } osDelay(20); } /* USER CODE END StartupEntry */ }
View more

After jumping, the software in the app does not work. I see that the jump was done successfully, but no task is running on the application it jumped to. When I examine the flash areas through the created .elf file, I get an output like below. Boot .isr_vector is:

Section: .isr_vector Region: FLASH Address: 0x08000000 Size: 436 00 00 05 20 25 16 00 08 7D 14 00 08 85 14 00 08 8D 14 00 08 95 14 00 08 9D 14 00 08 00 00 00 00 ...

App1 .isr_vector is:

Section: .isr_vector Region: FLASH Address: 0x08008000 Size: 436 00 00 05 20 B5 C7 00 08 CD B7 00 08 D5 B7 00 08 DD B7 00 08 E5 B7 00 08 ED B7 00 08 00 00 00 00 00 ...

After the jumping process i cannot see any reaction in my tasks. What are the places that I should pay attention to and not examine? If there is a wrong operation, can you also help me fix it?

Thanks for your attention and help.

5 REPLIES 5
TDK
Guru

Are you doing the jump within an interrupt?

> After jumping, the software in the app does not work.

What does "does not work" mean in particular? Do something simple. Blink an LED at 1 Hz.

If you feel a post has answered your question, please click "Accept as Solution".
mmercan
Associate II

There are 4 tasks in the application where I do the jump operation and I am doing a simple toggle operation here. I run a simple blink code in the StartupEntry task;

void StartupEntry(void *argument) { /* init code for USB_DEVICE */ MX_USB_DEVICE_Init(); /* USER CODE BEGIN StartupEntry */ ui_init(ui_updatesHandle); for (;;) { HAL_GPIO_TogglePin(BM83_EN_GPIO_Port, BM83_EN_Pin); osDelay(1); } /* USER CODE END StartupEntry */ }

The jump can't be done from an interrupt (tasks in FreeRTOS are run from an interrupt). When you do so, the bootloader is now running from an interrupt which means other interrupts may not happen.

 

Instead, set a magic value in your program which is untouched during loading and check it before starting the RTOS. If it's set, jump to bootloader.

If you feel a post has answered your question, please click "Accept as Solution".
mmercan
Associate II

Boot to Jump app operation is not in an interrupt. There is only one button event read operation. When this button value is set, jump operation is done.

 

I also did a skip operation within a delay, but again the operations that should have been done on the app side were not started.

mmercan
Associate II

Guys I found the problem that occurs when booting. The solution is as follows;

After loading the correct stack to MSP with __set_MSP, you need to switch Thread Mode to MSP with __set_CONTROL(0). Then you need to open interrupts with __enable_irq() and jump to appEntry() which is called like (Reset Handler) function.

The code is below:

static void prvJumpToApp(uint32_t appAddr) { uint32_t newSP = *(uint32_t*)appAddr; pFunction entry = (pFunction)*(uint32_t*)(appAddr + 4); prvBoot_DeInit(); SCB->VTOR = appAddr; __DSB(); __ISB(); __set_MSP(newSP); __set_CONTROL(0); __DSB(); __ISB(); __enable_irq(); entry(); while (1) { __NOP(); } }

 After __set_CONTROL(0) your program will works correctly.