;++++++++++++++++++++++++++++++++++++++++
; ZealMon : Z80 simple real time monitor
; Ver 0.01 2023/10/03 by skyriver
;+++++++++++++++++++++++++++++++++++++++
;
; TCB
; name ofst byte mearn
; TcList 0 : 2 address for TCB link
; TcTskNo 2 : 1 high nibble:priority(0:highest) low nibble:task No.
; TcTim 3 : 1 timer count
; TcEvCnt 4 : 1 how many waiting event except timer
; TcSP 5 : 2 stack pointer save area
; TcStat 7 : 1 task status !! not used !!
; 0 : not regist
; 1 : running
; 2 : ready
; 3 : wait
0008 TCBSIZ EQU 8 ; TCB size
0000 TcTop EQU 0 ; define offset
0000 TcList EQU TcTop
0002 TcTskNo EQU 2
0003 TcTim EQU 3
0004 TcEvCnt EQU 4
0005 TcSP EQU 5
0007 TcStat EQU 7
; TCBTBL 4 byte 0:top priority(not used)
;
0000 tcSt_NO EQU 0 ; not regist
0001 tcSt_RUN EQU 1 ; running
0002 tcSt_RDY EQU 2 ; ready
0003 tcSt_WAT EQU 3 ; wait
0004 MAX_PRI EQU 4 ; max priority
0000 PRI0 EQU 00H ; highest
0010 PRI1 EQU 10H
0020 PRI2 EQU 20H
0030 PRI3 EQU 30H ; lowest
000F MSKTNO EQU 00FH ; task No. bit mask
00F0 MSKPRI EQU 0F0H ; priority bit mask
0000' ASEG
ORG 0100H
0100 21 2000 INIRTM: LD HL,WORKST
0103 11 2001 LD DE,WORKST + 1
0106 01 002A LD BC,WORKSIZ - 1
0109 36 00 LD (HL),0
010B ED B0 LDIR
010D 21 0232 LD HL,INITCB
0110 11 2009 LD DE,TCB0
0113 01 0020 LD BC,TCBSIZ * TASKS
0116 ED B0 LDIR
0118 11 7FFF LD DE,STACK - 1
011B 21 0261 LD HL,TENTRY + 2 * ( TASKS - 1 ) + 1
011E 3E 04 LD A,TASKS
0120 01 0002 INIR10: LD BC,2 ; set return addres(=task entry)
0123 ED B8 LDDR
0125 E5 PUSH HL
0126 21 FFC2 LD HL,-(TSKSPSIZ - 2)
0129 19 ADD HL,DE
012A EB EX DE,HL
012B E1 POP HL
012C 3D DEC A
012D 20 F1 JR NZ,INIR10
012F 21 2009 LD HL,TCB0
0132 06 04 LD B,TASKS
0134 C5 INIR20: PUSH BC
0135 CD 018C CALL ADDRDY
0138 C1 POP BC
0139 11 0008 LD DE,TCBSIZ
013C 19 ADD HL,DE
013D 10 F5 DJNZ INIR20
013F F3 DI
0140 ED 73 1000 LD (SavSP),SP
0144 CD 0276 CALL IniAp
; dispatch task
; select ready task and run it
;
0147 DISPATCH:
0147 21 2001 LD HL,RDYLNK
014A 06 04 LD B,MAX_PRI
014C 7E DISP10: LD A,(HL)
014D 23 INC HL
014E B6 OR (HL)
014F 23 INC HL
0150 20 04 JR NZ,DISPFND ; find ready
0152 10 F8 DJNZ DISP10
0154 F3 DI ; TASK0(=idle task) is always ready
0155 76 HALT ; not exec here
0156 DISPFND:
0156 2B DEC HL
0157 2B DEC HL ; HL = RDYLINK
0158 CD 016F CALL REMOVE
REPT TcTskNo - TcTop
INC HL
ENDM
015B 23 + INC HL
015C 23 + INC HL
015D 7E LD A,(HL) ; get task No.
015E 32 2000 LD (RUNTSK),A
REPT TcSP - TcTskNo
INC HL
ENDM
0161 23 + INC HL
0162 23 + INC HL
0163 23 + INC HL
0164 5E LD E,(HL)
0165 23 INC HL
0166 56 LD D,(HL)
0167 EB EX DE,HL
0168 F9 LD SP,HL
0169 F1 POP AF
016A C1 POP BC
016B D1 POP DE
016C E1 POP HL
016D FB EI
016E C9 RET
; remove from link
; HL <- link addr(not empty link)
; HL -> removed tail TCB addr
;
016F 4E REMOVE: LD C,(HL)
0170 23 INC HL
0171 46 LD B,(HL)
0172 2B DEC HL
0173 78 LD A,B
0174 B1 OR C
0175 20 04 JR NZ,REMO10
0177 F3 DI
0178 C3 0178 JP $
017B EB REMO10: EX DE,HL
017C 69 LD L,C
017D 60 LD H,B
017E 4E LD C,(HL)
017F 23 INC HL
0180 46 LD B,(HL)
0181 2B DEC HL ; BC = next
0182 79 LD A,C
0183 B0 OR B
0184 20 F5 JR NZ,REMO10 ; HL = tail TCB, DE = prev
0186 EB EX DE,HL
0187 77 LD (HL),A ; A = 0
0188 23 INC HL
0189 77 LD (HL),A
018A EB EX DE,HL
018B C9 RET
; add TCB to ready que
; HL <- TCB
; HL -> TCB
018C ADDRDY:
REPT TcTskNo - TcTop
INC HL
ENDM
018C 23 + INC HL
018D 23 + INC HL
018E 7E LD A,(HL) ; get task No. & priority
REPT TcTskNo - TcTop
DEC HL
ENDM
018F 2B + DEC HL
0190 2B + DEC HL
0191 E6 F0 AND MSKPRI
0193 0F RRCA
0194 0F RRCA
0195 0F RRCA
0196 5F LD E,A
0197 16 00 LD D,0 ; DE = pri * 2
0199 E5 PUSH HL ; save TCB
019A 21 2001 LD HL,RDYLNK
019D 19 ADD HL,DE
019E D1 POP DE
019F CD 0205 CALL AddLnk ; HL = TCB
01A2 C9 RET
; timer interrupt
; if exist timer wait task, then dec timer and if time up, add rady task link
;
01A3 Timer:
01A4 SavINT EQU $ + 1 ; original int addr
01A3 CD 0000 CALL 0
01A6 F3 Tim00: DI
01A7 E5 PUSH HL
01A8 D5 PUSH DE
01A9 C5 PUSH BC
01AA F5 PUSH AF
01AB CD 021F CALL SaveSP ; save SP into TCB
01AE CD 018C CALL ADDRDY ; add running TCB to ready link
01B1 2A 2029 LD HL,(TIMLNK) ; timer wait task link
01B4 11 2029 LD DE,TIMLNK
01B7 18 1B JR Tim30
01B9 E5 Tim10: PUSH HL
REPT TcTim - TcTop
INC HL
ENDM
01BA 23 + INC HL
01BB 23 + INC HL
01BC 23 + INC HL
01BD 35 DEC (HL) ; decrement timer value
01BE E1 POP HL
01BF 4E LD C,(HL)
01C0 23 INC HL
01C1 46 LD B,(HL) ; BC = next link
01C2 2B DEC HL
01C3 20 0C JR NZ,Tim20
01C5 C5 PUSH BC
01C6 D5 PUSH DE
01C7 CD 018C CALL ADDRDY
01CA D1 POP DE
01CB C1 POP BC ; DE -> (HL:unlink) -> BC
01CC EB EX DE,HL
01CD 71 LD (HL),C
01CE 23 INC HL
01CF 70 LD (HL),B ; unlink from link
01D0 2B DEC HL
01D1 59 Tim20: LD E,C
01D2 50 LD D,B ; DE = next timer waiting task's TCB
01D3 EB EX DE,HL
01D4 7C Tim30: LD A,H
01D5 B5 OR L
01D6 20 E1 JR NZ,Tim10
01D8 C3 0147 JP DISPATCH
; timer wait
; A <- timer value
;
01DB F3 TWait: DI
01DC E5 PUSH HL
01DD D5 PUSH DE
01DE C5 PUSH BC
01DF F5 PUSH AF
01E0 4F LD C,A
01E1 CD 021F CALL SaveSP ; save running task's SP into TCB, HL = TCB
01E4 E5 PUSH HL
REPT TcTim - TcTop
INC HL
ENDM
01E5 23 + INC HL
01E6 23 + INC HL
01E7 23 + INC HL
01E8 71 LD (HL),C ; set timer
01E9 D1 POP DE ; DE = TCB
01EA 21 2029 LD HL,TIMLNK ; ADD TCB to TIMLNK
01ED CD 0205 CALL AddLnk
01F0 C3 0147 JP DISPATCH
; get running TCB addr
; HL -> TCB
;
01F3 GetRTcb:
01F3 3A 2000 LD A,(RUNTSK)
01F6 E6 0F AND MSKTNO
01F8 87 ADD A,A
01F9 5F LD E,A
01FA 16 00 LD D,0
01FC 21 0252 LD HL,TCBTBL
01FF 19 ADD HL,DE
0200 5E LD E,(HL)
0201 23 INC HL
0202 56 LD D,(HL)
0203 EB EX DE,HL ; HL = TCB
0204 C9 RET
; add TCB to link
; HL <- LINK addr
; DE <- TCB addr
; HL -> TCB
;
0205 4E AddLnk: LD C,(HL)
0206 23 INC HL
0207 46 LD B,(HL)
0208 72 LD (HL),D
0209 2B DEC HL
020A 73 LD (HL),E
020B EB EX DE,HL
020C 71 LD (HL),C
020D 23 INC HL
020E 70 LD (HL),B
020F 2B DEC HL
0210 C9 RET
; run next ready task(round robin)
;
0211 F3 ROBIN: DI
0212 E5 PUSH HL
0213 D5 PUSH DE
0214 C5 PUSH BC
0215 F5 PUSH AF
0216 CD 021F CALL SaveSP ; save SP into TCB
0219 CD 018C CALL ADDRDY
021C C3 0147 JP DISPATCH
; set SP into TCB
; HL -> TCB
;
021F SaveSP:
021F CD 01F3 CALL GetRTcb ; get running task's TCB
0222 E5 PUSH HL ; save TCB
0223 11 0005 LD DE,TcSP - TcTop
0226 19 ADD HL,DE
0227 EB EX DE,HL ; DE = TCB's SP save addr
0228 21 0004 LD HL,4 ; CALL THIS + PUSH HL
022B 39 ADD HL,SP
022C EB EX DE,HL
022D 73 LD (HL),E
022E 23 INC HL
022F 72 LD (HL),D ; save SP
0230 E1 POP HL ; HL = TCB
0231 C9 RET
; ++++++++++ test apprication ++++++++
0004 TASKS EQU 4 ; how many task
0040 TSKSPSIZ EQU 40H ; tasks stack size
8000 STACK EQU 8000H ; stack pointer
000A STREGSIZ EQU 10 ; PC & reg area size on stack
; *** TCB initial data ***
0000 TSK0NoO EQU 0
0001 TSK0No1 EQU 1
0002 TSK0No2 EQU 2
0003 TSK0No3 EQU 3
7FF6 STACK3 EQU STACK - STREGSIZ
7FB6 STACK2 EQU STACK3 - TSKSPSIZ
7F76 STACK1 EQU STACK2 - TSKSPSIZ
7F36 STACK0 EQU STACK1 - TSKSPSIZ
0232 INITCB:
; task0 : idle
0232 0000 DW 0 ; link
0234 30 DB TSK0NoO OR PRI3 ; task No.
0235 00 DB 0 ; timer
0236 00 DB 0 ; event
0237 7F36 DW STACK0 ; stack
0239 02 DB tcSt_RDY ; status(ready)
; task1
023A 0000 DW 0 ; link
023C 01 DB TSK0No1 OR PRI0 ; task No.
023D 00 DB 0 ; timer
023E 00 DB 0 ; event
023F 7F76 DW STACK1 ; stack
0241 02 DB tcSt_RDY ; status(ready)
; task2
0242 0000 DW 0 ; link
0244 02 DB TSK0No2 OR PRI0 ; task No.
0245 00 DB 0 ; timer
0246 00 DB 0 ; event
0247 7FB6 DW STACK2 ; stack
0249 02 DB tcSt_RDY ; status(ready)
; task3
024A 0000 DW 0 ; link
024C 03 DB TSK0No3 OR PRI0 ; task No.
024D 00 DB 0 ; timer
024E 00 DB 0 ; event
024F 7FF6 DW STACK3 ; stack
0251 02 DB tcSt_RDY ; status(ready)
0252 TCBTBL: ; TCB table
IRPC X,0123
DW TCB&X
ENDM
0252 2009 + DW TCB&0
0254 2011 + DW TCB&1
0256 2019 + DW TCB&2
0258 2021 + DW TCB&3
025A TENTRY: ; TASK entry addr table
IRPC X,0123
DW TASK&X
ENDM
025A 02A5 + DW TASK&0
025C 02A9 + DW TASK&1
025E 02D7 + DW TASK&2
0260 02EE + DW TASK&3
; *** CP/M ***
0005 BDOS EQU 0005H
0002 dfPUTC EQU 02H ; D <- data
; *** MSX ***
0039 INTADR EQU 038H + 1 ; interrupt jump addr
0010 INTTIM EQU ( 1000 / 60 ) ; interrupt interval time [ms]
000D CR EQU 13
000A LF EQU 10
; Hook Blank int for timer
; MSX : mode 1, RST 38H
0262 HookInt:
0262 2A 0039 LD HL,(INTADR)
0265 22 01A4 LD (SavINT),HL
0268 21 01A3 LD HL,Timer
026B 22 0039 LD (INTADR),HL
026E C9 RET
; unfuck blank int
;
026F 2A 01A4 UnHook: LD HL,(SavINT)
0272 22 0039 LD (INTADR),HL
0275 C9 RET
; apprication initialize proc
;
0276 CD 0262 IniAp: CALL HookInt
0279 2A 0001 LD HL,(1) ; get WBOOT addr
027C 11 0009 LD DE,3 * 3
027F 19 ADD HL,DE ; HL = conout
0280 22 028C LD (COUTADR),HL
0283 C9 RET
; putchar
; A <- data
;
0284 4F Putch: LD C,A
0285 F3 DI
0286 3E C9 LD A,0C9H ; But executed DI, interrupt occurs at MSXPen
0288 32 0038 LD (INTADR - 1),A
028C COUTADR EQU $ + 1
028B CD 0000 CALL 0
028E 3E C3 LD A,0C3H
0290 32 0038 LD (INTADR - 1),A
0293 FB EI
0294 C9 RET
; put string
; HL <- string addr
;
0295 7E Puts: LD A,(HL)
0296 B7 OR A
0297 C8 RET Z
0298 E5 PUSH HL
0299 CD 0284 CALL Putch
029C E1 POP HL
029D 23 INC HL
029E 3E 01 LD A,1
02A0 CD 01DB CALL Twait
02A3 18 F0 JR Puts
02A5 00 TASK0: NOP
02A6 C3 02A5 JP TASK0
02A9 21 0305 TASK1: LD HL,MsgStart
02AC CD 0295 CALL Puts
02AF 3E BB LD A,3000 / INTTIM
02B1 CD 01DB CALL TWait
02B4 06 10 LD B,16
02B6 TASK1_1:
02B6 C5 PUSH BC
02B7 3E 32 LD A,800 / INTTIM
02B9 CD 01DB CALL TWait
02BC 21 033C LD HL,MsgTk1
02BF CD 0295 CALL Puts
02C2 C1 POP BC
02C3 10 F1 DJNZ TASK1_1
02C5 21 0362 LD HL,MsgBye
02C8 CD 0295 CALL Puts
02CB F3 DI
02CC CD 026F CALL UnHook
02CF ED 7B 1000 LD SP,(SavSP)
02D3 FB EI
02D4 C3 0000 JP 0
02D7 TASK2:
02D7 3E A7 LD A,2680 / INTTIM
02D9 CD 01DB CALL TWait
02DC 3E 7D TSK2LP: LD A,2000 / INTTIM
02DE CD 01DB CALL TWait
02E1 3E 3E LD A,1000 / INTTIM
02E3 CD 01DB CALL TWait
02E6 21 0358 LD HL,MsgTk2
02E9 CD 0295 CALL Puts
02EC 18 EE JR TSK2LP
02EE TASK3:
02EE 3E B5 LD A,2900 / INTTIM
02F0 CD 01DB CALL TWait
02F3 TSK3LP:
02F3 3E 7A LD A,1960 / INTTIM
02F5 CD 01DB CALL TWait
02F8 3E 7D LD A,2000 / INTTIM
02FA CD 01DB CALL TWait
02FD 21 035D LD HL,MsgTk3
0300 CD 0295 CALL Puts
0303 18 EE JR TSK3LP
0305 MsgStart:
0305 0D 0A 54 61 DB CR, LF, 'Task1 says "hello", Task2 & Task3 say each number.', CR, LF, 0
0309 73 6B 31 20
030D 73 61 79 73
0311 20 22 68 65
0315 6C 6C 6F 22
0319 2C 20 54 61
031D 73 6B 32 20
0321 26 20 54 61
0325 73 6B 33 20
0329 73 61 79 20
032D 65 61 63 68
0331 20 6E 75 6D
0335 62 65 72 2E
0339 0D 0A 00
033C 0D 0A 68 65 MsgTk1: DB CR, LF, "hello, world. I am task1.", 0
0340 6C 6C 6F 2C
0344 20 77 6F 72
0348 6C 64 2E 20
034C 49 20 61 6D
0350 20 74 61 73
0354 6B 31 2E 00
0358 32 32 32 32 MsgTk2: DB "2222", 0
035C 00
035D 33 33 33 33 MsgTk3: DB "3333", 0
0361 00
0362 0D 0A 53 65 MsgBye: DB CR, LF, "See you again.", 0
0366 65 20 79 6F
036A 75 20 61 67
036E 61 69 6E 2E
0372 00
ORG 1000H
1000 SavSP: DS 2 ; original SP save area
ORG 2000H
2000 WORKST EQU $
2000 RUNTSK: DS 1 ; running task No.
2001 RDYLNK: DS 2 * MAX_PRI ; ready task que
if 1
IRPC X,0123
TCB&X: DS TCBSIZ
ENDM
2009 + TCB&0: DS TCBSIZ
2011 + TCB&1: DS TCBSIZ
2019 + TCB&2: DS TCBSIZ
2021 + TCB&3: DS TCBSIZ
else
X SET 0
REPT TASKS
TCB&X: DS TCBSIZ
X SET X+1
ENDM
endif
2029 TIMLNK: DS 2 ; timer wait task que
202B WORKEN EQU $
002B WORKSIZ EQU WORKEN - WORKST
END
Macros:
Symbols:
0205 ADDLNK 018C ADDRDY 0005 BDOS
028C COUTADR 000D CR 0002 DFPUTC
014C DISP10 0147 DISPATCH 0156 DISPFND
01F3 GETRTCB 0262 HOOKINT 0276 INIAP
0120 INIR10 0134 INIR20 0100 INIRTM
0232 INITCB 0039 INTADR 0010 INTTIM
000A LF 0004 MAX_PRI 0362 MSGBYE
0305 MSGSTART 033C MSGTK1 0358 MSGTK2
035D MSGTK3 00F0 MSKPRI 000F MSKTNO
0000 PRI0 0010 PRI1 0020 PRI2
0030 PRI3 0284 PUTCH 0295 PUTS
2001 RDYLNK 017B REMO10 016F REMOVE
0211 ROBIN 2000 RUNTSK 021F SAVESP
01A4 SAVINT 1000 SAVSP 8000 STACK
7F36 STACK0 7F76 STACK1 7FB6 STACK2
7FF6 STACK3 000A STREGSIZ 02A5 TASK0
02A9 TASK1 02B6 TASK1_1 02D7 TASK2
02EE TASK3 0004 TASKS 2009 TCB0
2011 TCB1 2019 TCB2 2021 TCB3
0008 TCBSIZ 0252 TCBTBL 0004 TCEVCNT
0000 TCLIST 0005 TCSP 0007 TCSTAT
0000 TCST_NO 0002 TCST_RDY 0001 TCST_RUN
0003 TCST_WAT 0003 TCTIM 0000 TCTOP
0002 TCTSKNO 025A TENTRY 01A6 TIM00
01B9 TIM10 01D1 TIM20 01D4 TIM30
01A3 TIMER 2029 TIMLNK 0001 TSK0NO1
0002 TSK0NO2 0003 TSK0NO3 0000 TSK0NOO
02DC TSK2LP 02F3 TSK3LP 0040 TSKSPSIZ
01DB TWAIT 026F UNHOOK 202B WORKEN
002B WORKSIZ 2000 WORKST
No Fatal error(s)
|