cancel
Showing results for 
Search instead for 
Did you mean: 

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

Kpodu.1
Associate II

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

1 ACCEPTED SOLUTION

Accepted Solutions

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
Up vote any posts that you find helpful, it shows what's working..

View solution in original post

4 REPLIES 4
hs2
Senior

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.

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
Up vote any posts that you find helpful, it shows what's working..

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

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.