c code rtos 8051
xTimeDelay equ 0FBH
_timeDelay:
/*a=counter high byte, R1=counter low byte*/
clr EA; disable interrupts
push DPH
push DPL
push 0
push b
mov b,a
mov a,running_id;running_id is a global variable in internal RAM
mov DPH,a
anl a,#0FH
add a,#taskcounters; taskcounters is address of counter array
mov R0,a; R0 point to address of counter of task running
mov a,#xTimeDelay;address of WORD variable in external RAM
mov DPL,a
mov a,R1
movx @dptr,a
inc dptr
mov a,b
movx @dptr,a
mov @R0,a
pop b
pop 0
pop DPL
pop DPH
setb EA
setb IDL; PCON.0 go to idle mode
ret
Added after 24 minutes:
This is sheduler function, it check counter array to detect which task'counter come to zero to change content in two variable: running_id and suspend_id. Then switching context routine based on these variable to switch.
_sheduler:
clr EA
push psw
push 0
...
push 7
push acc
push b
push DPH
push DPL
mov R2,#0FFh; initial task priority
mov R0,#taskcounters
mov DPH,#page; DPH=0x80
mov R1,#0Fh
mov suspend_id,running_id
_loop:
mov a,@R0
jnz _next
mov a,#priority
mov DPL,a
movx a,@dptr; get task's priority
mov b,a
subb a,R2 ; if a>R2
jnc _next ;
mov R2,b ; els if a<R2 then R2=a
mov a,#task_id
mov DPL,a
movx a,@dptr; get task's id (task_id=id OR 0x80)
mov resume_id,a
_next:
inc R0
inc DPH
djnz R1,_loop
mov running_id,resume_id
/**/
Added after 2 hours:
This context switching routine. This routine copy internal stack ponted by sp register of current task (identified by DPH) to external RAM, and then save content of DPL register to location xsp of 256 byte external RAM.
_contextSwitching:
mov a,suspend_id
mov DPH,a
clr a
mov DPL,a
save_context:
pop acc
movx @dptr,a
inc dptr
mov a,sp
cjne a,#stack,save_context
push DPL
mov a,#xsp
mov DPL,a
pop acc
movx @dptr,a
mov a,resume_id
mov DPH,a
movx a,@dptr; DPL=[xsp]
mov DPL,a
restore_context:
dec dptr
movx a,@dptr
push acc
mov a,DPL
jnz restore_context
pop DPL
pop DPH
pop b
pop acc
pop 7
...
pop 0
pop psw
reti
Added after 22 minutes:
This _timer routine called by TimerISR. When it called, this routine decrement the counters of task by one.
_timer:
push <0,1,dptr,acc,b>
mov R0,#taskcounters
mov R1,#0Fh; loop index
_tloop:
mov a,@R0
jz _tcheck
dec @R0
k1:
inc R0
djnz R1,_tloop
ret
_tcheck:
mov a,R0
subb a,#taskcounters; get id
orl a,#page; task_id=id OR 0x80
mov DPH,a
mov a,#xtimeDelay
mov DPL,a
movx a,@dptr; get high byte
jz k1
dec a
movx @dptr,a
inc dptr
movx a,@dptr; get low byte
mov @R0,a
sjmp k1