OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [taskmgr/] [taskmgr_const.s] - Blame information for rev 306

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 301 jshamlet
; Copyright (c)2022 Jeremy Seth Henry
2
; All rights reserved.
3
;
4
; Redistribution and use in source and binary forms, with or without
5
; modification, are permitted provided that the following conditions are met:
6
;     * Redistributions of source code must retain the above copyright
7
;       notice, this list of conditions and the following disclaimer.
8
;     * Redistributions in binary form must reproduce the above copyright
9
;       notice, this list of conditions and the following disclaimer in the
10
;       documentation and/or other materials provided with the distribution,
11
;       where applicable (as part of a user interface, debugging port, etc.)
12
;
13
; THIS SOFTWARE IS PROVIDED BY JEREMY SETH HENRY ``AS IS'' AND ANY
14
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16
; DISCLAIMED. IN NO EVENT SHALL JEREMY SETH HENRY BE LIABLE FOR ANY
17
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22
; THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
;
24
;------------------------------------------------------------------------------
25
; taskmgr_const.s
26
;
27
;  Task Manager constants, tables, and macros
28
;
29
; Revision History
30
; Author          Date     Change
31
;---------------- -------- ----------------------------------------------------
32
; Seth Henry      7/15/22  Initial Release
33
;------------------------------------------------------------------------------
34
 
35
;------------------------------------------------------------------------------
36
; Semaphore Value - should always be non-zero
37
.DEFINE SEMAPHORE_VAL        $FF       ; Standard value used to set semaphores
38
;------------------------------------------------------------------------------
39
 
40
;------------------------------------------------------------------------------
41
; I/O Mapping (HDL -> ASSY)
42
;------------------------------------------------------------------------------
43
 
44
; System RAM Write-Protect Register
45
.DEFINE WPR_MASK_REG         WPR_Address
46
 
47
; Write Protect Mask
48
.DEFINE WPR_MASK_0           WPR_MASK_REG + 0
49
.DEFINE WPR_MASK_1           WPR_MASK_REG + 1
50
.DEFINE WPR_MASK_2           WPR_MASK_REG + 2
51
.DEFINE WPR_MASK_3           WPR_MASK_REG + 3
52
 
53
; WP Register Map:
54
; Offset  Bitfield Description                        Read/Write
55
;   0x00  AAAAAAAA Region Enables  7:0                  (RW)
56
;   0x01  AAAAAAAA Region Enables 15:8                  (RW)
57
;   0x02  AAAAAAAA Region Enables 23:16                 (RW)
58
;   0x03  AAAAAAAA Region Enables 31:24                 (RW)
59
 
60
; I/O Write Qualification Register
61
.DEFINE IO_WRITE_QUAL        WQL_Address
62
 
63
; External Interrupt Manager / Task Timer
64
.DEFINE INT_MGR_IF           INT_Address ; Shared with the main
65
.DEFINE TASK_TIMER_PRD       INT_MGR_IF  + 0
66
 
67
; Defines for the 8-bit interrupt manager
68
.DEFINE EXT_INT_MASK         INT_MGR_IF + 1
69
.DEFINE EXT_INT_PEND         INT_MGR_IF + 2
70
.DEFINE EXT_INT_ACK          INT_MGR_IF + 3
71
 
72
; Defines for the 16-bit interrupt manager
73
.DEFINE EXT_INT16_MASK_L     INT_MGR_IF + 2
74
.DEFINE EXT_INT16_MASK_H     INT_MGR_IF + 3
75
.DEFINE EXT_INT16_PEND_L     INT_MGR_IF + 4
76
.DEFINE EXT_INT16_PEND_H     INT_MGR_IF + 5
77
.DEFINE EXT_INT16_ACK        INT_MGR_IF + 7
78
 
79
; Register Map:
80
; Offset  Bitfield Description                        Read/Write
81
;   0x00  AAAAAAAA PIT Timer Interval (0 = disabled)    (RW)
82
;   0x01  AAAAAAAA External Interrupt Mask              (RW)
83
;   0x02  AAAAAAAA Pending External Ints*               (RW)
84
;   0x02  A------- Interrupt Requested (write to clear) (RW)
85
 
86
; External Interrupt bit & mask definitions
87
.DEFINE EXT_INT0_BIT         2^0
88
.DEFINE EXT_INT1_BIT         2^1
89
.DEFINE EXT_INT2_BIT         2^2
90
.DEFINE EXT_INT3_BIT         2^3
91
.DEFINE EXT_INT4_BIT         2^4
92
.DEFINE EXT_INT5_BIT         2^5
93
.DEFINE EXT_INT6_BIT         2^6
94
.DEFINE EXT_INT7_BIT         2^7
95
 
96
.DEFINE EXT_INT8_BIT         2^0
97
.DEFINE EXT_INT9_BIT         2^1
98
.DEFINE EXT_INT10_BIT        2^2
99
.DEFINE EXT_INT11_BIT        2^3
100
.DEFINE EXT_INT12_BIT        2^4
101
.DEFINE EXT_INT13_BIT        2^5
102
.DEFINE EXT_INT14_BIT        2^6
103
.DEFINE EXT_INT15_BIT        2^7
104
;------------------------------------------------------------------------------
105
 
106
;------------------------------------------------------------------------------
107
; Register the interrupt service routines and form the vector address table at
108
;  the end of the ROM
109
;------------------------------------------------------------------------------
110
.ORG ISR_Start_Addr
111
.DW RAM_FAULT        ; (0xFFF1:0xFFF0) ISR 0
112
.DW TASK_SW_INT      ; (0xFFF3:0xFFF2) ISR 1
113
.DW EXT_INT_MGR      ; (0xFFF5:0xFFF4) ISR 2
114
.DW EXEC_SUPV0       ; (0xFFF7:0xFFF6) ISR 3
115
.DW EXEC_SUPV1       ; (0xFFF9:0xFFF8) ISR 4
116
.DW EXEC_SUPV2       ; (0xFFFB:0xFFFA) ISR 5
117
.DW EXEC_SUPV3       ; (0xFFFD:0xFFFC) ISR 6
118
.DW EXEC_SUPV4       ; (0xFFFF:0xFFFE) ISR 7
119
 
