cancel
Showing results for 
Search instead for 
Did you mean: 

Bootloader and distance reprogramming

Steven Bébin
Associate III

Hello,

I program on the NUCLEO-144 STM32F767ZI board and I have been facing a problem for over a week.

In FLASH memory, I have 3 programs located at specific addresses:

- A bootloader which allows to start on the main programmer or reprogramming program.

- A main program that has several functions like http server, tcp server, usart ...

- A reprogramming program that distance reprograms the stm32 card. The operation is basic, I send a binary file to an http server, then I put at the place of the main program.

When I reprogram with a basic program (for example: to light an LED) everything works. on the other side when I reprogram with a big program (for example: my actual main program) it does not work. The stm32 seems to hang somewhere and I do not know where. I have already tried to remove all the interruptions before jump, it does not change anything.

On the front line of all my programs, I have the "SCB-> VTOR" which points to current address.

Here my bootloader code :

#include "stm32f7xx_hal.h"
 
	#define REPROGRAMMATION_ADDRESS  0x08020000
 
	#define FLASH_MEM1_FIRST_ADDRESS	  0x08040000
 
	void JumpInProgram(uint32_t address);
	
	typedef  void (*pFunction)(void);
 
	pFunction Jump_To_Application;
 
int main(void) 
{
	SCB->VTOR = 0x8000000;
	if((*(uint32_t*)0x80C0000 == 1) JumpInProgram(REPROGRAMMATION_ADDRESS); // if variable locaded "0x80C0000" is equal to 1 go to reprogrammation program
	else JumpInProgram(FLASH_MEM1_FIRST_ADDRESS); // else principal program
}
 
void JumpInProgram(uint32_t address) 
{
	uint32_t JumpAddress = *(__IO uint32_t*)(address + 4);
	pFunction Jump = (pFunction)JumpAddress;
	__set_MSP(*(__IO uint32_t*)address);
	Jump();
}

Here my main fonction in principal program for example :

int main(void)
{
	SCB->VTOR = 0x8040000;
  HAL_Init(); 
  SystemClock_Config();
	
	MX_GPIO_Init();
	
	MX_TIM4_Init();
	
  MX_USART1_UART_Init();
	MX_USART2_UART_Init();
	MX_USART3_UART_Init();	
	
	HAL_TIM_Base_Start_IT(&htim4);
	HAL_UART_Receive_IT(&huart3, donneetic, 1); 
	HAL_UART_Receive_IT(&huart1, donneerf, 1); 
	
  osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, configMINIMAL_STACK_SIZE); 
  defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);
	
  osKernelStart(); 
}

Hoping you can help me, thank you

16 REPLIES 16

>> The stm32 seems to hang somewhere and I do not know where.

That's why we have debuggers, and instrument code so we know where it goes, the flow, and where it is stuck.

Make sure things like HardFault_Handler() and Error_Handler() output actionable data, rather than spin in a while(1) loop.

Identify all other dead locking or infinite loops, or those lacking timeouts.

Get a UART up, or GPIO, so you can provide information, or check-points, to pin down progress without a debugger attached.

When stuck, stop in the debugger, and review a) where it is in all your code, and b) the state of memory/peripherals

Don't transfer control from interrupt context (ie EXTI, SysTick, etc). Callbacks are executed in interrupt context.

Don't transfer control from an RTOS with User/System execution states, in User or Interrupt contexts.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Steven Bébin
Associate III

Thank you very much for your answer !

Unfortunately, I use the debugger to see where the program block. I also use GPIOs as control points to help. But despite that, I can not find the problem! I will not say that the problems are random, but almost! One day, the program was stuck in the msp_init() function and the day after it was blocked on the systick function.

I did not understand the last two lines.

While searching the web, people were talking about initializing properly before making the jump. But I do not know how to do it. Should devices, clocks, and other be uninitialized before jumping?

Sorry to appear a little lost, but I am clearly

>>While searching the web, people were talking about initializing properly before making the jump. But I do not know how to do it. Should devices, clocks, and other be uninitialized before jumping?

You have to define that contract between both sides, and implement it. Most of ST's boilerplate code assumes a blank-slate, reset-like, starting point

If your loader initializes all the clocks, and PLLs, no need to do it again in the app.

You should turn off all interrupt sources at each peripheral, the RAM and structures used by the loader aren't passed to the app, and will be placed in different memory by the linker. Identify the peripherals your loader is bring up, and get them into a safe state. You don't need to DeInit(), just be conscious to turn off the bits in the ISR registers. Using __disable_irq() really side steps doing things properly/mindfully.

When the app starts, none of it's RAM has been initialized, you don't want the loader SysTick firing. It might contain random stuff, and be mapped entirely differently.

Make sure your app code doesn't have any expectations about the HW or peripherals being in a RESET state

>>I did not understand the last two lines.

The processor maintains state, as does the NVIC, you need interrupts/handlers to unwind. If you transfer control from one premption level, you're never going to get anything at or below that level again.

 SystemInit() usually sets SCB->VTOR, ST's code is dumb, I let the linker fix up using the __vectors symbol

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Steven Bébin
Associate III

Hello !

I found the origin of the problem, but I do not know how to explain it. In my main program, I have a lot of global variables (variables used throughout the program). Approximately, I can not really be precise, I have 80kb of global variables.

When I decrease this number of variables, I manage to run the program.

Steven Bébin
Associate III

I do not understand. Sometimes it works sometimes it does not work. I use __disable_irq (); and __enable_irq (); but nothing changes.

Steven Bébin
Associate III

After sending a new program, the boot loader sends well to the correct address. When I'm in the debugger, I arrive in a hardfault function. The problem is never the same, sometimes the program block in the Hal_init (), sometimes in the SystemClock_Config () ... I have already tried to disable all interrupts, but nothing works. When I load the program with a download directly with the Keil software, it works well. But as soon as I'm in API, it is impossible.

Steven Bébin
Associate III

In my flash memory, my bootloader is in sector 0. I have parameters in sectors 1 and 2. My main program is located in sectors 5,6 and 7. My secondary program (reloaded by IAP) is located in sectors 8, 9 and 10. I do not use sectors 3, 4 and 11.

When I do tests, each time, I delete the secondary program so sectors 8, 9 and 10.

I do not know what went through my head, I thought, "What if I erased the sector 11 while we're there?" And well after clearing sector 11, the program was no longer blocking in the same place, the initialization was perfect, it even launched the threads. I thought it was not possible, nothing is related to my sector 11, I tried, like it works, but it seems to block further.

I'm still a beginner, but I think I'll unplug my brain this weekend, I need it.

Mtx_ing5
Associate

Maybe it's a basic question but do you change your linker for each application? I'm working in a bootloader for a STM32L476RE and sometimes when I don't update the linker, the MCU get stuck for a big program but it's works for a simple one.

Piranha
Chief II

Why are bootloader and reprogramming program two separate programs?

*(uint32_t*)0x80C0000 == 1

There is no need to wear flash for passing variable to bootloader. This can be done with a special region of SRAM, as hardware does not erase it at reset.

For changing bootloader/application modes there is a much better and simpler solution, which cancels all dependencies completely. I described it here:

https://community.st.com/s/question/0D50X0000AFpTmUSQV/using-nvicsystemreset-in-bootloaderapplication-jumps