#include <cpu/types.h>
#include <cpu/attr.h>
#include <cfg/debug.h>
+#include <cfg/module.h>
#include <cfg/arch_config.h> /* ARCH_EMUL */
#include <cfg/macros.h> /* ABS() */
#endif
}
+MOD_DEFINE(proc);
void proc_init(void)
{
/* Make sure the assembly routine is up-to-date with us */
ASSERT(asm_switch_version() == 1);
+ MOD_INIT(proc);
}
*/
void proc_schedule(void)
{
- /* This function must not have any "auto" variables, otherwise
- * the compiler might put them on the stack of the process
- * being switched out.
- */
- static struct Process *old_process;
- static cpuflags_t flags;
+ struct Process *old_process;
+ cpuflags_t flags;
/* Remember old process to save its context later */
old_process = CurrentProcess;
*/
if (CurrentProcess != old_process)
{
- static cpustack_t *dummy;
+ cpustack_t *dummy;
#if CONFIG_KERN_PREEMPTIVE
/* Reset quantum for this process */
*/
void proc_switch(void)
{
- /* Just like proc_schedule, this function must not have auto variables. */
- static cpuflags_t flags;
+ cpuflags_t flags;
IRQ_SAVE_DISABLE(flags);
SCHED_ENQUEUE(CurrentProcess);
.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
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
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