120
.DEFINE CPU_INT_ENABLES      $FF
121
;------------------------------------------------------------------------------
122
 
123
;------------------------------------------------------------------------------
124
; Pointer Defines and Table Organization
125
;------------------------------------------------------------------------------
126
 
127
; Create defined constants to pointer table
128
; Note that these are offset by 4 to account for the bootstrap JMP and NOP
129
.DEFINE STACK_MEMORY_PTR     BOOT_BLOCK +  4
130
.DEFINE FREE_SYSMEM_PTR      BOOT_BLOCK +  6
131
.DEFINE TASK_PARAMS_PTR      BOOT_BLOCK +  8
132
.DEFINE TASK_PARAM_TABLE     BOOT_BLOCK +  10
133
 
134
.MACRO INSTANCE_TASK_POINTERS
135
 
136
.DW TaskMgr.Task_Stacks   ; ( + 4) First available RAM location for stack data
137
.DW TaskMgr.Free_Mem      ; ( + 6) First available free RAM location in sysmem
138
.DW TASK_PARAM_TABLE      ; ( + 8) Start of task parameter table
139
.ENDM
140
 
141
;------------------------------------------------------------------------------
142
; INSTANCE_TASK_EXPORTS / CREATE_TASK_EXPORTS setup a ROM table for the task
143
;  switcher with critical entry points and memory & I/O write access
144
;  permissions. The entry points are created automatically by
145
;  INSTANCE_MAIN_LOOPS, while the other constants are setup in taskmgr_config.s
146
;  based on its task configuration and memory needs
147
;------------------------------------------------------------------------------
148
 
149
.DEFINE STACK_TABLE_OFFSET    2
150
.DEFINE PARAM_TABLE_OFFSET   20
151
 
152
; Define table offsets to allow quick use of LDO to access individual records
153
;  for each task
154
 
155
.DEFINE PARAM_MAIN_ADDR_LOW   0
156
.DEFINE PARAM_MAIN_ADDR_HIGH  1
157
 
158
.DEFINE PARAM_STACK_ADDR_LOW  2
159
.DEFINE PARAM_STACK_ADDR_HIGH 3
160
 
161
.DEFINE PARAM_WPR_BYTE0       4
162
.DEFINE PARAM_WPR_BYTE1       5
163
.DEFINE PARAM_WPR_BYTE2       6
164
.DEFINE PARAM_WPR_BYTE3       7
165
 
166
.DEFINE PARAM_WQL_LOW         8
167
.DEFINE PARAM_WQL_HIGH        9
168
 
169
.DEFINE SUPV_FN0_ENTRY_LOW    10
170
.DEFINE SUPV_FN0_ENTRY_HIGH   11
171
 
172
.DEFINE SUPV_FN1_ENTRY_LOW    12
173
.DEFINE SUPV_FN1_ENTRY_HIGH   13
174
 
175
.DEFINE SUPV_FN2_ENTRY_LOW    14
176
.DEFINE SUPV_FN2_ENTRY_HIGH   15
177
 
178
.DEFINE SUPV_FN3_ENTRY_LOW    16
179
.DEFINE SUPV_FN3_ENTRY_HIGH   17
180
 
181
.DEFINE SUPV_FN4_ENTRY_LOW    18
182
.DEFINE SUPV_FN4_ENTRY_HIGH   19
183
 
184
; CREATE_TASK_EXPORTS creates an entry in the TASK_PARAM_TABLE with critical
185
;  task information. Note that the WPR_LOW, WPR_HIGH, and WQL must be defined
186
;  in taskmgr_config.s. Everything else is automatically created here, or by
187
;  the assembler/linker.
188
 
189
.MACRO CREATE_TASK_EXPORTS
190
.DEFINE TASK\@_STACK_END      RAM_Address + (TASK\@_STACK_RGN * WP_Rgn_Size)
191
.DEFINE TASK\@_STACK_START    TASK\@_STACK_END + WP_Rgn_Size - 1
192
 
193
.DW TASK\@_MAIN          ; 1:0 Entry point created by INSTANCE_MAIN_LOOPS
194
.DW TASK\@_STACK_START   ; 3:2 Pointer to top of the task stack
195
.DW TASK\@_WPR_LOW       ; 5:4 Mask for enabling task mem writes for vars
196
.DW TASK\@_WPR_HIGH      ; 7:6 Mask for enabling task mem writes for stack
197
.DW TASK\@_WQL           ; 9:8 Mask for enabling task I/O write access
198
.DW _F0_EXE_S\@          ; 11:10 Entry point for supervisory function 0
199
.DW _F1_EXE_S\@          ; 13:12 Entry point for supervisory function 1
200
.DW _F2_EXE_S\@          ; 15:14 Entry point for supervisory function 2
201
.DW _F3_EXE_S\@          ; 17:16 Entry point for supervisory function 3
202
.DW _F4_EXE_S\@          ; 19:18 Entry point for supervisory function 4
203
.ENDM
204
 
205
.MACRO INSTANCE_TASK_EXPORTS
206
    .REPEAT TASK_COUNT
207
        CREATE_TASK_EXPORTS
208
    .ENDR
209
.ENDM
210
;------------------------------------------------------------------------------
211
 
212
;------------------------------------------------------------------------------
213
;  Memory Structures and Variable Organization
214
;------------------------------------------------------------------------------
215
 
216
; Variable    Size      Description
217
; --------    ----      -------------------------------------------------------
218
.STRUCT str_task_label
219
Label         DW        ; 2-byte "header" to allow task RAM to be easily found
220
.ENDST
221
 
222
.STRUCT str_isr_flag
223
Flag          DB        ; Single-byte flag variable for returning semaphores
224
.ENDST
225
 
226 302 jshamlet
.DEFINE TSB_SIZE             2 * TASK_COUNT
227
.DEFINE FREE_SYS             WP_Rgn_Size - 8 - TSB_SIZE
228 301 jshamlet
 
