2014-04-23 10:53 AM
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¤tviews=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
2014-04-25 06:28 AM
With Keil, you'd do better debugging the secondary app, rather than the primary, if it's going to cross the threshold into the secondary.
Disable run-to-main, and break point the Reset_Handler Are you using an RTOS?2014-04-25 08:24 AM
Ah, good idea. I think I could possibly run the debugger in bank 1, switch to bank 2 via BFB2/reset (at which point the debugger won't show stack), then perform the jump to bank 1 (at which point the debugger will show stack again). If my assumptions are correct.
Yes I'm using Keil RTX.2014-04-25 09:14 AM
Yes I'm using Keil RTX.
In user/process mode you will get a Hard Fault if you do things that require system mode. Take a look at Joseph Yiu's Hard Fault handler examples, and use the decoding of the stacked state to review the PC, and the failing instruction.2014-04-29 03:21 AM
Hi, try to read this! I have solved my problem!
/291a55f7
2014-04-29 06:48 AM
Yes, I've read that post, and it was quite helpful. However, when adapting it for my application, I am running into some hard fault problem after it jumps. I'll post more project/compiler setting that could help... although like I said, each of these compiled targets runs perfectly well in its defined flash bank; there's some critical failure in supporting the jump while running though.
Scatter files (custom, included in Linker tab of target options):
; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************
LR_IROM1 0x08000000 0x00030000 { ; load region size_region
ER_IROM1 0x08000000 0x00030000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
}
RW_IRAM1 0x20000000 0x0000C000 { ; RW data
SelfErase.o (+RO)
stm32l1xx_flash_ramfunc.o (+RO)
.ANY (+RW +ZI)
}
}
; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************
LR_IROM1 0x08030000 0x00030000 { ; load region size_region
ER_IROM1 0x08030000 0x00030000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
}
RW_IRAM1 0x20000000 0x0000C000 { ; RW data
SelfErase.o (+RO)
stm32l1xx_flash_ramfunc.o (+RO)
.ANY (+RW +ZI)
}
}
2014-04-29 07:42 AM
Yes, I've read that post, and it was quite helpful. However, when adapting it for my application, I am running into some hard fault problem after it jumps. I'll post more project/compiler setting that could help... although like I said, each of these compiled targets runs perfectly well in its defined flash bank; there's some critical failure in supporting the jump while running though.
If it runs from reset, but not from the RTOS, then it sounds like a privilege issue.2014-04-29 09:58 AM
All I know about privilege is that the program tasks are running in privileged mode (OS_RUNPRIV == 1). How does that affect running from another bank (what more is there besides relocating MSP and NVIC)?
I can't debug the second bank, after jumping the debugger crashes. Is there a way to allow this? Like I said, I can step through the assembly after the jump, but I can't really tell what's happening with the corresponding C code. I guess I can follow the pc using the .map file addresses though.2014-04-29 11:46 AM
How does that affect running from another bank (what more is there besides relocating MSP and NVIC)?
Well if you run instructions that aren't permitted, it'll Hard Fault on you. You'd perhaps want to handle the transition to the Secondary via an SVC so you're not in User/Process Mode? You could experiment by calling the secondary image prior to calling SystemInit() and __main() in the Primary. This would prove it's a system state issue. My experience with Keil and RealView, is that it's possible to debug the Secondary, you don't ''run to main'', you break point ResetHandler in the Secondary, and you walk through the Primary so that it hands off to the Secondary. If your Hard Fault resets the processor, think of a better way of handling that while you debug your issues. Go look at the instructions which are faulting, and the processor context. If you have serial ports, GPIOs or LEDs use those to way-point you traversal from ResetHandler, SystemInit() and through to main(). Until you figure out where it's breaking this will continue to be a circular discussion.
2014-04-29 01:06 PM
Well I finally discovered where it is hard-faulting... after SVC instruction. The following assembly code is in calling os_sys_init() at the end ofMain. Does this help pinpoint the issue? I will read about SVC in meantime.
; os_set_env
0x08000678 F7FFFE3E BL.W 0x080002F8
; _os_sys_init
0x0800067C 2200 MOVS r2,#0x00
0x0800067E 4611 MOV r1,r2
0x08000680 480E LDR r0,[pc,#56] ; @0x080006BC
; r0 == 0x08000515 (OsInit, first task to create other tasks)
0x08000682 F8DFC03C LDR.W r12,[pc,#60] ; @0x080006C2
; r12 == 0x08025A15 (rt_sys_init)
0x08000686 DF00 SVC 0x00
; goes to HardFault_Handler now
0x08000688 BF00 NOP
0x0800068A E7FE B 0x0800068A
2014-04-29 01:44 PM
It appears as if that _os_sys_init SVC instruction is not triggering SVC_Handler as it normally does from reset... obviously. I'm missing something fundamental. I'm trying to look at the NVIC at 0x08000000/0x08030000 --> 0x2000bf58, but not sure how to read this memory.