0

How to get actual value from SP register?

I Want to fill up whole SRAM with some initial values, but I didn't want to overwrite actual content of stack.

My startup code (which also overwrite actual content of stack):

void RESET_handler() {
    unsigned *src, *dst;
    // initialize memory
    // .....

    // fill SRAM
    dst = &_bss_end;
    while (dst < &_stacktop) {
        *dst++ = 0x55555555;
    }
}

_bss_end is end of used memory for static variables and _stacktop is pointing to end of SRAM memory or also top of stack.

Although this function is reset handler gcc make it safe and on begin push some registers into stack (more info). Yes at this point actual content of stack is irrelevant and overwriting it is safe but for clearance I would like to stop filling before stack by replacing &_stacktop with actual value of SP.

Any other ideas are also welcome except suggestion to rewrite startup code into assembler.

vlk
  • 2,581
  • 3
  • 31
  • 35
  • People advocating C standards will not like your question and my comment. What about `char *approximativeStackTop(char x) {return(&x);}` ? – Marian Aug 13 '17 at 08:38
  • I wonder what's the purpose of the whole exercise? Are you trying to debug some memory issues this way? –  Aug 13 '17 at 09:02
  • @Felix during development is nice to see how high is stack going, how much free memory do you have, is better than calculation or any static analysis. – vlk Aug 13 '17 at 09:07
  • what is the target architecture? – 0___________ Aug 13 '17 at 09:17
  • @PeterJ ARM, Cortex-M (STM32F0xx) – vlk Aug 13 '17 at 09:18
  • what are you trying to achieve with this? looks to me like you could achieve the same thing when you overwrite memory on mapping time. At any case you mention to not want to overwrite startup code in assembly, any reasons why you don't want to do this? given that in C you have a hard time setting registers. – Alexander Oh Aug 13 '17 at 09:55
  • @Alex it is done quite often by the developers. I do not know what is strange in this question and why you ask for the reason - it is obvious. – 0___________ Aug 13 '17 at 10:07
  • @PeterJ on most of the platforms I have worked this was done when pages are mapped into memory rather than startup time. – Alexander Oh Aug 13 '17 at 10:10
  • @Alex So you have not worked on the bare metal ones :) Google STM32F0 and then reconsider yout comment – 0___________ Aug 13 '17 at 10:12

1 Answers1

1

It can be done reliably only by the startup file modiffication.

I will only focus on single stack (for thread * privileged) example for openSTM32 type startup:

/* Call the clock system intitialization function.*/
    bl  SystemInit
/* Call static constructors */

    bl  fillStack  // <------------ add this

    bl __libc_init_array
/* Call the application's entry point.*/
    bl  main

Then in any of your C files implement the fillStack function. use CMSIS intrinsic instructions like __get_MSP()

0___________
  • 60,014
  • 4
  • 34
  • 74
  • Thanks for your advise, but there is a problem that my bare-metal model don't use CMSIS and I completely avoiding to use it. But I inspired how CMSIS implements `__get_MSP()` function and it is quite simple. Here is my modified reading msp: `register unsigned *msp_reg; __asm__ volatile ("mrs %0, msp\n" : "=r" (msp_reg) );` which is working as expected in my startup. – vlk Aug 13 '17 at 20:17
  • Any reason for not using the CMSIS? It is just a bunch of handy definitions, typedefs, intrinsics and inline functions. It is not a library - no overhead, no data added. CMSIS is the most bare metal - nothing but the plain hardware. – 0___________ Aug 13 '17 at 20:32
  • In my projects I have peripherals rewritten to C++ classes or structures with bitfields. I completely avoiding use of `#define` but I use all goods from C++11/14 like `namespace`, `class`, `template`, `enum class`, `auto`, bitfields, `inline` functions, ... The code is now more clean, better readable and also optimizations works well (code is small and also fast) – vlk Aug 13 '17 at 20:46
  • PS you can not use register as it is ignored if optimisations are on :) – 0___________ Aug 13 '17 at 20:48
  • Yes, but registers will be not ignored if they are connected with __asm__() ... I just tested all optimizations like -Os -O3 -Ofast .. and everywhere it is compiled correctly and code is working. – vlk Aug 13 '17 at 20:54
  • @vlk It is too hardcore programming for me :) I am too lazy :). There is another method to have potential stack overflows under control. Place your stack (or at least the exceptions stack on the top of ram. If stack overflows - you will get hardware exception - and you can handle it - for example switch off engines, turn on the alarm or just simple reset the system. It avoids "silent" data overwriting by the stack. – 0___________ Aug 13 '17 at 20:56
  • `I have peripherals rewritten to C++ classes or structures with bitfields` it will take ages in a bit more complex like F7 or advanced F4 – 0___________ Aug 13 '17 at 20:58
  • We sharing these peripherals definitions between different projects, we use only few peripherals (not all), some peripherals are same on other micros (F0, L0, F4, L4, ..) and this is not so big effort to maintain this. – vlk Aug 13 '17 at 21:16
  • @PeterJ_01 I don't see how putting your stack at the top of ram does anything useful. The ARM architecture has a descending stack. (I.e. the initial SP is set to the top of the stack which is the highest address of the memory assigned to the stack, and it decrements as stuff is pushed onto it) It overflows the stack by walking down too far in address. It would protect against underflows, but those are VERY rare with normal programming methodologies. – Russ Schultz Sep 10 '17 at 01:19
  • @Russ Schultz You did not understand what I wrote. If RAM starts at 0x20000000 and your stack has a size of 0x200 bytes, I put the stack at 0x20000200. When the stack is filled it may eventually pass the 0x20000000 address. If the something is pushed to the stack you will get BusFault. In the handler you can manage it - deciding what to do. If you place the stack in the bottom - stack will eventually (when overflow) overwrite your data - causing unrecoverable damages. I hope that is now much clearer – 0___________ Sep 10 '17 at 01:43
  • @PeterJ_01 Ah, the old 'what does the top of memory mean' problem. (I always refer to the top as highest address, but that isn't universal) – Russ Schultz Sep 10 '17 at 02:03
  • @Russ Schultz for me always top is the lowest address. Otherwise the items on the stackhave to levitate or be lighter than the air :). – 0___________ Sep 10 '17 at 02:11