cancel
Showing results for 
Search instead for 
Did you mean: 

bootloader to FreeRTOS on stm32f0x

retroll
Associate II

Hi, I'm trying to jump to a FreeRTOS app via a bootloader that i made. I'm pretty new to this. I know there is a lot of similar topic on the internet but none of them fixed my problem. When I try to jump to my FreeRTOS app with my bootloader, nothing happens.

Here is the function i'm using to jump.

void jumpToEntry(void)
{       
   const JumpStruct* vector_p = (JumpStruct*)A_MAIN_IMAGE_ADDR;
   deinitEverything();
   asm("msr msp, %0; bx %1;" : : "r"(vector_p->stack_addr), "r"(vector_p->func_p));
}
void deinitEverything()
{
  HAL_UART_DeInit(&huart2);
  HAL_RCC_DeInit();
  HAL_DeInit();
  SysTick->CTRL = 0;
  SysTick->LOAD = 0;
  SysTick->VAL = 0;
}

Before jumping on a FreeRTOS application, I did my tests to jump on  a simple blinky and it has a super weird behaviour.

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_USART2_UART_Init();

  while (1)
  {
    HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
    char c[10];
    sprintf(c, "tick: %ld\r\n",HAL_GetTick());
    HAL_Delay(1000);
  }
}

The only way to make this simple blinky to work was to had the 2 lines where I put the result of HAL_GetTick() in a random char array that I don't even use. If I just toggle pin and delay, the code seems to crash on the HAL_Delay.

I must precise that my blinky and my FreeRTOS are working fine if I flash them at the beginning of the flash (0x000800 0000). The problem must be something that I miss in the process of making a bootloader with a stm32f030R8.

Here is the code of my FreeRTOS code. I saw in a lot of guide that the vector table must be remapped, but with the cortex m0 it seems that i can't use SCB->VTOR . So I try to use a method I saw on this forum earlier. I'm not even sure it works in my case. I saw another method directly on the arm official website but it doesn't even compile (the commented part in the Remap_Table function).

volatile uint32_t VectorTable[48] __attribute__((section(".RAMVectorTable")));

void Remap_Table(void)
{
  // uint32_t *vector_table = (uint32_t *)&_stext;
  // uint32_t *vtor = (uint32_t *)0xE000ED08;
  // *vtor = ((uint32_t)vector_table & 0xFFFFFFF8);

  uint32_t i = 0;
  for (i = 0; i < 48; i++)
  {
    VectorTable[i] = *(__IO uint32_t *)(0x08004070 + (i << 2));
  }
  __HAL_RCC_SYSCFG_CLK_ENABLE();
  __HAL_SYSCFG_REMAPMEMORY_SRAM();
}

/**
 * @brief  Retargets the C library printf function to the USART.
 * @PAram  None
 * @retval None
 */
int __io_putchar(int ch)
{
  /* Place your implementation of fputc here */
  /* e.g. write a character to the USART1 and Loop until the end of transmission */
  HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, 0xFFFF);

  return ch;
}

/**
 * @brief  Function implementing the defaultTask thread.
 * @PAram  argument: Not used
 * @retval None
 */
void StartDefaultTask(void *argument)
{
  /* Infinite loop */
  for (;;)
  {
    printf("blinkzer \r\n");
    HAL_GPIO_TogglePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin);
    osDelay(500);
  }
}

/**
 * @brief  The application entry point.
 * @retval int
 */
int main(void)
{

  /* MCU Configuration--------------------------------------------------------*/
  Remap_Table();
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
  /* Configure the system clock */
  SystemClock_Config();

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART2_UART_Init();
  printf("before os init\r\n");

  /* Init scheduler */
  osKernelInitialize();

  printf("before task\r\n");

  /* creation of defaultTask */
  defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);

  /* Start scheduler */
  osKernelStart();
  /* We should never get here as control is now taken by the scheduler */
  /* Infinite loop */
  while (1)
  {
  }
}

My defaulTask is also a blinky and I added a reimplementation of io_putchar to use the printf and see it through a console like minicom.

I suspect the crash due to misinitialization of a clock or that interrupts are not managed correctly. The code may crash at  the systemclock_config of my FreeRTOS app because I can't see any printf i my console so it must be a problem before usart init. And the generated System_clock config is not the same in my bootloader/blinky and my freeRTOS app. To precise my method, I followed a step by step tutorial made by ST in this video:

https://www.youtube.com/watch?v=lood3ehvGJ4

Thank you if anyone wants to help me. I apologize if the answer has already been given in any topic here that I would've missed. Also I may have done some dumb mistake since I'm only a beginner with RTOS and bootloader creation.

