X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=kern%2Fswitch_avr.S;h=93892919ff483d5bdae0a915042c2fd799c00605;hb=3d3ba5cae20af3f5d1a75d7a3d727a2199160137;hp=266a77e4bd1ed08a39e27e00d99b028d0f26cb53;hpb=1cc167e20f21d2e81527ca47ccd4a21a6198f86f;p=bertos.git diff --git a/kern/switch_avr.S b/kern/switch_avr.S old mode 100755 new mode 100644 index 266a77e4..93892919 --- a/kern/switch_avr.S +++ b/kern/switch_avr.S @@ -3,7 +3,7 @@ * * * \brief AVR context switch @@ -16,12 +16,25 @@ #include +/* + * NOTE: At each change of this function affecting proc.c + * (i.e. arguments, data stored in the stack) bump up version + * number in asm_switch_version(). + */ + /* void asm_switch_context(void **new_sp, void **save_sp) */ .globl asm_switch_context asm_switch_context: -; push r0 caller-save -; push r1 caller-save +; 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 r1 ;zero-reg push r2 push r3 push r4 @@ -38,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 @@ -96,7 +119,17 @@ 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 ret + + +/* int asm_switch_version(void) */ +.globl asm_switch_version +asm_switch_version: + ldi r24,lo8(1) + ldi r25,hi8(1) + ret +