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
tommycooper
Associate II
Posted on April 30, 2014 at 19:22

Also, when I remove the line to set VTOR before jumping to Bank 2, I get the same results (not including VTOR obviously)...

After SVC, inside HardFault_Handler:

SVCall (0x0803002C) = 0x08030355 (SVC_Handler); VTOR = 0x08000000

PC = 0; LR = 0x2000BCC8

CFSR = 0; HFSR = 0x40000000; DFSR = 0x00000003; MMFAR = BFAR = 0xE000EDF8; AFSR = 0

stm322399
Senior
Posted on April 30, 2014 at 19:44

OK, I was wrong saying that PRIMASK set to one is harmless. Indeed, it is exactly what makes SVCall to enter HardFault according to ARM architecture manual.

It does not happen on my platform because the first task is launched with ''cpsie i'' right before SVC.

Of course PRIMASK is very convenient to avoid any interruptions during the *switched reboot*. You have to do it differently, probably by disabling every NVIC source.

Anyway that does not explain the reboot.

That does not explain why PC=0 right after the SVC/HardFault. Normally the HardFault can be catch very early by setting a breakpoint at the first instruction of the handler. The handler address(+1) is declared at 0x800000c/0x803000c, so you can set that breakpoint.

Another reason for rebooting is the use of the debugger. It is *possible* (I don't know your debugging system) that the debugger is configured in a way that it resets the processor when a lockup is detected (e.g. re-entering HardFault handler infinitely).

Posted on April 30, 2014 at 20:01

After SVC, inside HardFault_Handler:

SVCall (0x0803002C) = 0x08030355 (SVC_Handler);VTOR = 0x08030000

PC = 0; LR = 0x2000BCC8 CFSR = 0; HFSR = 0x40000000; DFSR = 0x00000003; MMFAR = BFAR = 0xE000EDF8; AFSR = 0

Well PC and LR appear totally bogus, what does your Hard Fault handler look like? Here we decode the registers, and stacked context, emitting it out USART1.

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 30, 2014 at 20:36

Thanks Laurent, it works perfectly now! I just had to replace __disable_irq with

NVIC_DisableIRQ();

__DSB();

__ISB();

as recommended by 

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dai0321a/BIHHFHJD.html

Hopefully this post will help others if they get stuck on the same issue; I realize now that Tom Rfid removed his __disable_irq in his answer, but I thought it wasn't related since it wasn't explained.

I'm not sure why the PC and LR were screwed up, but I was using the Joseph Yiu hard fault handler you pointed to Clive.

tommelou
Associate II
Posted on May 21, 2014 at 12:15

Nice!

I have remove the __disable_irq because my jump is done before to set the vector table and initialize it, so I had no need.