The STM8 stack limit

A little known feature with interesting side effects, please read carefully if you are an STM8 user.

The stack limit feature

The STM8 has one little known feature, the main stack has an hardware limit that makes it wrap on top of the RAM if a PUSH instruction makes it cross a hardware-defined boundary. This limit is positioned 1KB or 512B below the RAM top address depending on the STM8 model.
The curious thing is the feature is not mentioned much in the available documentation:

  • The “STM8 CPU programming manual” (PM0044, Rev2) does not mention anywhere it and states: ”The 16-bit Stack Pointer provides access to a 64K-level Stack”. This manual also mentions features that are not implemented in actual products anyway.
  • The various STM8 Reference Manuals give some hints about the feature: ”The stack pointer is decremented after data has been pushed onto the stack and incremented after data is popped from the stack. It is up to the application to ensure that the lower limit is not exceeded.” and also ”make sure the stack pointer is initialized properly (with the address given in the data sheets)”.
  • The various STM8 Data Sheets does not mention the stack limit explicitly but in the memory map picture the stack is shown as allocated in a fixed area with a clear lower limit address. Interestingly it also states ”16-bit stack pointer - access to a 64 K-level stack”.

A bit confusing, isn't it?

How it works

It is very simple, if a PUSH/PUSHW instruction (not sure about CALL, CALLF, RET, RETF, IRQ stacking but I suppose it is the same) crosses the limit then the stack returns to the position it had after reset: the higher RAM address. The limit seems to be some kind of safety measure but I wonder if it is really effective and if it is rather a problem in itself:

  • It does not prevent the application from crashing uncontrollably, there are no exceptions involved.
  • The limit can still be crossed using SUBW/ADDW instructions, and those are often used by the compilers in order to create stack frames. Once the limit is crossed the stack continues to work normally (and this is a luck as we will see later).
  • If you need a larger stack then you are out of luck unless you reposition the stack below the boundary after reset using a custom startup file.
  • The limit assumes that in a system there is a single stack, this is simply not true when a RTOS is involved (and the STM8 is a very effective architecture for a small RTOS).
  • It seems to be impossible to disable it.

The problem using an RTOS

The problem is that a preemptive RTOS has as many stacks as tasks/threads, a thread stack allocated in a memory area intersecting the boundary would lead certainly to an uncontrolled crash.

Workarounds

The are two classes of workarounds, one for statically designed systems the other for system handling the memory dynamically.

Static systems

In this case we simply have to make sure that a thread working area does not intersect the boundary. This can be done in several ways.

  • If the used RAM upper limit is lower than the stack boundary then the system is safe.
  • If the used RAM extends above the boundary then by simply examining the map file it is possible to determine if a thread working area intersects the boundary, if so the memory objects order can be rearranged manually. There are no problems if other kind of objects cross the boundary.
  • By assigning the whole stack area to the main() function thread it is assured that no object would intersect the boundary, the linker would prevent it. This may waste some RAM because unused stack space however.

Dynamic systems

Dynamic systems in few KB of RAM? very bad idea IMO, anyway:

  • Make sure than the whole heap, from which threads are allocated, does not intersect the boundary else dynamically allocated threads would not be safe and a problem may happen in any moment at runtime.
  • By assigning the whole stack area to the main() function thread it is assured that no object, including the heap, would intersect the boundary, the linker would prevent it. This may waste some RAM because unused stack space however.
 
chibios/articles/stm8_stack.txt · Last modified: 2011/10/03 20:44 by giovanni
 
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.3