We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
Hi all,
If the processor tries to go back from the test() function to the main() function, the program counter gets always the wrong address - so that an undef handler occurs.... (processor is searching for an programm code in the sdram...). The whole programm is stored in an external nor flash device (0x10000000).
void test(void) { //do some stuff... return; } void main(void) { test(); }
The user stack size is 0x800. That's a short part of the disassembly where the jump to the sdram occurs (the next step after 0x100012D4). According to the map file, the function test() is using the memory space until 0x1000012D8 and the next function starts at 0x100001304. I'm not sure about the space within these two points? All these values are also stored in the nor flash device...
522: return; 0x100012C8 E7980185 LDR R0,[R8,R5,LSL #3] 0x100012CC E3C00001 BIC R0,R0,#0x00000001 0x100012D0 E7880185 STR R0,[R8,R5,LSL #3] 523: } 0x100012D4 E8BD8FF8 LDMIA R13!,{R3-R11,PC} 0x100012D8 544F5250 DD 0x544F5250 0x100012DC 0050495F DD 0x0050495F 0x100012E0 0A50490A DD 0x0A50490A 0x100012E4 00000000 DD 0x00000000 0x100012E8 606E6F64 DD 0x606E6F64 0x100012EC 6E6B2074 DD 0x6E6B2074 0x100012F0 7420776F DD 0x7420776F 0x100012F4 20736968 DD 0x20736968 0x100012F8 6B636170 DD 0x6B636170 0x100012FC 000A7465 DD 0x000A7465 0x10001300 68746520 DD 0x68746520 0x10001304 00000020 DD 0x00000020 39: pbuf->hdr->flag = used;
best regards Howard
SVC_Stack_Size EQU 0x00000008 ... ; Branch to interrupt handler in Supervisor mode */
Apparently, interrupt handlers are run in Supervisor mode, and only 8 bytes are allocated for Supervisor mode stack. If you have any interrupt handlers at all, 8 bytes would not be enough. The straightforward solution is to increase Supervisor stack size. Another solution is to run the interrupt handlers in User or System mode (shares stack with main program, saves memory.) I could be missing something, of course...
thank you for the hint. I was always looking at the last definition in the startup file
MSR CPSR_c, #ARM_MODE_SVC:OR:I_BIT:OR:F_BIT
where the interrupts are disabled in the supervisor mode. I've one question about the supervisor mode: in which mode will be the lowlevelinit function called in the startup file?
The straightforward solution is to increase Supervisor stack size. Another solution is to run the interrupt handlers in User or System mode (shares stack with main program, saves memory.)
The definition of the user mode (at the end of the startup file)
MSR CPSR_c, #ARM_MODE_USR
will allow all kind of interrupts (in the user mode). I'm starting the main function in the user mode, when a interrupt occurs the irqhandler in the startup file will be executed and will change the original settings of the supervisor mode (interrupts disabled)? And all the values of the interupt (+ jump back addr) will be stored in the SVC_Stack_Size?
; Branch to interrupt handler in Supervisor mode */ MSR CPSR_c, #ARM_MODE_SVC STMFD sp!, {r1-r4, r12, lr} MOV lr, pc BX r0 LDMIA sp!, {r1-r4, r12, lr} MSR CPSR_c, #ARM_MODE_IRQ | I_BIT
Could you explain me the above part a little bit?
So if I will replace the line above with
; Branch to interrupt handler in Supervisor mode */ MSR CPSR_c, #ARM_MODE_USR
the interupts will be executed in the user mode?
I've changed the size of the supervisor stack to 0x100 and the same error occurs.
The stack size, which the processor use, starts from 0x314000 and ends at 0x313E40.
The interrupt method is very small - only checking the status registers (emac receive, transmit) and setting the value of a volatile global variable, which inidicates that a new ethernet frame received.
Too many questions, and all of them are answered in the ARM Architecture Reference Manual. I have no knowledge of the AIC, so I'm afraid my advice could be completely wrong. All I know is that with the startup file you presented, you'll definitely overflow the Supervisor mode stack. That could explain all your troubles.
All I know is that with the startup file you presented, you'll definitely overflow the Supervisor mode stack. That could explain all your troubles.
Could you please tell me which configuration I have to made to avoid supervisor mode stack overflow?
; Branch to interrupt handler in User mode */ MSR CPSR_c, #ARM_MODE_USER STMFD sp!, {r1-r4, r12, lr} MOV lr, pc BX r0 LDMIA sp!, {r1-r4, r12, lr} MSR CPSR_c, #ARM_MODE_IRQ | I_BIT
Howard
This is exactly what I would try first. Of course, the problem could be caused by something completely unrelated to this...
Hi Howard,
; Exception Vectors Vectors LDR pc,=resetHandler LDR PC,Undef_Addr LDR PC,SWI_Addr LDR PC,PAbt_Addr LDR PC,DAbt_Addr Where is the Reserved Vector? LDR PC,[PC,#-0xF20] ; Vector From AIC_IVR LDR PC,[PC,#-0xF20] ; Vector From AIC_FVR Reset_Addr DCD resetHandler Undef_Addr DCD undefVector SWI_Addr DCD swiVector PAbt_Addr DCD prefetchAbortVector DAbt_Addr DCD dataAbortVector DCD 0 ; Reserved Address IRQ_Addr DCD irqVector FIQ_Addr DCD fiqVector
Did you delete anything here?
You should have 8 exception vectors here, but I only see 7.
Mmmmm........
For me, I choose to use the startup file from KEIL, because I am using KEIL's toolchain. And, I prefer not to change anything in the startup file. It is danger for me.
You're definitely right, but the Keil startup file fails if you try to boot from an external flash device. It only works when the programm starts from the internal ram or the external sdram.
The initialization of the processor is a little bit different depending on the source to boot.
The reserve vector should be available in the startup file above. The only thing which is different - comparing the map file using Keil startup and atmel startup is that the dataAbortVector get 8byte instead of 4byte as all the other vectors.
VECTOR 0x10000000 Section 168 copy of board_cstartup_keil.o(VECTOR) undefVector 0x1000003c ARM Code 0 copy of board_cstartup_keil.o(VECTOR) swiVector 0x10000040 ARM Code 0 copy of board_cstartup_keil.o(VECTOR) prefetchAbortVector 0x10000044 ARM Code 0 copy of board_cstartup_keil.o(VECTOR) dataAbortVector 0x10000048 ARM Code 0 copy of board_cstartup_keil.o(VECTOR) irqVector 0x10000050 ARM Code 0 copy of board_cstartup_keil.o(VECTOR) fiqVector 0x10000054 ARM Code 0 copy of board_cstartup_keil.o(VECTOR) !!!main 0x100000a8 Section 8 __main.o(!!!main)
Are you using an AT91SAM9263, and booting from the NOR-Flash?
Vectors LDR pc,=resetHandler LDR PC,Undef_Addr LDR PC,SWI_Addr LDR PC,PAbt_Addr LDR PC,DAbt_Addr NOP LDR PC,[PC,#-0xF20] ; Vector From AIC_IVR LDR PC,[PC,#-0xF20] ; Vector From AIC_FVR
Please add an "NOP" there, and give it a try.
(It seems some solutions for AT91SAM9263 are made by GNU toolchain.)
You are right - are you also using one of the atmel controllers?
The problem changed; now the processor is able to call the main function from the test2function() once; if I try the same code a second time, it fails.... the test2function is always called if there was an interrupt. So maybe there is something wrong with my interrupt handler in the startup file....
Right, atmel use the GNU toolchain to compile their boards.
Actually, I don't know anything about ARM9 and ATMEL MCUs.
Some related URLs:
http://www.keil.com/forum/docs/thread14628.asp
http://www.keil.com/forum/docs/thread14480.asp
http://www.keil.com/forum/docs/thread13351.asp
I'm not alone with that problem...
I will try to use the keil startup file together with my lowlevelinit function. So that the only difference between the original keil file and my startup file will be shown below.
; Reset Handler EXPORT Reset_Handler IMPORT LowLevelInit Reset_Handler ; Set pc to actual code location (i.e. not in remap zone) LDR pc, =label NOP label ; Set up temporary stack (Top of the SRAM) LDR r0, = Stack_Top ; get top of the stack MOV sp, r0 ; store top of the stack in register0 ; Call Low level init BL LowLevelInit NOP ; Cache Setup ------------------------------------------------------------------ IF ICACHE_SETUP != 0 MRC p15, 0, R0, c1, c0, 0 ; Enable Instruction Cache ORR R0, R0, #ICACHE_ENABLE MCR p15, 0, R0, c1, c0, 0 ENDIF ; Setup Stack for each mode ---------------------------------------------------- LDR R0, =Stack_Top