229
.STRUCT str_taskman
230
This_Task     DB           ; Holds the task number of the current task
231
Next_Task     DB           ; Specifieds which task to be executed next
232
Fault_Flag    DB           ; Memory write fault flag
233
Fault_Task    DB           ; Task active/responsible for write fault
234 302 jshamlet
Temp_R0       DB           ; Temp storage for R0
235
Temp_R1       DB           ; Temp storage for R1
236
Temp_R2       DB           ; Temp storage for R2
237
Temp_R3       DB           ; Temp storage for R3
238 301 jshamlet
Task_Stacks   DSB TSB_SIZE ; First location for stack data*
239
Free_Mem      DSB FREE_SYS ; Unused memory in system region
240
.ENDST
241
 
242
; * Note that this location is used to setup a pointer, which the task manager
243
;  will use to assign each task a backup location for its current stack pointer
244
;  Thus, this area grows up to 2x the number tasks. The type is intentionally
245
;  set as DB as a reminder. If attempting to reuse memory in this region, this
246
;  should be noted
247
 
248
.ENUM SYSTEM_VARMEM
249
TaskMgr       INSTANCEOF str_taskman
250
.ENDE
251
;------------------------------------------------------------------------------
252
 
253
;------------------------------------------------------------------------------
254
; Utility macros for booting the system and providing access to internal vars
255
;------------------------------------------------------------------------------
256
 
257
; The Open8 supports an optional mode for the RSP instruction that
258
;  converts it from Reset Stack Pointer to Relocate Stack Pointer.
259
; The new form of the instruction takes one of the CPU flags as a
260
;  direction/mode bit. Setting PSR_S will cause the instruction
261
;  to write R1:R0 -> SP, while clearing it will cause the instruction
262
;  to copy the SP -> R1:R0.
263
 
264
.MACRO RETRIEVE_SP
265
              CLP  PSR_S   ; Affirmatively clear PSR_S flag first
266
              RSP          ; Then execute the RSP instruction
267
.ENDM
268
 
269
.MACRO RELOCATE_SP
270
              STP  PSR_S   ; Affirmatively set PSR_S flag first
271
              RSP          ; Execute the RSP instruction
272
              CLP  PSR_S   ; Reset PSR_GP4 afterward
273
.ENDM
274
 
275
; Task initialization, switching time, and init/exec macros
276
.MACRO DISABLE_PREEMPTION_TIMER
277
              CLR  R0                     ; Make sure the PIT is disabled
278
              STA  R0, TASK_TIMER_PRD     ; by writing 0 to the PIT period
279
.ENDM
280
 
281
.MACRO RESET_PREEMPTION_TIMER
282
              LDI  R0, #MAX_TASK_TIMESLICE; Turn on the PIT timer at this point
283
              STA  R0, TASK_TIMER_PRD     ;  to kick off the task switcher
284
.ENDM
285
 
286
; Fault flag macros
287
.MACRO INITIALIZE_FAULT_FLAGS
288
              CLR  R0
289
              STA  R0, TaskMgr.Fault_Flag
290
              STA  R0, TaskMgr.Fault_Task
291
.ENDM
292
 
293
.MACRO SET_FAULT_FLAGS
294
              LDI  R0, #SEMAPHORE_VAL
295
              STA  R0, TaskMgr.Fault_Flag
296
              LDA  R0, TaskMgr.This_Task
297
              STA  R0, TaskMgr.Fault_Task;
298
.ENDM
299
 
300 304 jshamlet
; BACKUP_FULL_CONTEXT pushes all 8 registers to the stack
301
.MACRO BACKUP_FULL_CONTEXT
302
              PSH  R0
303
              PSH  R1
304
              PSH  R2
305
              PSH  R3
306
              PSH  R4
307
              PSH  R5
308
              PSH  R6
309
              PSH  R7
310
.ENDM
311 301 jshamlet
 
312 304 jshamlet
; RESTORE_FULL_CONTEXT pops all 8 registers off of the stack
313
.MACRO RESTORE_FULL_CONTEXT
314
              POP  R7
315
              POP  R6
316
              POP  R5
317
              POP  R4
318
              POP  R3
319
              POP  R2
320
              POP  R1
321
              POP  R0
322
.ENDM
323
 
324
; REINIT_TASK_TABLE_PTR uses the This_Task variable to configure R3:R2 as a
325
;  pointer into the TASK_PARAMS table.
326
.MACRO REINIT_TASK_TABLE_PTR
327
              LDA  R0, TaskMgr.This_Task
328 301 jshamlet
              LDI  R1, #PARAM_TABLE_OFFSET
329
              MUL  R1
330
 
331
              LDA  R2, TASK_PARAMS_PTR + 0  ; Load R3:R2 with the start of the
332 304 jshamlet
              LDA  R3, TASK_PARAMS_PTR + 1  ;  task parameter region
333 301 jshamlet
 
334 304 jshamlet
              ADD  R2                       ; Add [R3:R2] + [R1:R0] -> [R3:R2]
335 301 jshamlet
              T0X  R2
336
              TX0  R1
337
              ADC  R3
338
              T0X  R3
339 304 jshamlet
.ENDM
340 301 jshamlet
 
341 305 jshamlet
; INITIALIZE_TASK_STACK relocates the CPU stack pointer during setup, then
342
;  simulates an RTI by loading an initial flag and return address, then resets
343
;  all registers to 0
344
.MACRO INITIALIZE_TASK_STACK
345 306 jshamlet
              REINIT_TASK_TABLE_PTR      ; Use This_Task to initialize R3:R2
346
 
347 301 jshamlet
              ; Get the task's starting stack address from the table and load
348
              ;  it into the CPU SP
349
              LDO  R2, PARAM_STACK_ADDR_HIGH
350
              T0X  R1
351
              LDO  R2, PARAM_STACK_ADDR_LOW
352
              RELOCATE_SP                 ; R1:R0 -> CPU SP
353
 
354
              ; From here on out, the CPU SP is pointing to the target task's
355
              ;  stack region, so we can initialize its stack memory
356
 
357 304 jshamlet
              ; Write initial flag value to simulate entering code as an ISR
358 301 jshamlet
              CLR  R0
