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
Posted on April 23, 2014 at 22:18

So logic there seems a bit messed up. Do you have ANY interrupts running? Have you relocated the SCB->VTOR?

Are you doing a ''Step Into'' operation, and it's going to an address that is NOT the one in R5?

Some L1 parts have 48KB (0x20000000..0x2000BFFF), others have 80KB (0x20000000..0x20013FFF)
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
stm322399
Senior
Posted on April 23, 2014 at 22:27

Strange that I focussed on stm32L10x part only ... my bad.

Anyway, there should be an interrupt/fault/event that brings you to bank1 before you had time to configure VTOR to bank2.

Clive1 is right about step/stepinto different behaviour using the debugger. Try to put a breakpoint early in your bank2 firmware, presumably at 0x80306b4 or 0x80306b6.

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

I added a new line to setSCB->VTOR before jumping as seen below... but it still does not work.

I tried placing a breakpoint at the bank 2 jump address, since I already have one in Reset_Handler, but I did not catch anything different.


/* 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;

__disable_irq();

__set_MSP(*(U32*)FLASH_BANK_2_START_ADDR);

NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x30000);

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);

NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);

jumpToOtherBank();

}

This is how I have VECT_TAB_OFFSET defined in System.c so that I can build a target for each bank (this is working).


/*!< Vector Table base offset field. This value must be a multiple of 0x */

#ifdef BANK_1_TARGET

#ifdef BANK_2_TARGET

#error ''Multiple target banks specified!''

#else

#define VECT_TAB_OFFSET 0x0

#endif

#else

#ifdef BANK_2_TARGET

#define VECT_TAB_OFFSET 0x30000

#else

#error ''No target bank specified!''

#endif

#endif

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

duplicate reply due to site error

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

''Are you doing a ''Step Into'' operation, and it's going to an address that is NOT the one in R5?''

Yes, that is what I'm seeing in the debugger. Could be VTOR related, hopefully I provided enough info/code to help identify it.

Posted on April 23, 2014 at 22:55

Make sure you are doing the ''Step Into'' from the Assembler code pane, not the C code pane.

You should be able to observe the value in R5, watch the return address moved to LR, and PC should be what's in R5

Do not ''Step Over'' or ''Run''

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 24, 2014 at 18:46

You're right, I was able to step into the jump function in the assembly viewer. It does seem to properly jump from bank 2 to 0x080006B1, and I can step thru the assembly code for hundreds of lines. However, when I eventually start running, it winds up in the Reset_Handler for the original bank 2. I'm guessing this indicates a hard fault or some error that triggers a reset, which would boot into bank 2 as expected. Setting a breakpoint in the HardFault_Handler for bank 1 doesn't work (presumably since the debugger is still operating in bank 2).

Is there anything else I'm missing before the jump, besides relocating the MSP and VTOR? I will continue to investigate this reset.

tommycooper
Associate II
Posted on April 24, 2014 at 18:58

I was able to confirm the hard fault is occuring, and dump some values:

pc = 0

configurable fault status reg: 0x0

hard fault status reg: 0x40000000 (forced)

mem manage fault address reg: 0xE000ED34

bus fault address reg: 0xE000ED38

Seems like the program counter should be non-zero at least. Does this provide any clues?

Posted on April 24, 2014 at 19:41

How on earth is it ending up in the Reset_Handler? It's not getting there randomly. I can see a Hard Fault, but if that's got a while(1); in it then it will dwell there.

You're stepping the code, you should be able to see exactly what instructions are being executed, and how it arrived where it ends up. LOOK at that code flow, and the register context, it should be apparent, and at the very least you could document the flow. You should have direct access to 90%+ of the source code it's executing.

Use LEDs, GPIOs or USART to identify how far into the code it's gotten.

What interrupts do you have enabled when you do this?

Do you do anything in SystemInit() that is aware that the CPU is running from the PLL rather than HSI when it does this secondary entry? Some of ST's code makes assumptions.

Look at the vector table entries, any of these zero? Branching/calling zero with cause a hard fault, as it's not ODD

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 25, 2014 at 14:46

I forgot to mention my hard_fault_handler forces a reset (after dumping status regs to EEPROM). For some reason I assumed this was default behavior after not touching that code for awhile.

I gave up on stepping though assembly code since I have no idea how long it will take to hard fault, and the debugger doesn't follow my bank switching in C. However, using LEDs is a good idea for determining where it occurs.

I disable interrupts with __disable_irq() before jumping, then after I enable EXTI and NVIC IRQ as part of the usual initialization in main. Not sure about the SystemInit/PLL/HSI suggestion.

I'll take a look at the vector table entries. I didn't think I was manually manipulating these and could assume they are compiled correctly with all bit[0]=1. Note to self, refer to: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka12545.html

Unfortunately I have to put this project on the backburner for a bit, so I will follow up with any findings as soon as possible. Thanks for your help so far though, I'm definitely learning a lot.