Skip to main content
Kpodu.1
Associate III
February 21, 2020
Solved

STM32F4 bootloader jump to user application failing when using RTOS or TouchGFX

  • February 21, 2020
  • 4 replies
  • 1854 views

Hi All,

I am working on a bootloader for STM32F429ZIT6. And for the project we are using Touch GFX and FreeRTOS.

The problem I have currently is:

  1. If I create a regular project without touchgfx code or free rtos code in it. I can properly jump from bootloader to user application.
  2. But If I create a project with either TouchGFX or FreeRTOS The jump is failing from bootloader. But I can run this project using debug normally.

I read a lot of posts online regarding this. And everyone have to say something with Interrupt but none of the solutions are working. Below is my code

BOOTLOADER.(where I am jumping to user application) 

       if(!bootLoaderVerifyCRC(rxBuf, packetLength - CRC_PACKET_LENGTH, hostCRC))

       {

              bootLoaderSendAck(1);

              uint32_t goAdress = *((uint32_t *)&rxBuf[2]);

              uint32_t* baseAdress = (uint32_t *)goAdress;

              if(verifyAddress(goAdress) == ADDR_VALID)

              {

                     bootLoaderUARTWriteData(&addrValid,sizeof(addrValid));

                     __disable_irq();

                     __set_MSP(*baseAdress);

                     uint32_t goToAddress = *(volatile uint32_t *)(baseAdress + 1);

                     void (*jumpToLocation) (void) = (void *)goToAddress;

                     jumpToLocation();

              }

 

USER APPLICATION(main code)

int main(void)

{

  /* USER CODE BEGIN 1 */

      __enable_irq();

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */

  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */

 SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */

 MX_GPIO_Init();

 MX_CRC_Init();

 MX_I2C3_Init();

 MX_USART1_UART_Init();

 MX_TIM3_Init();

 MX_TIM10_Init();

  /* USER CODE BEGIN 2 */

 ntsd.init();

 {

  GPIO_InitTypeDef GPIO_InitStruct = {0};

  HAL_GPIO_WritePin(GPIOF, LCD_CS_Pin, GPIO_PIN_SET);

  /*Configure GPIO pin Output Level */

  HAL_GPIO_WritePin(GPIOF, LCD_SCK_Pin|LCD_MOSI_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */

  HAL_GPIO_WritePin(GPIOA,LCD_RESET_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pins : LCD_CS_Pin LCD_SCK_Pin LCD_MOSI_Pin */

 GPIO_InitStruct.Pin = LCD_CS_Pin|LCD_SCK_Pin|LCD_MOSI_Pin;

 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;

 GPIO_InitStruct.Pull = GPIO_NOPULL;

 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;

  HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

  /*Configure GPIO pin : LCD_RESET_Pin */

 GPIO_InitStruct.Pin = LCD_RESET_Pin;

 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;

 GPIO_InitStruct.Pull = GPIO_NOPULL;

 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;

  HAL_GPIO_Init(LCD_RESET_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pins : LCD_CS_Pin LCD_SCK_Pin LCD_MOSI_Pin */

 GPIO_InitStruct.Pin = LCD_CS_Pin|LCD_SCK_Pin|LCD_MOSI_Pin;

 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;

 GPIO_InitStruct.Pull = GPIO_NOPULL;

 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;

  HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

 }

  HAL_Delay(1000);

  HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3);

  HAL_TIM_Base_Start(&htim10);

 st7796s_init();

  /* USER CODE END 2 */

/* Initialise the graphical hardware */

 GRAPHICS_HW_Init();

  /* Initialise the graphical stack engine */

 GRAPHICS_Init();    //IF I COMMENT THIS LINE AND FREERTOS RELATED STUFF THE JUMP IS WORKING

  

  /* USER CODE BEGIN RTOS_MUTEX */

  /* add mutexes, ... */

  /* USER CODE END RTOS_MUTEX */

  /* USER CODE BEGIN RTOS_SEMAPHORES */

  /* add semaphores, ... */

  /* USER CODE END RTOS_SEMAPHORES */

  /* USER CODE BEGIN RTOS_TIMERS */

  /* start timers, add new ones, ... */

  /* USER CODE END RTOS_TIMERS */

  /* Create the thread(s) */

  /* definition and creation of defaultTask */

 osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 4096); // COMMENT OUT THIS ONE

 defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL); // COMMENT OUT THIS ONE

  /* USER CODE BEGIN RTOS_THREADS */

  /* add threads, ... */

  /* USER CODE END RTOS_THREADS */

  /* USER CODE BEGIN RTOS_QUEUES */

  /* add queues, ... */

  /* USER CODE END RTOS_QUEUES */

  /* Start scheduler */

  osKernelStart(); // COMMENT OUT THIS ONE

  

  /* We should never get here as control is now taken by the scheduler */

  /* Infinite loop */

  /* USER CODE BEGIN WHILE */

  while (1)

 {

        while(1)

       {

            HAL_GPIO_WritePin(GPIOE, GPIO_PIN_2, GPIO_PIN_SET);

            HAL_Delay(100);

            //DelayUs(100000);

            HAL_GPIO_WritePin(GPIOE, GPIO_PIN_2, GPIO_PIN_RESET);

            //DelayUs(100000);

            HAL_Delay(100);

       }

   /* USER CODE END WHILE */

   /* USER CODE BEGIN 3 */

 }

  /* USER CODE END 3 */

}

and in the system_stm32f4xx.c file I have added below line

#define VECT_TAB_OFFSET 0x20000

But individually this code works if I debug instead of jumping.

 

I am stuck here for a long time. Any help is highly appreciated.

Thanks,

krishna

This topic has been closed for replies.
Best answer by Tesla DeLorean

Disabling ALL interrupts is NOT how to do this. You really want the SOURCE of the interrupt(s) turned off.

Also don't call from Interrupt/Callback or User context

Watch for PLL, Clock and startup code which expects reset conditions.

Have a proper Hard Fault routine on both sides which can output useful data.

Have something in Default_Handler() to catch the interrupts you forgot.

One of the more robust ways to make this work on the F2/F4 is via an NVIC_SystemReset(), caught in Reset_Handler via a RAM variable, and then jumping to the app.

4 replies

hs2
Visitor II
February 21, 2020

I assume you do have proper C runtime init code of the application somewhere including vector table adjustment, right ?

I think it‘s not so good to enable IRQs and peripherals before FreeRTOS init. This might cause problems when using FreeRTOS calls in ISRs.

Usually you‘re better off doing HW / peripheral init incl. enabling IRQ as late as possible e.g. in the task which handles the peripheral.

Kpodu.1
Kpodu.1Author
Associate III
February 23, 2020

Thanks hs2 for your reply. Yes I have modified the vector table value in startup script it self. I tried your solution but still it didnt work.

Tesla DeLorean
Tesla DeLoreanBest answer
Guru
February 21, 2020

Disabling ALL interrupts is NOT how to do this. You really want the SOURCE of the interrupt(s) turned off.

Also don't call from Interrupt/Callback or User context

Watch for PLL, Clock and startup code which expects reset conditions.

Have a proper Hard Fault routine on both sides which can output useful data.

Have something in Default_Handler() to catch the interrupts you forgot.

One of the more robust ways to make this work on the F2/F4 is via an NVIC_SystemReset(), caught in Reset_Handler via a RAM variable, and then jumping to the app.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
Kpodu.1
Kpodu.1Author
Associate III
February 23, 2020

Hi Clive1,

I saved a flag in CCRAM and used NVIC_SystemReset(). Was able to successfully run the user application. Thanks for your suggestion

Krishna