Hi Guys!
I was debugging my context switching code, when i realised i have made a mistake that would come to haunt me when i eventually implemented un-privilaged tasks.
On an IRQ I..
1) Push R0..R12 onto the stack.
2) Push LR onto the stack ( The PC of the interrupted task )
3) Copy the MODE flags from SPSR to CPSR and read the SP and LR registers to get the interrupted tasks SP and LR.
4) Restore CPSR mode flags.
5) Service the IRQ.
6) Call my scheduler... This coppies the CPU state from the stack, and modifies the stack with data from the task to be awakened.
7) Pop CPU state off the stack, and return from iterrups.
Point 3 is my problem!
When the interrupted task is un-privilaged, switching to unprivilaged mode to read the LR and SP would lose the ability to switch back to the IRQ mode.
I realise that there instructions to read banked registers, but they are not supported by all arm CPU's.
What is the correct, portable way of doing this in armv7a ??
The cpu state push/pop code is in _my_IRQ_handler
https://github.com/chris-stones/ShovelO ... /context.S
The very primitive *scheduler* (essentially an array of states to memcpy!):
https://github.com/chris-stones/ShovelO ... /kthread.c
Thanks for any input!
Chris.
my buggy armv7a context switching.
Re: my buggy armv7a context switching.
Answering my own question, incase anyone else was confused by this.
For reading the banked registers of privilaged modes, one should switch to that mode, read the registers into unbanked registers, and switch back again.
For the special case of USER mode, where writing to 'CPSR.mode' is not allowed, one should use the special structions.
LDM[cond][type] Rn[!], {SP,LR}^
and
STM[cond][type] Rn[!], {SP,LR}^
Its not pretty, as interrupt-heade/footerr code needs to follow different paths depending on the 'SPSR.mode', but is seems to be the only way to accumplish this.
ENJOY.
For reading the banked registers of privilaged modes, one should switch to that mode, read the registers into unbanked registers, and switch back again.
For the special case of USER mode, where writing to 'CPSR.mode' is not allowed, one should use the special structions.
LDM[cond][type] Rn[!], {SP,LR}^
and
STM[cond][type] Rn[!], {SP,LR}^
Its not pretty, as interrupt-heade/footerr code needs to follow different paths depending on the 'SPSR.mode', but is seems to be the only way to accumplish this.
ENJOY.