359
              PSH  R0
360
 
361
              ; Initialize the return address to point to the "initialize"
362
              ;  portion of the task, so that the task can do its one-time
363
              ;  startup code.
364
 
365
              LDO  R2, PARAM_MAIN_ADDR_HIGH ; Write return PC MSB
366
              PSH  R0
367
 
368
              LDO  R2, PARAM_MAIN_ADDR_LOW  ; Write return PC LSB
369
              PSH  R0
370
 
371
              ; Setup the initial reg values
372
              CLR  R0                  ; Initialize all registers to 0
373 304 jshamlet
              T0X  R1
374
              T0X  R2
375
              T0X  R3
376
              T0X  R4
377
              T0X  R5
378
              T0X  R6
379
              T0X  R7
380
.ENDM
381 301 jshamlet
 
382 304 jshamlet
; BACKUP_STACK_POINTER uses the This_Task variable to configure R3:R2 as a
383
;  pointer into the system memory where stack pointer backups are stored, then
384
;  obtains the current stack address and pushes it to the task's backup
385
;  SP variable
386
.MACRO BACKUP_STACK_POINTER
387
              LDA  R0, TaskMgr.This_Task    ; Get the task number
388
              LDI  R1, #STACK_TABLE_OFFSET  ; Multiply it by 2
389 301 jshamlet
              MUL  R1
390
 
391 304 jshamlet
              LDA  R2, STACK_MEMORY_PTR + 0 ; Load R3:R2 with the start of the
392
              LDA  R3, STACK_MEMORY_PTR + 1 ;  stack memory region
393 301 jshamlet
 
394 304 jshamlet
              ADD  R2                  ; Add [R3:R2] + [R1:R0] -> [R3:R2]
395 301 jshamlet
              T0X  R2
396
              TX0  R1
397
              ADC  R3
398
              T0X  R3
399
 
400
              RETRIEVE_SP
401
              STX  R2
402
              TX0  R1
403
              STO  R2,1
404
.ENDM
405
 
406 305 jshamlet
; SUSPEND_THIS_TASK pushes all of the registers to a task's stack, then
407
;  backups up the stack pointer to the system memory backup location for that
408
;  task.
409
.MACRO SUSPEND_THIS_TASK
410
              BACKUP_FULL_CONTEXT
411
              BACKUP_STACK_POINTER
412
.ENDM
413
 
414
; SETUP_TASK is a template used to generate code that sets up a single task's
415
; stack and stack pointer for each a task. This macros will temporarily
416
;  relocate the stack pointer, push the task's initial state to the task's
417
;  stack. Note that it is important to also ensure that the stack has data to
418
;  not only restore the return address, but also R7:R0, as well as the flag
419
;  state.
420
.MACRO SETUP_TASK
421
              LDI  R0, #\@
422
              STA  R0, TaskMgr.This_Task ; Write This_Task
423
 
424
              INITIALIZE_TASK_STACK      ; Setup the new task's stack area
425
              SUSPEND_THIS_TASK          ; Suspend the task to store setup
426
.ENDM
427
 
428 304 jshamlet
; RESTORE_STACK_POINTER uses the This_Task variable to configure R3:R2 as a
429
;  pointer into the system memory where stack pointer backups are stored. It
430
;  then looks up the task's SP backup variable and pushes it back to the CPU SP
431
.MACRO RESTORE_STACK_POINTER
432 301 jshamlet
              LDA  R0, TaskMgr.This_Task    ; Get the task number
433
              LDI  R1, #STACK_TABLE_OFFSET  ; Multiply it by 2
434
              MUL  R1
435
 
436
              LDA  R2, STACK_MEMORY_PTR + 0 ; Load R3:R2 with the start of the
437
              LDA  R3, STACK_MEMORY_PTR + 1 ;  stack memory region
438
 
439
              ADD  R2                  ; Add [R3:R2] + [R1:R0] -> [R3:R2]
440
              T0X  R2
441
              TX0  R1
442
              ADC  R3
443
              T0X  R3
444
 
445 303 jshamlet
              LDO  R2,1                ; Copy [R3:R2]* -> R1:R0
446 301 jshamlet
              T0X  R1
447 303 jshamlet
              LDX  R2
448 301 jshamlet
              RELOCATE_SP              ; Update R1:R0 -> CPU SP
449 304 jshamlet
.ENDM
450 301 jshamlet
 
451 304 jshamlet
; RESTORE_TASK_PERMISSIONS looks up the current (new) task's RAM & I/O write
452
;  permissions (masks) and reconfigures the hardware to allow access.
453
.MACRO RESTORE_TASK_PERMISSIONS
454 301 jshamlet
              REINIT_TASK_TABLE_PTR    ; Setup R3:R2 to point to the task table
455
 
456
              ; Rewrite the RAM WPR register for this task. Note that the WPR
457
              ; is a 32-bit register.
458
              LDO  R2, PARAM_WPR_BYTE0
459
              STA  R0, WPR_MASK_0
460
 
461
              LDO  R2, PARAM_WPR_BYTE1
462
              STA  R0, WPR_MASK_1
463
 
464
              LDO  R2, PARAM_WPR_BYTE2
465
              STA  R0, WPR_MASK_2
466
 
467
              LDO  R2, PARAM_WPR_BYTE3
468
              STA  R0, WPR_MASK_3
469
 
470
              LDO  R2, PARAM_WQL_LOW   ; Update the new task's WQL
471
              STA  R0, IO_WRITE_QUAL
472 304 jshamlet
.ENDM
473 301 jshamlet
 
474 304 jshamlet
; INIT_NEXT_TASK forces the Next_Task variable to 0 (Task 0)
475
.MACRO INIT_NEXT_TASK
476
              CLR  R0
477
              STA  R0, TaskMgr.Next_Task
478
.ENDM
479
 
480
; ADVANCE_NEXT_TASK implements the simple scheduler. By default, the task
481
; manager uses a simple round-robin scheduler, unless an ISR alters the
482
;  Next_Task variable, so increment the task count, check it against the
483
;  total task count, and reset it to task 0 if necessary.
484
.MACRO ADVANCE_NEXT_TASK
485
              LDA  R1, TaskMgr.Next_Task ; Copy Next_Task -> This_Task
