I was trying to write a register context saving/restoring when I came across a weird behaviour.
My code (sorry, tried to format tens of times, but the editor WANTS to make asm a table):
When the exception is returned from, the calling function:
msg = "returned from SVC\r\n";
serial_io.put_string(msg, util_str_len(msg)+1);
asm volatile (
);
msg = "cpsr = ";
util_word_to_hex(scratchpad, tmp1);
serial_io.put_string(scratchpad, 9);
serial_io.put_string("\r\n", 3);
outputs "returned from SVC" and "cpsr = 60000013".
Why the "00000002"? the barriers don't seem to have any effect.
Uhm, what I mean is that a single LDM is approximately twice as fast as the two instructions POP + PUSH.
-Thus you will not have to use POP+PUSH, but can just read the contents of the stack and avoid writing to it.
The registers need to be loaded from the stack, that is correct, because they do not contain any defined value on interrupt entry.
Thus instead of ...
pop {r0-r3}
push {r0-r3}
... you can write ...
ldm sp,{r0-r3}
... which only reads the registers.
dbg_out is allowed to corrupt r2 and r3 as well, which I think is why you see the strange value you mentioned earlier.
I did not know about the 8-byte alignment requirement.
-But remember to restore SP to its original value before you return; either by saving the entire value of SP or by adding the difference back, otherwise you'll get a crash.
Ah, stupid me. That's what you ment - no writeback -> no write back...
"dbg_out is allowed to corrupt r2 and r3 as well"
Yes, allowed, but it doesn't - checked the disassembly.
"But remember to restore SP..."
I wrote them as pair. That way you don't forget, and it's easier to write one as "mirror image" of the other.
If you wrote the entire dbg_out yourself, it probably won't change r2 and r3.
What I'm most worried about is that if it's written in C, the C-compiler will optimize it at some later point, so it changes r2 and r3.
If dbg_out calls another C-routine, which you didn't write, then it's very much in danger of being unpredictable, regarding which registers it uses.
If you've written dbg_out in assembly language, then begin the routine by saving r0-r3 and r12 (since it's a debugging routine), then you won't have the problem at a later point).
-But it's great to see you found the error; this one is difficult to spot.
The dbg_out was written in C, but only used for debugging that situation. It's already removed.