cancel
Showing results for 
Search instead for 
Did you mean: 

Jump address is not compiling correctly for STML1x

tommycooper
Associate II
Posted on April 23, 2014 at 19:53

My goal is to jump from bank 1 to bank 2 at the start of main. I'm trying to follow the example in this forum post:

/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https%3a//my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Jump%20address%20to%20choose%20one%20of%202%20binary%20in%20flash&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&currentviews=110

However, when I try to specify an address in the opposite flash bank, an address that is offset from PC seems to be loaded instead of the exact address. As you can see, the 0x08000000 address is loaded correctly but the 0x08030000 address is not. Even if I replace the C code with inline ASM, it still does this. Am I doing something wrong or using the wrong ASM instruction? How do I go about accomplishing this? Here is my relevant C code in main:


/* Jump to opposite bank without modifying BFB2 bit */

if
(currFwBank == 1)

{

U32 jumpAddr = *(U32*)(FLASH_BANK_2_START_ADDR+4);

JumpFunc_t jumpToOtherBank = (JumpFunc_t)jumpAddr;

//__ASM volatile (''''); 

__disable_irq();

__set_MSP(*(U32*)FLASH_BANK_2_START_ADDR);

jumpToOtherBank();

}

else

{

U32 jumpAddr = *(U32*)(FLASH_BANK_1_START_ADDR+4);

JumpFunc_t jumpToOtherBank = (JumpFunc_t)jumpAddr;

__disable_irq();

__set_MSP(*(U32*)FLASH_BANK_1_START_ADDR);

jumpToOtherBank();

}

Here are my mixed C/assembly instructions from the Keil debugger:

203: if (currFwBank == 1) 
204: { 
0x0800061E F89D0000 LDRB r0,[sp,#0x00]
0x08000622 2801 CMP r0,#0x01
0x08000624 D10A BNE 0x0800063C
205: U32 jumpAddr = *(U32*)(FLASH_BANK_2_START_ADDR+4); 
0x08000626 481F LDR r0,[pc,#124] ; @0x080006A4
0x08000628 6844 LDR r4,[r0,#0x04]
206: JumpFunc_t jumpToOtherBank = (JumpFunc_t)jumpAddr; 
207: //__ASM volatile (''''); 
0x0800062A 4625 MOV r5,r4
208: __disable_irq(); 
0x0800062C B672 CPSID I
209: __set_MSP(*(U32*)FLASH_BANK_2_START_ADDR); 
0x0800062E 491D LDR r1,[pc,#116] ; @0x080006A4
0x08000630 6808 LDR r0,[r1,#0x00]
171: __regMainStackPointer = topOfMainStack; 
0x08000632 F3808808 MSR MSP,r0
172: } 
0x08000636 BF00 NOP 
210: jumpToOtherBank(); 
0x08000638 47A8 BLX r5
211: } 
212: else 
213: { 
0x0800063A E00C B 0x08000656
214: U32 jumpAddr = *(U32*)(FLASH_BANK_1_START_ADDR+4); 
0x0800063C F04F6000 MOV r0,#0x8000000
0x08000640 6844 LDR r4,[r0,#0x04]
215: JumpFunc_t jumpToOtherBank = (JumpFunc_t)jumpAddr; 
0x08000642 4625 MOV r5,r4
216: __disable_irq(); 
0x08000644 B672 CPSID I
217: __set_MSP(*(U32*)FLASH_BANK_1_START_ADDR); 
0x08000646 F04F6100 MOV r1,#0x8000000
0x0800064A 6808 LDR r0,[r1,#0x00]
0x0800064C F3808808 MSR MSP,r0
0x08000650 BF00 NOP 
218: jumpToOtherBank(); 
0x08000652 47A8 BLX r5
219: } 

#jump-address-stm32l1-flash-bank
44 REPLIES 44
stm322399
Senior
Posted on April 23, 2014 at 20:27

The generated code looks good.  In the first case 0x8030000 (or whatever address isFLASH_BANK_2_START_ADDR

) is loaded into R0 from a constant pool addressed by relative PC (look at 0x080006A4, it must contain 0x08030000).  In the second case 0x08000000 is loaded into R0 as a constant embedded in the opcode.  If something goes wrong, it looks like this code is not guilty. 

Posted on April 23, 2014 at 20:41

Print out the values you are reading/using

Dump out the front of the vector table from both ''banks''

Your code needs to be linked for the specific address it is being placed.

How does BFB2 relate to this? Is the second bank really at 0x08030000 and expect to be executed from there?
Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
tommycooper
Associate II
Posted on April 23, 2014 at 20:50

You are correct, 0x080006A4 does contain the desired address 0x08030000. I misunderstood the instruction, although I should have checked that address anyways.

Moving on, I'm still not sure what the problem could be. When I step past the jump in the debugger, it goes to Reset_Handler in bank 1 instead of bank 2.

tommycooper
Associate II
Posted on April 23, 2014 at 20:55

I have successfully linked/downloaded separate firmware images to each bank (not PIC). I can switch between the two banks by modifying BFB2 and resetting. However, I would like to keep BFB2 intact and switch to bank 2, so that I may test running the 2nd firmware image; if it fails and resets, BFB2 will force reverting to the original working image in bank 1. This is my plan at least, if it's even possible.

stm322399
Senior
Posted on April 23, 2014 at 21:10

And what are the values respectively taken by R5 before the jump in both cases ?

tommycooper
Associate II
Posted on April 23, 2014 at 21:28

For jumping from bank 1 to bank 2, r5 = 0x080306B5.

SP changes from 0x2000BF28 to 0x2000BF40 within the __set_MSP call.

After jump, debugger goes to 0x080006B0 in Reset_Handler.

stm322399
Senior
Posted on April 23, 2014 at 22:06

Just a guess:

No STM32L1x has 0x2000BF28 in his memory (max 16KB, -> 0x20004000), BLX trying to store some data to the stack will fault.

Coincidentally Reset_Handler might be the destination of hard fault.

Make sure there is 0x08030000 address in flash (unless you have STM32L100RC).

Generally, double check the low-level ported from STM32F106 to make sure it fit stm32L1x.

tommycooper
Associate II
Posted on April 23, 2014 at 22:09

Also, for jumping from bank 2 to bank 1, r5 = 0x080006B1.

SP changes from 0x2000BF30 to 0x2000BF48 within the __set_MSP call.

After jump, debugger goes to 0x080306B0 in Reset_Handler.

tommycooper
Associate II
Posted on April 23, 2014 at 22:15

I'm using the STM32L151QD chip specifically, which has 48KB SRAM (up to 0x2000c000).