486
              STA  R1, TaskMgr.This_Task
487
 
488
              INC  R1                  ; Increment the task count
489
              LDI  R0, #TASK_COUNT     ; Compare it with the task count
490
              XOR  R1
491
              BNZ _TS_ADV_TN_\@        ; If it matches the task count
492
              LDI  R1, #$00            ;  reset the counter to zero
493
_TS_ADV_TN_\@:STA  R1, TaskMgr.Next_Task ; Store the new value into Next_Task
494
.ENDM
495
 
496
; AWAKEN_NEXT_TASK is responsible for updating the Next_Task variable, then
497
;  using it to restore the stack pointer from the system memory copy. It then
498
;  updates the memory write protection parameters and I/O write qualification
499
;  register for the new task. Finally, it resets the pre-emption timer and
500
;  restores the register state from the task's stack.
501
.MACRO AWAKEN_NEXT_TASK
502
              ADVANCE_NEXT_TASK        ; Advance the task positions
503
              RESTORE_STACK_POINTER    ; Lookup the new task's table pointer
504
              RESTORE_TASK_PERMISSIONS ; Restore the task's write access masks
505 301 jshamlet
              RESET_PREEMPTION_TIMER   ; Reset the PIT timer
506
              RESTORE_FULL_CONTEXT     ; Restore the new task's register state
507 304 jshamlet
              RTI                      ; Return to the new task
508 301 jshamlet
.ENDM
509
;------------------------------------------------------------------------------
510
 
511
;------------------------------------------------------------------------------
512
; System Start
513
;
514
; System initialization requires that the CPU start in supervisor mode, as it
515
;  writes to every active region in memory. Thus, if the CPU is NOT in
516
;  in supervisor mode, something has gone horribly wrong. This branch locks the
517
;  main loop if the I bit is not set. This is probably unnecessary now that the
518
;  panic ISR is in place.
519
;------------------------------------------------------------------------------
520
 
521 304 jshamlet
; INSTANCE_TASK_SETUP expands to create setup code for all of the tasks based
522
;  on the template above. There should be one setup per task, hence the repeat
523
;  based on TASK_COUNT
524
.MACRO INSTANCE_TASK_SETUP
525
          .REPT TASK_COUNT
526
              SETUP_TASK
527
          .ENDR
528 301 jshamlet
.ENDM
529
 
530
.MACRO BOOT_SYSTEM
531
; Before beginning, turn off all of the CPU interrupts (The NMI will still be
532
;  active, but memory write protection is effectively disabled with the I-bit
533
;  set) Note that this code is running in interrupt context (I-bit is set)
534
;  so it is "uninterruptible" due to the HDL generic being set. However, this
535
;  doesn't prevent pending interrupts from being latched by the CPU.
536
; Note that this macro is defined in "isr_const.s"
537
              DISABLE_CPU_INTS
538
 
539
; Even though interrupts are off, disable the task timer so that there isn't
540
;  a pending task timer interrupt waiting when interrupts are re-enabled. This
541
;  avoids the first task missing out on initialization.
542
              DISABLE_PREEMPTION_TIMER
543
 
544
; Initialize the system fault flags
545
              INITIALIZE_FAULT_FLAGS
546
 
547
; Setup the stack and stack pointer for each of the tasks. (see above)
548
              INSTANCE_TASK_SETUP
549
 
550
; Before starting, make sure the external interrupt controller has been
551
;  initialized. Initialization of the external interrupt controller involves
552
;  clearing any pending interrupts and setting up the interrupt mask. Finally,
553
;  the CPU interrupts should be enabled at this point, as the interrupt core is
554
;  ready.
555
.IFDEF INTMGR16
556
              INITIALIZE_IO_INTMGR16      ; Setup the 16-bit IF
557
.ELSE
558
              INITIALIZE_IO_INTMGR        ; Setup the 8-bit IF
559
.ENDIF
560
; Once the external interrupt manager is configured, enable the CPU interrupts
561
              ENABLE_CPU_INTS             ; Enable the CPU interrupt inputs
562
 
563
; Like the task switcher ISR, restore the full CPU state for the first task
564 304 jshamlet
              INIT_NEXT_TASK              ; Reset the next task to task 0
565
              AWAKEN_NEXT_TASK            ; Load task 0's context to system
566 301 jshamlet
 
567
; Create all of the task loops here.
568 304 jshamlet
              INSTANCE_TASK_LOOPS         ; Instantiate the main task loops
569 301 jshamlet
.ENDM
570
;------------------------------------------------------------------------------
571
 
572
;------------------------------------------------------------------------------
573
; Task Loops
574
;------------------------------------------------------------------------------
575
 
576
; INSTANCE_MAIN_LOOP:
577
; These loops represent each task's "main()", and should never "exit".
578
; Each task's func.s file should declare two required functions, TASKn_INIT and
579
; TASKn_EXEC
580
;
581
; Note that the call to the task switch ISR occurs prior to the task's exec
582
;  function to allow every task to finish its setup BEFORE any task begins
583
;  processing.
584
;
585
; Last, the final branch is only taken if the I bit is still NOT set. If it
586
;  somehow gets set, the task will trigger a system panic (which never returns)
587
 
588
; There should be one loop per task. Note that the labels are used in to create
589
;  the table of entry points
590
 
591
.MACRO INSTANCE_TASK_LOOP
592
TASK\@_MAIN:  JSR  TASK\@_INIT
593
_TASK\@_LOOP: CALL_TASK_SW
594
              JSR  TASK\@_EXEC
595
              BNI  _TASK\@_LOOP
596
              CALL_PANIC
597
.ENDM
598
 
599
; INSTANCE_MAIN_LOOPS expands to create the stub main loops for all of the
600
;  tasks based on the template above. There should be one setup per task, hence
601
;  the repeat based on TASK_COUNT. Note that the output labels will be used to
602
;  populate fields in the task parameter table.
603
.MACRO INSTANCE_TASK_LOOPS
604
              .REPEAT TASK_COUNT
