X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=kern%2Fswitch_avr.S;h=93892919ff483d5bdae0a915042c2fd799c00605;hb=49d4f9b278ec7da35bbf2dcd3f5013940d1a74e3;hp=84fa14d3287af07337649412ce29d9a2e8bd3233;hpb=5f3952176a4e9a00ca8dd5ec4a6b994958f89e0a;p=bertos.git diff --git a/kern/switch_avr.S b/kern/switch_avr.S index 84fa14d3..93892919 100644 --- a/kern/switch_avr.S +++ b/kern/switch_avr.S @@ -26,10 +26,15 @@ .globl asm_switch_context asm_switch_context: +; r0 is the TEMP REG and can be used freely. +; r1 is the ZERO REG and must always contain 0. +; +; Stack frame is 19 byte, remember to update +; CPU_SAVED_REGS_CNT if you change pushed regs. + in r0,SREG-__SFR_OFFSET push r0 -; push r0 caller-save -; push r1 caller-save +; push r1 ;zero-reg push r2 push r3 push r4 @@ -46,48 +51,58 @@ asm_switch_context: push r15 push r16 push r17 -; push r18 caller-save -; push r19 caller-save -; push r20 caller-save -; push r21 caller-save -; push r22 caller-save -; push r23 caller-save -; push r24 caller-save -; push r25 caller-save -; push r26 caller-save -; push r27 caller-save +; push r18 ;caller-save +; push r19 ;caller-save +; push r20 ;caller-save +; push r21 ;caller-save +; push r22 ;caller-save +; push r23 ;caller-save +; push r24 ;caller-save +; push r25 ;caller-save +; push r26 ;caller-save +; push r27 ;caller-save push r28 push r29 -; push r30 caller-save -; push r31 caller-save +; push r30 ;caller-save +; push r31 ;caller-save -; First parameter (new_sp) is in r24:r25, second (save_sp) in r22:r23 +; First parameter (new_sp) is in r24:r25, second (save_sp) in r22:r23 - in r0,SPL-__SFR_OFFSET ; r0:r1 = SP - in r1,SPH-__SFR_OFFSET + in r18,SPL-__SFR_OFFSET ; r18:r19 = SP + in r19,SPH-__SFR_OFFSET movw r26,r22 ; X = save_sp - st X+,r0 ; *save_sp = SP - st X,r1 + st X+,r18 ; *save_sp = SP + st X,r19 movw r26,r24 ; X = new_sp - ld r0,X+ - ld r1,X - out SPL-__SFR_OFFSET,r0 ; SP = *new_sp - out SPH-__SFR_OFFSET,r1 + ld r18,X+ + ld r19,X + +; Set new stack pointer. +; AVR is an 8 bit processor so +; care must be taken when updating +; SP that is a 16 bit reg. +; Two instructions are required to update SP +; so an IRQ can sneak in between them. +; So IRQ *MUST* be disabled and then restored. + cli ; Disable interrupt + out SPL-__SFR_OFFSET,r18 ; SP = *new_sp + out SPH-__SFR_OFFSET,r19 + out SREG-__SFR_OFFSET,r0 ; Restore previous IRQ state -; pop r31 caller-save -; pop r30 caller-save +; pop r31 ;caller-save +; pop r30 ;caller-save pop r29 pop r28 -; pop r27 caller-save -; pop r26 caller-save -; pop r25 caller-save -; pop r24 caller-save -; pop r23 caller-save -; pop r22 caller-save -; pop r21 caller-save -; pop r20 caller-save -; pop r19 caller-save -; pop r18 caller-save +; pop r27 ;caller-save +; pop r26 ;caller-save +; pop r25 ;caller-save +; pop r24 ;caller-save +; pop r23 ;caller-save +; pop r22 ;caller-save +; pop r21 ;caller-save +; pop r20 ;caller-save +; pop r19 ;caller-save +; pop r18 ;caller-save pop r17 pop r16 pop r15 @@ -104,8 +119,7 @@ asm_switch_context: pop r4 pop r3 pop r2 -; pop r1 caller-save -; pop r0 caller-save +; pop r1 ;zero-reg pop r0 out SREG-__SFR_OFFSET,r0