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.
I am attempting to do something that seemed simple, but it is turning into a mess. I want to write a stack underflow monitor in main that both checks the stack pointer to insure it is at the bottom, and checks a byte under the stack bottom for a pattern (to better insure that the stack never went under when it was outside of main).
I've come to find that you cannot compile the following statement:
unsigned char * data StackPtr _at_ 0x81; (because it is an sfr address)
It seems like this should be the same thing as: sfr SP = 0x81; ..but with the added benefit of being able to dereference StackPtr to get at what it is pointing at.
The plan was to enter main at power-up, get the address SP is pointing at, stuff a pattern in there like 0xAA, then increment the SP. Later, when it returns to main, the test verfies the SP is still pointing at the SP++ address, and the original SP pattern is still 0xAA.
Assembler seems my only way out.
I should have mentioned that I need to try and maintain MISRA-C compliance.
unsigned char start_SP = SP; MAIN.C(91): error C247: non-address/-constant initializer
But the typecasting inspired another means.
void main(void) { *(uint8_t data *)SP = 0xAAu; SP++; ... if((SP != &stackbot[0]) || (*(uint8_t data *)(SP-1) != 0xAAu)) { //fail } }
'stackbot' I stuck in the startup file and defined it in the header file as:
extern uint8_t const idata stackbot[];
I needed to put the 'data' keyword in there because the compiler must have thought it was generic pointer, and stuffed all sorts of useless instructions in there.
It compiles and runs like it should. The thing I can't figure out is what is causing the compiler to put in extra instructions...
267: if((SP != &stackbot[0]) || (*(uint8_t data *)(SP-1) != 0xAAu)) C:0x0264 AF81 MOV R7,SP(0x81) C:0x0266 7E00 MOV R6,#xFPage(0x00) C:0x0268 747E MOV A,#STACKBOT(0x7E) C:0x026A B5070D CJNE A,0x07,C:027A C:0x026D EE MOV A,R6 C:0x026E B40009 CJNE A,#xFPage(0x00),C:027A C:0x0271 E581 MOV A,SP(0x81) C:0x0273 14 DEC A C:0x0274 F8 MOV R0,A C:0x0275 E6 MOV A,@R0 C:0x0276 64AA XRL A,#EMI0CN(0xAA) C:0x0278 6007 JZ C:0281
I'm using the compact memory model
if((SP != (uint8_t)&stackbot[0]) || (*(uint8_t data *)(SP-1) != 0xAAu))
That fixed it! Thanks for the help.
I screwed this up badly. I should have incremented SP, then put in the 0xAA pattern. Then the SP-1 down below should have simply been 'SP'.
The stack pointer always increments before something gets pushed onto the stack.
(I inadvertently stuffed 0xAA into a variable, instead of onto the actual stack bottom) Someday someone will also want to do this, and it would be easier if it were posted correctly.