605
              INSTANCE_TASK_LOOP
606
              .ENDR
607
.ENDM
608
;------------------------------------------------------------------------------
609
 
610
;------------------------------------------------------------------------------
611
; Software-callable Interrupts
612
;------------------------------------------------------------------------------
613
 
614
; CALL_PANIC executes the same ISR as a memory fault and triggers the shutdown
615
;  sequence. This requires a hard-reset to recover
616
.MACRO CALL_PANIC
617
              INT  0
618
.ENDM
619
 
620
; CALL_TASK_SW executes the same ISR as the pre-emption timer, and allows tasks
621
;  to give up any remaining time
622
.MACRO CALL_TASK_SW
623
              INT  1
624
.ENDM
625
 
626
; Interrupt 2 is reserved for the external interrupt manager. Calling it would
627
;  likely be harmless, but do no real work.
628
 
629
; CALL_SUPV_FNn allow tasks to execute code in an interrupt/supervisor context
630
;  and should be used with caution.
631
.MACRO CALL_SUPV_FN0
632
              INT  3
633
.ENDM
634
 
635
.MACRO CALL_SUPV_FN1
636
              INT  4
637
.ENDM
638
 
639
.MACRO CALL_SUPV_FN2
640
              INT  5
641
.ENDM
642
 
643
.MACRO CALL_SUPV_FN3
644
              INT  6
645
.ENDM
646
 
647
.MACRO CALL_SUPV_FN4
648
              INT  7
649
.ENDM
650
 
651
;------------------------------------------------------------------------------
652
 
653
;------------------------------------------------------------------------------
654
;  CPU Interrupt Control Macros
655
;------------------------------------------------------------------------------
656
.MACRO DISABLE_CPU_INTS
657
              CLR  R0
658
              SMSK
659
.ENDM
660
 
661
.MACRO ENABLE_CPU_INTS
662
              LDI  R0, #CPU_INT_ENABLES
663
              SMSK
664
.ENDM
665
;------------------------------------------------------------------------------
666
 
667
;------------------------------------------------------------------------------
668
; RAM Access Fault Shutdown (CALL_PANIC)
669
;  If a task manages to cause a memory fault, sets default conditions and
670
;   then soft-halts the CPU.
671
;  Note that DISABLE_PREEMPTION_TIMER, SET_FAULT_FLAGS are defined in
672
;   "main_const.s", while PANIC_HALT macro calls each task's PANICn_HALT macro
673
;------------------------------------------------------------------------------
674
 
675
.MACRO PROCESS_RAM_FAULT
676
              DISABLE_CPU_INTS         ; Disable interrupts
677
              DISABLE_PREEMPTION_TIMER ; Disable the task timer
678
              SET_FAULT_FLAGS          ; Copy the faulting task info
679
              EXEC_PANIC_HALT          ; Run any necessary shutdown code
680
_RFLT_HALT:   WAI                      ; Soft-Halt the CPU
681
              JMP  _RFLT_HALT          ; This shouldn't happen, but if it does
682
.ENDM
683
 
684
.MACRO CREATE_PANIC_TASK_BLOCK
685
              LDI  R0, #\@
686
              LDI  R1, #PARAM_TABLE_OFFSET
687
              MUL  R1
688
 
689
              LDA  R2, TASK_PARAMS_PTR + 0  ; Load R3:R2 with the start of the
690
              LDA  R3, TASK_PARAMS_PTR + 1  ;  task parameter region
691
 
692
              ADD  R2                  ; Add [R3:R2] + [R1:R0] -> [R3:R2]
693
              T0X  R2
694
              TX0  R1
695
              ADC  R3
696
              T0X  R3
697
 
698
              ; Update the WQL for the task's panic code so each task isn't
699
              ;  doing this on its own
700
 
701
              LDO  R2, PARAM_WQL_LOW
702
              STA  R0, IO_WRITE_QUAL
703
 
704
              TASK\@_PANIC
705
.ENDM
706
 
707
.MACRO EXEC_PANIC_HALT
708
              .REPEAT TASK_COUNT
709
              CREATE_PANIC_TASK_BLOCK
710
              .ENDR
711
.ENDM
712
 
713
;------------------------------------------------------------------------------
714
 
715
;------------------------------------------------------------------------------
716
; Task Switcher ISR (CALL_TASK_SW)
717
;
718
; Handles switching context between tasks when called.
719
;------------------------------------------------------------------------------
720
 
721
.MACRO SWITCH_TASKS
722 304 jshamlet
              SUSPEND_THIS_TASK
723 301 jshamlet
              AWAKEN_NEXT_TASK
724
.ENDM
725
 
726
;------------------------------------------------------------------------------
727
 
728
;------------------------------------------------------------------------------
729
; External System Interrupt Map & ISR Macros
730
; This code configures the external I/O interrupt manager at startup
731
;------------------------------------------------------------------------------
732
 
733
; Setup the external I/O Interrupt manager by writing the mask registers and
734
;  clearing any pending interrupts. Note that the interrupt enable constants
735
;  are defined in ext_isr_config.s
736
 
737
.MACRO INITIALIZE_IO_INTMGR
738
              CLR  R0                     ; Disable all external interrupts
739
              STA  R0, EXT_INT_MASK
740
 
741
              LDI  R0, #SEMAPHORE_VAL     ; Clear any pending interrupts
742
              STA  R0, EXT_INT_PEND       ;  and do a master acknowledge
743
              STA  R0, EXT_INT_ACK
744
 
745
              LDI  R0, #EXT_INTERRUPT_EN_L; Re-enable the external interrupts
746
              STA  R0, EXT_INT_MASK
747
.ENDM
748
 
749
.MACRO INITIALIZE_IO_INTMGR16
750
              CLR  R0                     ; Disable all external interrupts
751
              STA  R0, EXT_INT16_MASK_L
752
              STA  R0, EXT_INT16_MASK_H
753
 
754
              LDI  R0, #SEMAPHORE_VAL     ; Clear any pending interrupts
755
              STA  R0, EXT_INT16_PEND_L   ;  and do a master acknowledge
