Doe Keil IDE support initializing stack space with a constant? For example with a #define. If not, please does someone have ARM Cortex M3/M4 assembler code to do that and where should it be located? For example in startup*.s prior to the branch to main?
For example in startup*.s prior to the branch to main?
Did you look at any of the Keil examples?
Here is an extract from a startup file, taken from one of the cortex examples:
; <h> Stack Configuration ; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> ; </h> Stack_Size EQU 0x00000200 AREA STACK, NOINIT, READWRITE, ALIGN=3 Stack_Mem SPACE Stack_Size __initial_sp
Yes. I did look at this. How would I modify it to load the stack space with 0xcc for example?
You could:
1 - Edit the file (the EQU) directly, or 2 - Open the file in uVision IDE, select the 'configuration wizard' tab and change the value there.
Easy.
You don't address the question. I want to fill the stack, not change its size. My Config wizard only has a size definition.
Sorry, I missed an important detail of what you were saying :(
I don't know of a direct way, but the startup module knows where the stack starts, it also contains the length. You could simply add the necessary small block of code within the startup module. No?
OK ... and "the necessary small block of code" is?
A little bit of assembler with a loop storing your constant value should suffice.
You don't really expect me to draw it out do you?
I'm feeling generous (and had a few bored moments). This might be an acceptable start:
; Reset Handler Reset_Handler PROC EXPORT Reset_Handler [WEAK] IMPORT __main LDR R0, =Stack_Mem ;Added LDR R1, =Stack_Size ; LDR R2, =0xCCCCCCCC ; Fill STR R2, [R0], #4 ; SUBS R1,#4 ; BNE Fill ; LDR R0, =__main BX R0 ENDP
Thanks. I'll try that. After your build up ... it should work!
OK so the Reset Handler now looks like this,
; Reset handler Reset_Handler PROC EXPORT Reset_Handler [WEAK] IMPORT SystemInit IMPORT __main LDR R0, =SystemInit BLX R0 LDR R0, =Stack_Mem ;Added LDR R1, =Stack_Size ; LDR R2, =0xCCCCCCCC ; Fill STR R2, [R0], #4 ; SUBS R1,#4 ; BNE Fill ; LDR R0, =__main BX R0 ENDP
It works! Thanks for your help. I have one more question.
I checked the fill worked by getting the STACK address from the *.map file. Why doesn't typing "STACK" or "Stack_Mem" etc. directly into the "Memory 1" Memory Window work?
In other words, how can I use a symbolic name in the IDE debugger to view the stack content?
It works!
Glad to be of help [in the end].
Sorry, but I will have to let someone else (who might know the answer) respond to that one.
There's a caveat. Although it works as I step through the assembler ... as soon as the program jumps to main the STACK gets overwritten and cleared to zero despite its AREA being marked NOINIT. Please does anyone have any idea why this happens and how to stop it?
Hmmm.
The area gets cleared by the scatter loader (executed between startup and entry to main).
This is where I have previously started using a slightly more complex scatter file. Using an UNINIT section for the segment that I din't want to be touched by the scatter loader.
OK. Thanks for the hint. I see the project's scatter file *.sct in \Obj\ folder and that I can specify a different one by unchecking the target Options/Linker/Use Memory Layout from Target Dialog checkbox.
So how do I get the STACK into an UNINIT'd section please? ... or where can I find instructions to make a new scatter file?
Sorry, I don't have much time now ... but here's a scatter file I've modified from one of the Blinky examples. I gave it a quick try and the stack is not now being cleared.
In the IDE, select this one (or the one that you'll modify accordingly).
LR_ROM1 0x00000000 0x04000000 { ; load region size_region ER_ROM1 0x00000000 0x04000000 { ; load address = execution address *.o (RESET, +First) *(InRoot$$Sections) .ANY (+RO) } RW_RAM1 0x20000000 0x00400000 { ; RW data .ANY (+RW +ZI) } RW_STACK +0 UNINIT ALIGN 16 ; RW data - Stack <<< THIS SECTION IS WHAT I ADDED { *.o (Stack) } }