cancel
Showing results for 
Search instead for 
Did you mean: 

Interrupt not working after jump to code from bootloader

spack
Associate

I have a project that consists of a bootloader and 2 pieces of code on STM32L100R8. The bootloader correctly switches to the relevant piece of code but it seems as though when the code receives it first interrupt it fails. Attached are screenshots of the bootloader and linker/target options in the keil environment. Any ideas ??

0690X000006C8etQAC.jpg0690X000006C8eoQAC.jpg0690X000006C8ejQAC.jpg

9 REPLIES 9
Bob S
Principal

Define "fails".

Basic debugging: start your debugger, run the bootloader, let it call your app. When the app fails, pause the debugger and see where you are. Then see if you can figure out how you got there. This can be tricky when you have a bootloader and separate application.

Hint: What steps does the CPU take when it gets an interrupt? And from where does it fetch whatever data it needs to do that? And what data is actually there? I am guessing at how you generate all of your code, but this may help you find the answer.

Make sure the code in the application sets the SCB->VTOR properly, typically in SystemInit()

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

Hi - Many thanks for the quick replies ! The project is a keypad that is connected to a telematics device using UART2. In normal operation data travels in both directions between the keypad and telematics device - when located at the standard address of 0x8000000 everything works fine.

I have discovered that if I disconnect the RX line from the telematics unit to the STM32 then everything indeed works fine (so the STM32 can still send data to the telematics unit - it just can't receive it), even with the code relocated to address 0x8001C00. However, once I connect up the RX Line to the STM32 it seems to go into a loop. This leads me to believe that the Interrupt connected to UART2 is not being handled properly.

In one reply you mention setting SCB->VTOR in the application - does this not get set in the bootloader code I set out above - and the compiler/linker place this at the start of memory 0x8001C00 when I compile the application ? To be safe I also added the SCB->VTOR to the application itself and it seem to make no difference.

Once the program seems to loop and I stop the debugger it does not seem to have me in a recognizable location ? To be honest as per the comment above I suspect it is not the easiest thing to debug separate bits of code like this !

These are the relevant bits of code that handle the interrupt - but I'm hoping that the fact that it all works when located at 0x8000000 and only fails when located to a different memory space that it is a compiler/linker option ?

This is issued at the start of the application :

HAL_UART_Receive_IT(&huart2, &Rx2_char, 1);

This is the function to deal with the interrupt :

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)

{

if (UartHandle->Instance == USART2) //If data on uart2

{

HAL_NVIC_ClearPendingIRQ(USART2_IRQn);

Rx2_buf[Rx2_count] = Rx2_char;

Rx2_count++;

if (Rx2_char == 0x0D)

{

uart2_dta_set = 1;

}

HAL_UART_Receive_IT(&huart2, &Rx2_char, 1);

return;

}

}

void HAL_UART_ErrorCallback(UART_HandleTypeDef *UartHandle)

{

if (UartHandle->Instance == USART2) //If data on uart2

{

if (UartHandle->ErrorCode == HAL_UART_ERROR_ORE)

{

__HAL_UART_CLEAR_OREFLAG(UartHandle);

HAL_UART_Receive_IT(&huart2, &Rx2_char, 1);

}

}

}

Hello Clive,

in one of the previous posts you recommended not to use SystemInit() in application code, removing call to it in a startup_*.s

Could you please elaborate on it?

Thank you,

Gennady

Can you actually cite the post, it depends on the context.

I've suggested in the past that if you have a "contract" between the Boot Loader and App you shouldn't need to reconfigure the clocks and external bus interfaces repeatedly. Such activity can be highly disruptive.

The FPU is probably already enabled also, and the code in startup.s could be expanded to set SCB->VTOR appropriately automatically.

LDR R0, =0xE000ED08 ; SCB->VTOR
  LDR R1, =__Vectors
  STR R1, [R0]

In the HAL a lot of the code that should be in SystemInit() has migrated to a call to SystemClock_Config() from main()

This can be a bit late for external memories you want to use or initialize. https://community.st.com/s/question/0D50X0000ADDERqSQP/how-to-initialize-external-sram-in-systemstm32l4xxc

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

This is a comment I am talking about:

Posted on April 12, 2012 at 18:54

<< Running SystemInit() a second time around is not advisable, it doesn't seem to pay

<< any attention the the current state of the system and bangs the HSE and PLL

<< assuming a cold start running from HSI, rather than one already running from the

<< PLL. Much grinding of gears and consternation will occur...

<< Remove the call to SystemInit in startup_stm32f10x_md.s in the application project.

Anyway, my question is related to the problem I have now.

My processor is stm32L432.

I have a bootloader and application using the same peripherals - bidirectional UART1 with DMA for data transfer and a few timers (no SysTick). By some reason communication is not working in application (though I used a similar bootloader multiple times in other projects) and I am trying to find a reason.

I've read practically all your comments on related issues on a forum and want to try to change my approach according to what I read. Would it be possible for you to look at the following process list and let me know if something is wrong?

Bootloader:

  1. Remove SystemInit() call. Use startup.s to set SCB->VTOR as you suggested.
  2. Use HAL_Init() and SystemClock_Config().
  3. Initialize peripherals and interrupts.
  4. Before jump de-init uart and dma and disable related interrupts
  5. Jump to application using standard procedure.

Application:

  1. Use modified startup.s to set a new vector
  2. Skip HAL_Init() - can I?
  3. Skip SystemClock_Config()
  4. Since long delays (seconds) are necessary to initialize DSP etc, initialize uart and dma and enable related interrupts only before the main loop.
  5. If bootloader reentry is requested for application upgrade, set a flag in RAM at predefined location.
  6. Before jump de-init uart and dma and disable related interrupts
  7. Jump to bootloader using standard procedure.

Bootloader reentry:

  1. If reentry flag is set, skip HAL_Init(), SystemClock_Config() and peripherals initialization.
  2. Initialize uart and dma, enable related interrupts.

I would highly appreciate your comments on the above procedure.

Gennady

Set VTOR to the address of the table, not to the stack pointer in the table.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
JBond.1
Senior

Did you ever figure the solution for this? I have the same issue on STM32F407

SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;

I do this before jumping to application, it worked on STM32F103 but does not work on STM32F407 (timer interrupt doesnt trigger after jump to application). Any ideas?

Nevermind I have solved by setting VECT_TAB_OFFSET which I forgot to set. Now interrupt is working!