Repository navigation
Expand file tree
/
Copy pathtasker3.asm
More file actions
302 lines (256 loc) · 12.7 KB
/
Copy pathtasker3.asm
File metadata and controls
302 lines (256 loc) · 12.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
;*******************************************************************************
;* Program : TASKER3.ASM
;* Programmer: Tony Papadimitriou <tonyp@acm.org>
;* Purpose : Demonstrate the simplest (?) preemptive three-task "multitasker"
;* : Each task takes turns running for 4.1ms at a time
;* : This one can be extended to more tasks very easily
;* Language : Motorola/Freescale/NXP 68HC11 Assembly Language (aspisys.com/ASM11)
;* Status : FREEWARE, Copyright (c) 2020 by Tony Papadimitriou
;* History : 99.08.18 v1.00 Original
;* : 99.09.20 v1.01 Added SWI Handler for giving up remaining timeslice
;* : 99.09.21 v1.02 Added SHADOW11 for simulator runs.
;* : 00.09.19 v1.03 Added conditional for setting TASKS at assembly time.
;* : 01.05.05 v1.04 Removed SHADOW11 conditional (newer Shadow11 OK)
;* : 02.02.14 v1.05 Added TASKSTACKSIZE for defining task stack size
;* : 06.04.25 v1.06 Added conditionals for upto 5 tasks
;* : 16.02.18 Refactored for latest ASM11
;* : 18.05.13 Added ! in front of SEI and CLI instructions in
;* : respective macros to avoid recursion in certain
;* : #Macro modes
;* : 20.12.19 Removed redundant instruction in SWI handler [-2 bytes]
;* : Added LF2CRLF conditional to convert LF to CR/LF
;*******************************************************************************
#ifdef ?
#Hint ****************************************************
#Hint * Possible -D option values are shown here:
#Hint ****************************************************
#Hint * DEBUG....: For use with SIM11E
#Hint * TASKS:n..: Set number of tasks to n
#Hint * INTS.....: Interrupts OK inside Print
#Hint * SWI......: Third task gives up remaining timeslice
#Hint ****************************************************
#Fatal Run ASM11 -Dx (where x is any of the above)
#endif
#ifdef DEBUG
#Hint For SIM11E use only (do NOT burn device)
#endif
#ListOff
#Uses 811e2.inc ;found in ASM11 distribution
#ListOn
TASKSTACKSIZE def 50 ;default task stack size
;*******************************************************************************
; Macros
;*******************************************************************************
sei macro
#ifndef INTS
!sei ;prevent interrupts
#endif
endm
;-------------------------------------------------------------------------------
cli macro
#ifndef INTS
!cli ;interrupts OK now
#endif
endm
;*******************************************************************************
#RAM
;*******************************************************************************
MAXTASKS def 3 ;Number of maximum tasks (default)
#if MAXTASKS < 2
#Error MAXTASKS ({MAXTASKS}) must be at least two
#endif
;--------------------------------------
; Multitasking-related variables and definitions
;--------------------------------------
? macro
TASKSTACK1 equ STACKTOP-TASKSTACKSIZE
mdo 2
TASKSTACK{:mloop} equ TASKSTACK{:mloop-1}-TASKSTACKSIZE
mloop MAXTASKS
endm
@?
;-------------------------------------------------------------------------------
task_index rmb 1 ;0, 1, 2, etc.
stack rmb 2*MAXTASKS ;Stack for tasks
?FREE_RAM equ RAM_END-:RAM
?STACKUSED equ MAXTASKS*TASKSTACKSIZE
#if ?STACKUSED > ?FREE_RAM
#Error Not enough RAM for all stacks and variables
#endif
;*******************************************************************************
#ROM
;*******************************************************************************
;*******************************************************************************
; Real Time Interrupt requests come here (does task switching)
RTI_Handler proc
lda #RTIF.
sta TFLG2 ;Reset the RTI int
; bra SWI_Handler
;*******************************************************************************
; SoftWare Interrupt requests come here (use SWI to give up timeslice)
SWI_Handler proc
;-------------------------------------- ;save current task stack pointer
ldb task_index
ldx #stack
abx:2
sts ,x ;save current SP
;-------------------------------------- ;point to next task
; ldb task_index ;B = current task (already loaded)
incb ;task_index := (task_index + 1) mod MAXTASKS
cmpb #MAXTASKS ;higher than max task?
blo Wrap@@
clrb ;if yes, wrap around to first task
Wrap@@ stb task_index ;and save it
;-------------------------------------- ;switch stacks
ldx #stack
abx:2
lds ,x ;load new task's SP
RTI ;continue with next task
;*******************************************************************************
TCB macro ;Task Control Block
mdef 1,MAXTASKS
lds #TASKSTACK{:loop} ;extra stack
ldx #Task{:loop} ;point to extra task start address
pshx
clrx ;D, X, and Y start out zeroed
pshx:3
lda #S.|X. ;Initial CCR for task 1
psha
sts stack+{:loop-1*2+2}
mtop ~1~
endm
;*******************************************************************************
Start proc
clr task_index ;initialize to main task
@tcb ;prepare initial stack frame(s)
;-------------------------------------- ;Primary (Task0) task's initialization
lds #STACKTOP ;primary task's stack
;--------------------------------------
; Let's initialize the SCI for polled mode operation at 9600 bps
;--------------------------------------
clr SCCR2
#ifdef DEBUG
clrd ;For SIM11E, use fastest bps rate
#else
ldd #~$30
#endif
std BAUD
lda #%1100
sta SCCR2 ;Transmitter/Receiver enabled
;--------------------------------------
; Now, let's initialize the timer
; Real-time clock initialization (4.1ms RTI @ 2MHz MCU E-Clock)
;--------------------------------------
ldx #REGS
bclr [PACTL,x,%11 ;mask off RTR1:0 bits
bset [TMSK2,x,RTIF. ;Enable RTI interrupts
clrd
clrx
clry
cli ;allow multi-tasking from this point on
; bra Task0
;*******************************************************************************
; PRIMARY TASK (Task0)
;*******************************************************************************
Task0 proc
Loop@@ ldx #Msg@@
bsr Print
bsr Delay
bra Loop@@ ;loop forever
Msg@@ fcs LF,'---Main Task---'
;*******************************************************************************
; SECOND TASK (Task1)
;*******************************************************************************
Task1 proc
Loop@@ ldx #Msg@@
bsr Print
bra Loop@@ ;Cannot use RTS or RTI (independent process)
Msg@@ fcs LF,'>>>>>>>>>>>>>>>>>>>> Task 2 <<<<<<<<<<<<<<<<<<<<'
;*******************************************************************************
; THIRD TASK (Task2)
;*******************************************************************************
Task2 proc
Loop@@ ldx #Msg@@
bsr Print
#ifdef SWI
swi ;Give up remaining timeslice
#endif
bra Loop@@ ;Cannot use RTS or RTI (independent process)
Msg@@ fcs LF,'T3'
;*******************************************************************************
; ADDITIONAL TASKS (Add as needed)
;*******************************************************************************
Task3 proc
swi
!... Add your code here
bra *
;*******************************************************************************
Task4 proc
!... Add your code here
bra *
;*******************************************************************************
Task5 proc
!... Add your code here
bra *
;*******************************************************************************
; Purpose: Send ASCIZ string (pointed to by RegX) to the SCI
; Input : X -> ASCIZ string
; Output : None
; Note(s):
Print proc
@sei ;prevent interrupts
pshx
psha
Loop@@ lda ,x ;get character
beq Done@@ ;on terminating zero, get out
bsr PutChar ;everything else, we send to the SCI
inx ;point to next string character
bra Loop@@ ;repeat
Done@@ pula
pulx
@cli ;interrupts OK now
rts
;*******************************************************************************
; Purpose: Delay 0.5ms
; Input : None
; Output : None
; Note(s):
#Cycles
Delay proc
pshx
ldx #DELAY@@
#Cycles
Loop@@ dex
bne Loop@@
#temp :cycles
pulx
rts
DELAY@@ equ BUS_KHZ/2-:cycles-:ocycles/:temp
;*******************************************************************************
; Purpose: Send a character to the SCI
; Input : A = character to send
; Output : None
; Note(s):
PutChar proc
#ifdef LF2CRLF
cmpa #LF
bne ?PutChar
lda #CR
bsr ?PutChar
lda #LF
#endif
; bra ?PutChar
;*******************************************************************************
?PutChar proc
Loop@@ tst SCSR
bpl Loop@@
sta SCDR
rts
;*******************************************************************************
@vector Vrti,RTI_Handler ;Timer interrupt
@vector Vswi,SWI_Handler ;SoftWare Interrupt
@vector Vcop,Start ;COP vector
@vector Vcmf,Start ;CMF vector
@vector Vreset,Start ;RESET vector
;*******************************************************************************
end :s19crc