756
              STA  R0, EXT_INT16_PEND_H
757
              STA  R0, EXT_INT16_ACK
758
 
759
              LDI  R0, #EXT_INTERRUPT_EN_L; Re-enable the external interrupts
760
              STA  R0, EXT_INT16_MASK_L
761
 
762
              LDI  R0, #EXT_INTERRUPT_EN_H; Re-enable the external interrupts
763
              STA  R0, EXT_INT16_MASK_H
764
.ENDM
765
 
766
; Sets up an individual external interrupt macro. Note that these refer to
767
;  macros defined in ext_isr_config.s
768
 
769
.MACRO PROCESS_EXT_ISR
770
              SET_INT\@_FLAGS
771
 
772
              TX0  R3                  ; When done with the flags, update the
773
              LDI  R1, #EXT_INT\@_BIT  ;  mask clear register with the ext bit
774
              OR   R1                  ;  and restore it to R3. Then, before
775
              T0X  R3                  ;  falling into the next check, make
776
              TX0  R2                  ;  sure to restore the current ints
777
.ENDM
778
 
779
; This code checks the external I/O interrupt manager status and processes the
780
;  flag code for each interrupt source.
781
 
782
.MACRO CHECK_EXTERNAL_IO_INTS
783
_EXT_INT_STRT:PSH  R0
784
              PSH  R1
785
              PSH  R2
786
              PSH  R3
787
 
788
_EXT_INT_LO:  CLR  R0                  ; R3 will be our pending mask clear reg,
789
              T0X  R3                  ;  so clear it here
790
 
791
              LDA  R0, EXT_INT_PEND    ; R2 will be our current pending reg, so
792
              T0X  R2                  ;  load it from the hardware here
793
 
794
_EXT_INT_0:   BTT  0
795
              BRZ  _EXT_INT_1
796
              PROCESS_EXT_ISR
797
 
798
_EXT_INT_1:   BTT  1
799
              BRZ  _EXT_INT_2
800
              PROCESS_EXT_ISR
801
 
802
_EXT_INT_2:   BTT  2
803
              BRZ  _EXT_INT_3
804
              PROCESS_EXT_ISR
805
 
806
_EXT_INT_3:   BTT  3
807
              BRZ  _EXT_INT_4
808
              PROCESS_EXT_ISR
809
 
810
_EXT_INT_4:   BTT  4
811
              BRZ  _EXT_INT_5
812
              PROCESS_EXT_ISR
813
 
814
_EXT_INT_5:   BTT  5
815
              BRZ  _EXT_INT_6
816
              PROCESS_EXT_ISR
817
 
818
_EXT_INT_6:   BTT  6
819
              BRZ  _EXT_INT_7
820
              PROCESS_EXT_ISR
821
 
822
_EXT_INT_7:   BTT  7
823
              BRZ  _EXT_INT_CLR
824
              PROCESS_EXT_ISR
825
 
826
_EXT_INT_CLR: STA  R3, EXT_INT_PEND
827
 
828
              STA  R3, EXT_INT_ACK     ; pending ints and ack the HW
829
 
830
              POP  R3
831
              POP  R2
832
              POP  R1
833
              POP  R0
834
              RTI
835
.ENDM
836
 
837
.MACRO CHECK_EXTERNAL_IO_INTS16
838
_EXT_INT_STRT:PSH  R0
839
              PSH  R1
840
              PSH  R2
841
              PSH  R3
842
 
843
_EXT_INT_LO:  CLR  R0                  ; R3 will be our pending mask clear reg,
844
              T0X  R3                  ;  so clear it here
845
 
846
              LDA  R0, EXT_INT16_PEND_L; R2 will be our current pending reg, so
847
              T0X  R2                  ;  load it from the hardware here
848
 
849
_EXT_INT_0:   BTT  0
850
              BRZ  _EXT_INT_1
851
              PROCESS_EXT_ISR
852
 
853
_EXT_INT_1:   BTT  1
854
              BRZ  _EXT_INT_2
855
              PROCESS_EXT_ISR
856
 
857
_EXT_INT_2:   BTT  2
858
              BRZ  _EXT_INT_3
859
              PROCESS_EXT_ISR
860
 
861
_EXT_INT_3:   BTT  3
862
              BRZ  _EXT_INT_4
863
              PROCESS_EXT_ISR
864
 
865
_EXT_INT_4:   BTT  4
866
              BRZ  _EXT_INT_5
867
              PROCESS_EXT_ISR
868
 
869
_EXT_INT_5:   BTT  5
870
              BRZ  _EXT_INT_6
871
              PROCESS_EXT_ISR
872
 
873
_EXT_INT_6:   BTT  6
874
              BRZ  _EXT_INT_7
875
              PROCESS_EXT_ISR
876
 
877
_EXT_INT_7:   BTT  7
878
              BRZ  _EXT_INT_CLRL
879
              PROCESS_EXT_ISR
880
 
881
_EXT_INT_CLRL:STA  R3, EXT_INT16_PEND_L
882
 
883
_EXT_INT_HI:  CLR  R0
884
              T0X  R3
885
 
886
              LDA  R0, EXT_INT16_PEND_H
887
              T0X  R2
888
 
889
_EXT_INT_8:   BTT  0
890
              BRZ  _EXT_INT_9
891
              PROCESS_EXT_ISR
892
 
893
_EXT_INT_9:   BTT  1
894
              BRZ  _EXT_INT_10
895
              PROCESS_EXT_ISR
896
 
897
_EXT_INT_10:  BTT  2
898
              BRZ  _EXT_INT_11
899
              PROCESS_EXT_ISR
900
 
901
_EXT_INT_11:  BTT  3
902
              BRZ  _EXT_INT_12
903
              PROCESS_EXT_ISR
904
 
905
_EXT_INT_12:  BTT  4
906
              BRZ  _EXT_INT_13
907
              PROCESS_EXT_ISR
908
 
909
_EXT_INT_13:  BTT  5
910
              BRZ  _EXT_INT_14
911
              PROCESS_EXT_ISR
912
 
913
_EXT_INT_14:  BTT  6
914
              BRZ  _EXT_INT_15
