📄 kernel.s
字号:
include "8051fa.h"include "kernel.h"include "data.h"extern code mainseg data at 0RB0: ds 8 ;;; Register space.seg data at 8/* Process stack. */HW: ds 1 ;;; int **HW;Stack: ds 3 ;;; int *Stack[3];/* Interrupt descriptor table. */global SP_IE0: ds 1global SP_RI: ds 1global SP_TI: ds 1seg dataSP_BASE: ds 2 ds 0x18seg code at 0ajmp Startat 0x03; mov R0, #SP_IE0; acall Resume; retiat 0x0b; acall Process; retiDidTx: mov R0, #SP_TI; acall Resume; retiDidRx: mov R0, #SP_RI; acall Resume; retiat 0x23 jbc TI, DidTx clr RIsjmp DidRxat 0x2b jnb EXF2, DidTF2 jnb TF2, DidEXF2sjmp DidBothat 0x33 jb PCF, DequeueHigh jnb CF, DequeueLowsjmp UpdateStatusDidBoth: mov A, RCAP2H jb ACC.7, DidEXF2 ;;; This determines if TF2 or EXF2 was first.DidTF2: clr TF2 acall TickretiDidEXF2: clr EXF2 djnz Sector0, 1f mov Sector0, #SECTORS mov TIME0 + 0, RCAP2L mov TIME0 + 1, RCAP2H mov TIME0 + 2, TIME + 0 mov TIME0 + 3, TIME + 1 setb TC0 1:retiEndSeg = $;;; Software to insert to handle 5 additional falling edge capture counters.;;; This will resolve multiple EC interrupts in such a way that;;; captures that occur before timer overflows are handled first.seg data at 0x20global CSTATUS: ds 1 ;;; High-priority interrupt queue.global PCF bit CSTATUS.7global PCF0 bit CSTATUS.0global PCF1 bit CSTATUS.1global PCF2 bit CSTATUS.2global PCF3 bit CSTATUS.3global PCF4 bit CSTATUS.4seg code at EndSegUpdateStatus: ;;; Update CSTATUS setb PCF1: jnb CCF0, 1f; mov A, CCAP0H; mov C, ACC.7; mov PCF0, C1: jnb CCF1, 1f; mov A, CCAP1H; mov C, ACC.7; mov PCF1, C1: jnb CCF2, 1f; mov A, CCAP2H; mov C, ACC.7; mov PCF2, C1: jnb CCF3, 1f; mov A, CCAP3H; mov C, ACC.7; mov PCF3, C1: jnb CCF4, 1f; mov A, CCAP4H; mov C, ACC.7; mov PCF4, C1:DequeueHigh: ;;; Dequeue high priority flags. jbc PCF0, DoCCF0 jbc PCF1, DoCCF1 jbc PCF2, DoCCF2 jbc PCF3, DoCCF3 jbc PCF4, DoCCF4DoCF: clr PCF clr CF acall CTickretiDequeueLow: ;;; Dequeue low priority flags. jbc CCF0, DidCCF0 jbc CCF1, DidCCF1 jbc CCF2, DidCCF2 jbc CCF3, DidCCF3DoCCF4: clr CCF4DidCCF4: djnz Sector5, 1f mov Sector5, #SECTORS mov (TIME5 + 0), CCAP4L mov (TIME5 + 1), CCAP4H mov (TIME5 + 2), (CTIME + 0) mov (TIME5 + 3), (CTIME + 1) setb TC5 1:retiDoCCF3: clr CCF3DidCCF3: djnz Sector4, 1f mov Sector4, #SECTORS mov (TIME4 + 0), CCAP3L mov (TIME4 + 1), CCAP3H mov (TIME4 + 2), (CTIME + 0) mov (TIME4 + 3), (CTIME + 1) setb TC4 1:retiDoCCF2: clr CCF2DidCCF2: djnz Sector3, 1f mov Sector3, #SECTORS mov (TIME3 + 0), CCAP2L mov (TIME3 + 1), CCAP2H mov (TIME3 + 2), (CTIME + 0) mov (TIME3 + 3), (CTIME + 1) setb TC3 1:retiDoCCF1: clr CCF1DidCCF1: djnz Sector2, 1f mov Sector2, #SECTORS mov (TIME2 + 0), CCAP1L mov (TIME2 + 1), CCAP1H mov (TIME2 + 2), (CTIME + 0) mov (TIME2 + 3), (CTIME + 1) setb TC2 1:retiDoCCF0: clr CCF0DidCCF0: djnz Sector1, 1f mov Sector1, #SECTORS mov (TIME1 + 0), CCAP0L mov (TIME1 + 1), CCAP0H mov (TIME1 + 2), (CTIME + 0) mov (TIME1 + 3), (CTIME + 1) setb TC1 1:reti;;; Pulse input scheduler;;; When SECTORS (20) pulse inputs are counted from an input source, one full;;; nutation is marked off, the time of that nutation is saved in the;;; corresponding TIMEn variable, and the sector count is reset. TCn marks this;;; event. At regular intervals a pending input is dequeued by looking for and;;; resetting the first marked TCn flag.;;; FXn is used to mark the first nutation in a test. It is cleared thereafter.seg data at 0x21global TSTATUS: ds 1 ;;; Pulse-counter queue.global TC0 bit TSTATUS.0global TC1 bit TSTATUS.1global TC2 bit TSTATUS.2global TC3 bit TSTATUS.3global TC4 bit TSTATUS.4global TC5 bit TSTATUS.5global State: ds 1global FX0 bit State.0global FX1 bit State.1global FX2 bit State.2global FX3 bit State.3global FX4 bit State.4global FX5 bit State.5global FXX bit State.6global Counter: ds 1seg codePROCESS_RATE equ 2000global Scheduler: mov TL0, #low(-PROCESS_RATE) mov TH0, #high(-PROCESS_RATE) clr TF0 setb TR0 setb ET0retProcess: ;;; "Pause on TF0" clr ET0 clr TR0 jbc TC0, ResumeX0 ;;; Dequeue input from pulse-counter queue. jbc TC1, ResumeX1 jbc TC2, ResumeX2 jbc TC3, ResumeX3 jbc TC4, ResumeX4 jbc TC5, ResumeX5sjmp SchedulerFirstPartial: acall Partialsjmp SchedulerNext: acall Nutationsjmp SchedulerResumeX0: mov Counter, #0 jbc FX0, FirstPartialsjmp NextResumeX1: mov Counter, #1 jbc FX1, FirstPartialsjmp NextResumeX2: mov Counter, #2 jbc FX2, FirstPartialsjmp NextResumeX3: mov Counter, #3 jbc FX3, FirstPartialsjmp NextResumeX4: mov Counter, #4 jbc FX4, FirstPartialsjmp NextResumeX5: mov Counter, #5 jbc FX5, FirstPartialsjmp NextStart: ;;; Install main(), set its return address to Idle(). mov HW, #Stack ;;; HW = &Stack[0]; mov SP, #(SP_BASE - 1) ;;; SP = SP_BASE - 1; mov DPTR, #Exit push DPL push DPH ;;; @SP++ = Exit(); acall mainIdle: orl PCON, #1sjmp Idleglobal Spawn: ;;; int Spawn(int @R0, void *(DPTR())) { mov R1, HW mov @R1, SP inc HW ;;; @HW++ = SP; dec R0 mov SP, R0 ;;; SP = --R0; acall Enter ;;; (*DPTR)();Exit: dec HW mov R0, HW mov SP, @R0 ;;; SP = @--HW;ret ;;; }Enter: push DPL push DPHretglobal Pause: ;;; void Pause(int @@R0) { mov @R0, SP ;;; @R0 = SP; dec HW mov R0, HW mov SP, @R0 ;;; SP = @--HW;ret ;;; "idle until resume";global Resume: mov R1, HW mov @R1, SP inc HW ;;; @HW++ = SP; mov SP, @R0 ;;; SP = @R0;ret ;;; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -