cancel
Showing results for 
Search instead for 
Did you mean: 

Use second firmware as function, called when necessary

LSpad.1
Associate III

Hi!

I want to use 2 firmware on the same microcontroller, one is written at 0x8000000 with ram starting at 0x20000000. The other is flashed at 0x8040000 with ram starting at 0x20010000.

The first firmware should use the second as a function. So i allocated a function pointer, like in a common bootloader, and used the function. The function execute, because the led switches on, but it does not return to the caller firmware after execution. These are the 2 main of the projects, that are all the executed code:

Caller program:

int main(void)
{
  /* USER CODE BEGIN 1 */
 
  /* 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();
  /* USER CODE BEGIN 2 */
 
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  char var = 0;
  char* pvar = &var;
  char** ppvar = &pvar;
	uint32_t  JumpAddress = *(__IO uint32_t*)(SYSMEM_ADDRESS + 4);
	int (*run)(int len, char** v) = (void*) JumpAddress;
  while (1)
  {
  	//__set_MSP(*(__IO uint32_t*)SYSMEM_ADDRESS);
  	run(1, ppvar);
  	//SCB->VTOR = SYSMEM_ADDRESS;
  	HAL_Delay(1000);
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

Called program:

int main(int len, char** var)
{
  /* USER CODE BEGIN 1 */
	//SCB->VTOR = 0x08020000;
	GPIOD->BSRR = LED_RED_Pin|LED_BLUE_Pin;
	(**var) +=1;
	//__set_MSP(*(__IO uint32_t*)0x08000000);
	GPIOD->BSRR = (LED_GREEN_Pin|LED_ORANGE_Pin|LED_RED_Pin|LED_BLUE_Pin);
	return 0;
  /* 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 */
  /* USER CODE BEGIN 2 */
 
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
//  while (1)
//  {
//    /* USER CODE END WHILE */
//
//    /* USER CODE BEGIN 3 */
//  }
  /* USER CODE END 3 */
}

I tryed to run the called firmware from debugger and after the return 0 in line 9 it returns in the reset handler, in particular in the third line:

/* Call the application's entry point.*/
  bl  main
  bx  lr    

I think that is normal if i launch the second firmware without the first one, it returns in the reset handler, but looking at the disassebly flash address with the debugger, it is the same address that goes into when i call the second firmware from the first one.

I think it is a bit strange because if i call a function, when it returns, it should have the return address and so it should return in the address that called it. Do you know what am i doing wrong?

PS: all the code is generated from CubeMX (STM32F401VC), the only modified files are the main.c and the flash.ld, only for start address and size of the flash and ram. I tryed execute the code changing the stack pointer and VTOR register and without changing them (you can see the commented lines).

Thank you in advance

1 ACCEPTED SOLUTION

Accepted Solutions
EJOHA
Senior

Did you tried to set the address to 0x080201D5 instead.

PS. Maybe you get some more info by studying the STM32CubeIDE UM. It covers many aspects of linking and locating code at different places but it might not cover the way you try to use to fw in this way, The UM is available here:

https://www.st.com/resource/en/user_manual/dm00629856-description-of-the-integrated-development-environment-for-stm32-products-stmicroelectronics.pdf

View solution in original post

3 REPLIES 3
EJOHA
Senior

Maybe I am missing something here.

Why do you call the second main() via the the Reset_Handler in the second program? Could not you just call second main directly?

As it is now it seems main() will return to Reset_Handler function in second program...

Hi,

Thank you for the answer!

You are right, i noticed that if i set the function address via the second program start address (0x8020000) i go in the reset handler of the second firmware.

I tryed, debugging the second firmware, to detect the address of the main:0693W000003Ps4iQAC.png

So i set the address of the function (removing the "+ 4") to 0x080201D4, but when I call it from the first firmware i retreive an hard fault. I tryed the addresses from 0x080201C9 to 0x080201D9, but same result. What could be the problem?

EJOHA
Senior

Did you tried to set the address to 0x080201D5 instead.

PS. Maybe you get some more info by studying the STM32CubeIDE UM. It covers many aspects of linking and locating code at different places but it might not cover the way you try to use to fw in this way, The UM is available here:

https://www.st.com/resource/en/user_manual/dm00629856-description-of-the-integrated-development-environment-for-stm32-products-stmicroelectronics.pdf