915
              PROCESS_EXT_ISR
916
 
917
_EXT_INT_15:  BTT  7
918
              BRZ  _EXT_INT_CLRH
919
              PROCESS_EXT_ISR
920
 
921
_EXT_INT_CLRH:STA  R3, EXT_INT16_PEND_H
922
 
923
_EXT_ACK_HW:  STA  R3, EXT_INT16_ACK     ; pending ints and ack the HW
924
 
925
              POP  R3
926
              POP  R2
927
              POP  R1
928
              POP  R0
929
              RTI
930
.ENDM
931
;------------------------------------------------------------------------------
932
 
933
;------------------------------------------------------------------------------
934
; ISR/Supervisory Mode Functions - Allows tasks to define up to 5 functions
935
;  that will operate in supervisor mode by calling a soft-int.
936
;
937 302 jshamlet
; Note 1: that using these functions requires at least 5 free bytes of stack
938
;
939
; Note 2: Due to assembler limitations, it is actually necessary for each task
940 301 jshamlet
;  to define all 5 sets of these macros, even if not used. These are defined
941
;  in the pattern of TASKx_SPV_FUNCy, where x is the task number and
942
;  y is the function 0-4.
943
;
944 302 jshamlet
; Note 3: Task code for these functions should NOT use RTS or RTI, as this WILL
945 301 jshamlet
;  corrupt their stacks and likely crash the whole system. These are intended
946
;  for operations that are atomic in nature, or that require supervisor perms
947 302 jshamlet
;  due to write access (writing flags/messages to other tasks) Registers will
948
;  be preserved in local system memory and restored prior to entering the stub
949
;  effectively meaning that registers will retain their state through the
950
;  function call. The state of system flags will NOT be retained, however.
951 301 jshamlet
;
952 302 jshamlet
; Note 4: These functions will run to completion (or hang) regardless of the
953 301 jshamlet
;  task timer, as interrupts can't pre-empt each other, so caution should be
954
;  used with them. However, both the internal and external interrupt managers
955
;  will latch incoming interrupts while these are running.
956
;------------------------------------------------------------------------------
957
 
958
; CREATE_SUPV_FUNC creates an individual supervisory task function, which is
959
;  referenced in the ISR table. (EXEC_SUPVn is used in the interrupt table)
960
 
961
.MACRO CREATE_SUPV_FUNC
962 302 jshamlet
EXEC_SUPV\@:  STA  R0, TaskMgr.Temp_R0  ; Copy R0-R3 to local RAM, not stack
963
              STA  R1, TaskMgr.Temp_R1
964
              STA  R2, TaskMgr.Temp_R2
965
              STA  R3, TaskMgr.Temp_R3
966 301 jshamlet
 
967
              REINIT_TASK_TABLE_PTR    ; Setup R3:R2 to point to the task table
968
 
969
              LDO  R2, SUPV_FN\@_ENTRY_HIGH
970
              PSH  R0
971
 
972
              LDO  R2, SUPV_FN\@_ENTRY_LOW
973
              PSH  R0
974
 
975 302 jshamlet
              LDA  R3, TaskMgr.Temp_R3 ; Replace R0-R3 from local RAM so that
976
              LDA  R2, TaskMgr.Temp_R2 ;  the stub has the same register space
977
              LDA  R1, TaskMgr.Temp_R1 ; as a function call - less the flag
978
              LDA  R0, TaskMgr.Temp_R0 ; state, which isn't preserved
979
 
980 301 jshamlet
              RTS                      ; Use RTS to "return" to our jump addr
981
 
982 302 jshamlet
              .REPEAT TASK_COUNT       ; Create a stub for each task. The final
983
              CREATE_F\@_FUNCTION_STUB ;  RTI will be handled in the stubs
984
              .ENDR
985 301 jshamlet
.ENDM
986
 
987
; CREATE_Fn_FUNCTION_STUB creates an entry point that is referenced in the
988
;  TASK_PARAM_TABLE, and is "RTS JMP'ed" to by the code from CREATE_SUPV_FUNC.
989
;  Because RTS was used to reach the code generated in these blocks, a final
990
;  JMP instruction will return to the calling supervisory function without
991
;  disrupting the stack. (These aren't technically subroutines)
992
 
993
.MACRO CREATE_F0_FUNCTION_STUB
994 302 jshamlet
_F0_EXE_S\@:  TASK\@_SUPV_FN0          ; Run the stub code from the task
995
              RTI                      ; Return from the interrupt
996 301 jshamlet
.ENDM
997
 
998
.MACRO CREATE_F1_FUNCTION_STUB
999 302 jshamlet
_F1_EXE_S\@:  TASK\@_SUPV_FN1          ; Run the stub code from the task
1000
              RTI                      ; Return from the interrupt
1001 301 jshamlet
.ENDM
1002
 
1003
.MACRO CREATE_F2_FUNCTION_STUB
1004 302 jshamlet
_F2_EXE_S\@:  TASK\@_SUPV_FN2          ; Run the stub code from the task
1005
              RTI                      ; Return from the interrupt
1006 301 jshamlet
.ENDM
1007
 
1008
.MACRO CREATE_F3_FUNCTION_STUB
1009 302 jshamlet
_F3_EXE_S\@:  TASK\@_SUPV_FN3          ; Run the stub code from the task
1010
              RTI                      ; Return from the interrupt
1011 301 jshamlet
.ENDM
1012
 
1013
.MACRO CREATE_F4_FUNCTION_STUB
1014 302 jshamlet
_F4_EXE_S\@:  TASK\@_SUPV_FN4          ; Run the stub code from the task
1015
              RTI                      ; Return from the interrupt
1016 301 jshamlet
.ENDM
1017
 
1018
; INSTANCE_SUPV_FUNCS creates all 5 supervisory function entry points and a set
1019
;  of stub functions for each task and is used to place everything in ROM
1020
.MACRO INSTANCE_SUPV_FUNCS
1021
              .REPEAT 5
1022
              CREATE_SUPV_FUNC
1023
              .ENDR
1024
.ENDM
1025
 
1026
;------------------------------------------------------------------------------

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.