Skip to main content
Kpodu.1
Associate III
Feb 21, 2020 10:31 PM UTC
Solved

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

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.
Tesla DeLorean
Tesla DeLoreanBest answer
Guru
Feb 21, 2020 11:26 PM UTC

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..

4 replies

hs2
Visitor II
Feb 21, 2020 10:55 PM UTC

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
Feb 23, 2020 12:16 AM UTC

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
Feb 21, 2020 11:26 PM UTC

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
Feb 23, 2020 12:16 AM UTC

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