8 REPLIES 8
gbm
Lead III

1. sprintf() in your example uses 10-byte buffer which is enough only for single-digit numbers,

2. HAL uses SysTick (or other timer) interrupt. All the interrupts must be disabled while switching from the bootloader to your app.

Pavel A.
Evangelist III

Ah so this is STM32F0.

This is Cortex-M0 and its interrupt vectors table is always at fixed address 0.

STM32F0 has a special magic that allows to remap address 0 to the internal flash 0x08000000 (by default) or to RAM. So the systick interrupt handler of your app still jumps to the vector table of your bootloader.

One option to fix this is to remap address 0 to the RAM and copy the app vector table to start of the RAM. This has been described in this forum many times. 

Newer STM32s are based on Cortex-M0+, they have the VTOR register like CM3 and better.

Thank you, disable irq was part of my problem. Now my FreeRTOS at least initialize. Still crash but initialize, I have to investigate this problem of vector table remapping.

STM32F0 has a special magic that allows to remap address 0 to the internal flash 0x08000000 (by default) or to RAM. So the systick interrupt handler of your app still jumps to the vector table of your bootloader.

One option to fix this is to remap address 0 to the RAM and copy the app vector table to start of the RAM. This has been described in this forum many times. 


isn't it what I do in this snippet ?

void Remap_Table(void)
{
  uint32_t i = 0;
  for (i = 0; i < 48; i++)
  {
    VectorTable[i] = *(__IO uint32_t *)(0x08004070 + (i << 2));
  }
  __HAL_RCC_SYSCFG_CLK_ENABLE();
  __HAL_SYSCFG_REMAPMEMORY_SRAM();
}

I got it from one of many post in this forum. But it seems that it's not doing what it's suppose to do, because after disabling irq as another answer suggested, my FreeRTOS now  initialize but the task is still not running.

 

Pavel A.
Evangelist III

Yes. Sorry. I've missed this part ((

Where is the section(".RAMVectorTable"), how do you ensure it is at start of SRAM?

I've added a section in the linker script. it's the first section declared in the RAM, I assume it is at its beggining.

...  

.init_array :
  {
    . = ALIGN(4);
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array*))
    PROVIDE_HIDDEN (__init_array_end = .);
    . = ALIGN(4);
  } >FLASH

  .fini_array :
  {
    . = ALIGN(4);
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(SORT(.fini_array.*)))
    KEEP (*(.fini_array*))
    PROVIDE_HIDDEN (__fini_array_end = .);
    . = ALIGN(4);
  } >FLASH

  .RAMVectorTable :
  {
    *(.RAMVectorTable)
  } >RAM

  /* Used by the startup to initialize data */
  _sidata = LOADADDR(.data);

  /* Initialized data sections into "RAM" Ram type memory */
  .data :
  {
    . = ALIGN(4);
    _sdata = .;        /* create a global symbol at data start */
    *(.data)           /* .data sections */
    *(.data*)          /* .data* sections */
    *(.RamFunc)        /* .RamFunc sections */
    *(.RamFunc*)       /* .RamFunc* sections */

    . = ALIGN(4);
    _edata = .;        /* define a global symbol at data end */

  } >RAM AT> FLASH
...

 It's here in the autogenerated linker srcipt.

retroll
Associate II

Update, I changed my board to a stm32f410RB, with hope that if I use a different method to remap the vector table, my application would work correctly. it appears that nothing changed. Here is my new jump function:

typedef void (*pFunction)(void);
void jumpToEntry()
{
        deinitEverything();
        SCB->VTOR = A_MAIN_IMAGE_ADDR;
        __set_MSP(*(volatile uint32_t *)A_MAIN_IMAGE_ADDR);
        pFunction appEntry;
        appEntry = (pFunction)(*(volatile uint32_t *)(A_MAIN_IMAGE_ADDR + 4));
        appEntry();
}

 

My blinky app still doesn't blink and crash on the HAL_Delay. And the HAL_GetTick() function returns 0. Here is the while of my blinker app.

  while (1)
  {
    HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
    Debug_Print("blink1\r\n");
    char c[50];
    sprintf(c, "%ld\r\n", HAL_GetTick());
    Debug_Print(c);
    HAL_Delay(1000);
  }

 My FreeRTOS app still does nothing, it seems that the program crash somewhere at the scheduler start. But the default task never start. I precise that all these application when I  change their linker script and programm them at the beginning of the flash (0x08000000) are working perfectly. I must miss something important when I jump to make everything working fine.

Pavel A.
Evangelist III

Yes , looks like something else is broken, that is not shown in your posts.