A little known feature with interesting side effects, please read carefully if you are an STM8 user. |
|
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 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 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)
”.16-bit stack pointer - access to a 64 K-level stack
”.A bit confusing, isn't it?
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:
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.
The are two classes of workarounds, one for statically designed systems the other for system handling the memory dynamically.
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.
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 in few KB of RAM? very bad idea IMO, anyway:
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.