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 304

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 304 jshamlet
; SETUP_TASK is a template used to generate code that sets up a single task's
342
; stack and stack pointer for each a task. This macros will temporarily
343
;  relocate the stack pointer, push the task's initial state to the task's
344
;  stack. Note that it is important to also ensure that the stack has data to
345
;  not only restore the return address, but also R7:R0, as well as the flag
346
;  state.
347
.MACRO SETUP_TASK
348
              LDI  R0, #\@
349
              STA  R0, TaskMgr.This_Task    ; Write This_Task
350
 
351
              REINIT_TASK_TABLE_PTR         ; Use This_Task to initialize R3:R2
352
 
353 301 jshamlet
              ; Get the task's starting stack address from the table and load
354
              ;  it into the CPU SP
355
              LDO  R2, PARAM_STACK_ADDR_HIGH
356
              T0X  R1
357
              LDO  R2, PARAM_STACK_ADDR_LOW
358
              RELOCATE_SP                 ; R1:R0 -> CPU SP
359
 
360
              ; From here on out, the CPU SP is pointing to the target task's
361
              ;  stack region, so we can initialize its stack memory
362
 
363 304 jshamlet
              ; Write initial flag value to simulate entering code as an ISR
364 301 jshamlet
              CLR  R0
365
              PSH  R0
366
 
367
              ; Initialize the return address to point to the "initialize"
368
              ;  portion of the task, so that the task can do its one-time
369
              ;  startup code.
370
 
371
              LDO  R2, PARAM_MAIN_ADDR_HIGH ; Write return PC MSB
372
              PSH  R0
373
 
374
              LDO  R2, PARAM_MAIN_ADDR_LOW  ; Write return PC LSB
375
              PSH  R0
376
 
377
              ; Setup the initial reg values
378
              CLR  R0                  ; Initialize all registers to 0
379 304 jshamlet
              T0X  R1
380
              T0X  R2
381
              T0X  R3
382
              T0X  R4
383
              T0X  R5
384
              T0X  R6
385
              T0X  R7
386 301 jshamlet
 
387 304 jshamlet
              ; Once the task's initial state has been created, "suspend"
388
              ;  the task. This will effective initialize its state and
389
              ;  SP pointer
390
              SUSPEND_THIS_TASK
391
.ENDM
392 301 jshamlet
 
393 304 jshamlet
; SUSPEND_THIS_TASK pushes all of the registers to a task's stack, then
394
;  backups up the stack pointer to the system memory backup location for that
395
;  task.
396
.MACRO SUSPEND_THIS_TASK
397
              BACKUP_FULL_CONTEXT
398
              BACKUP_STACK_POINTER
399
.ENDM
400
 
401
; BACKUP_STACK_POINTER uses the This_Task variable to configure R3:R2 as a
402
;  pointer into the system memory where stack pointer backups are stored, then
403
;  obtains the current stack address and pushes it to the task's backup
404
;  SP variable
405
.MACRO BACKUP_STACK_POINTER
406
              LDA  R0, TaskMgr.This_Task    ; Get the task number
407
              LDI  R1, #STACK_TABLE_OFFSET  ; Multiply it by 2
408 301 jshamlet
              MUL  R1
409
 
410 304 jshamlet
              LDA  R2, STACK_MEMORY_PTR + 0 ; Load R3:R2 with the start of the
411
              LDA  R3, STACK_MEMORY_PTR + 1 ;  stack memory region
412 301 jshamlet
 
413 304 jshamlet
              ADD  R2                  ; Add [R3:R2] + [R1:R0] -> [R3:R2]
414 301 jshamlet
              T0X  R2
415
              TX0  R1
416
              ADC  R3
417
              T0X  R3
418
 
419
              RETRIEVE_SP
420
              STX  R2
421
              TX0  R1
422
              STO  R2,1
423
.ENDM
424
 
425 304 jshamlet
; RESTORE_STACK_POINTER uses the This_Task variable to configure R3:R2 as a
426
;  pointer into the system memory where stack pointer backups are stored. It
427
;  then looks up the task's SP backup variable and pushes it back to the CPU SP
428
.MACRO RESTORE_STACK_POINTER
429 301 jshamlet
              LDA  R0, TaskMgr.This_Task    ; Get the task number
430
              LDI  R1, #STACK_TABLE_OFFSET  ; Multiply it by 2
431
              MUL  R1
432
 
433
              LDA  R2, STACK_MEMORY_PTR + 0 ; Load R3:R2 with the start of the
434
              LDA  R3, STACK_MEMORY_PTR + 1 ;  stack memory region
435
 
436
              ADD  R2                  ; Add [R3:R2] + [R1:R0] -> [R3:R2]
437
              T0X  R2
438
              TX0  R1
439
              ADC  R3
440
              T0X  R3
441
 
442 303 jshamlet
              LDO  R2,1                ; Copy [R3:R2]* -> R1:R0
443 301 jshamlet
              T0X  R1
444 303 jshamlet
              LDX  R2
445 301 jshamlet
              RELOCATE_SP              ; Update R1:R0 -> CPU SP
446 304 jshamlet
.ENDM
447 301 jshamlet
 
448 304 jshamlet
; RESTORE_TASK_PERMISSIONS looks up the current (new) task's RAM & I/O write
449
;  permissions (masks) and reconfigures the hardware to allow access.
450
.MACRO RESTORE_TASK_PERMISSIONS
451 301 jshamlet
              REINIT_TASK_TABLE_PTR    ; Setup R3:R2 to point to the task table
452
 
453
              ; Rewrite the RAM WPR register for this task. Note that the WPR
454
              ; is a 32-bit register.
455
              LDO  R2, PARAM_WPR_BYTE0
456
              STA  R0, WPR_MASK_0
457
 
458
              LDO  R2, PARAM_WPR_BYTE1
459
              STA  R0, WPR_MASK_1
460
 
461
              LDO  R2, PARAM_WPR_BYTE2
462
              STA  R0, WPR_MASK_2
463
 
464
              LDO  R2, PARAM_WPR_BYTE3
465
              STA  R0, WPR_MASK_3
466
 
467
              LDO  R2, PARAM_WQL_LOW   ; Update the new task's WQL
468
              STA  R0, IO_WRITE_QUAL
469 304 jshamlet
.ENDM
470 301 jshamlet
 
471 304 jshamlet
; INIT_NEXT_TASK forces the Next_Task variable to 0 (Task 0)
472
.MACRO INIT_NEXT_TASK
473
              CLR  R0
474
              STA  R0, TaskMgr.Next_Task
475
.ENDM
476
 
477
; ADVANCE_NEXT_TASK implements the simple scheduler. By default, the task
478
; manager uses a simple round-robin scheduler, unless an ISR alters the
479
;  Next_Task variable, so increment the task count, check it against the
480
;  total task count, and reset it to task 0 if necessary.
481
.MACRO ADVANCE_NEXT_TASK
482
              LDA  R1, TaskMgr.Next_Task ; Copy Next_Task -> This_Task
483
              STA  R1, TaskMgr.This_Task
484
 
485
              INC  R1                  ; Increment the task count
486
              LDI  R0, #TASK_COUNT     ; Compare it with the task count
487
              XOR  R1
488
              BNZ _TS_ADV_TN_\@        ; If it matches the task count
489
              LDI  R1, #$00            ;  reset the counter to zero
490
_TS_ADV_TN_\@:STA  R1, TaskMgr.Next_Task ; Store the new value into Next_Task
491
.ENDM
492
 
493
; AWAKEN_NEXT_TASK is responsible for updating the Next_Task variable, then
494
;  using it to restore the stack pointer from the system memory copy. It then
495
;  updates the memory write protection parameters and I/O write qualification
496
;  register for the new task. Finally, it resets the pre-emption timer and
497
;  restores the register state from the task's stack.
498
.MACRO AWAKEN_NEXT_TASK
499
              ADVANCE_NEXT_TASK        ; Advance the task positions
500
              RESTORE_STACK_POINTER    ; Lookup the new task's table pointer
501
              RESTORE_TASK_PERMISSIONS ; Restore the task's write access masks
502 301 jshamlet
              RESET_PREEMPTION_TIMER   ; Reset the PIT timer
503
              RESTORE_FULL_CONTEXT     ; Restore the new task's register state
504 304 jshamlet
              RTI                      ; Return to the new task
505 301 jshamlet
.ENDM
506
;------------------------------------------------------------------------------
507
 
508
;------------------------------------------------------------------------------
509
; System Start
510
;
511
; System initialization requires that the CPU start in supervisor mode, as it
512
;  writes to every active region in memory. Thus, if the CPU is NOT in
513
;  in supervisor mode, something has gone horribly wrong. This branch locks the
514
;  main loop if the I bit is not set. This is probably unnecessary now that the
515
;  panic ISR is in place.
516
;------------------------------------------------------------------------------
517
 
518 304 jshamlet
; INSTANCE_TASK_SETUP expands to create setup code for all of the tasks based
519
;  on the template above. There should be one setup per task, hence the repeat
520
;  based on TASK_COUNT
521
.MACRO INSTANCE_TASK_SETUP
522
          .REPT TASK_COUNT
523
              SETUP_TASK
524
          .ENDR
525 301 jshamlet
.ENDM
526
 
527
.MACRO BOOT_SYSTEM
528
; Before beginning, turn off all of the CPU interrupts (The NMI will still be
529
;  active, but memory write protection is effectively disabled with the I-bit
530
;  set) Note that this code is running in interrupt context (I-bit is set)
531
;  so it is "uninterruptible" due to the HDL generic being set. However, this
532
;  doesn't prevent pending interrupts from being latched by the CPU.
533
; Note that this macro is defined in "isr_const.s"
534
              DISABLE_CPU_INTS
535
 
536
; Even though interrupts are off, disable the task timer so that there isn't
537
;  a pending task timer interrupt waiting when interrupts are re-enabled. This
538
;  avoids the first task missing out on initialization.
539
              DISABLE_PREEMPTION_TIMER
540
 
541
; Initialize the system fault flags
542
              INITIALIZE_FAULT_FLAGS
543
 
544
; Setup the stack and stack pointer for each of the tasks. (see above)
545
              INSTANCE_TASK_SETUP
546
 
547
; Before starting, make sure the external interrupt controller has been
548
;  initialized. Initialization of the external interrupt controller involves
549
;  clearing any pending interrupts and setting up the interrupt mask. Finally,
550
;  the CPU interrupts should be enabled at this point, as the interrupt core is
551
;  ready.
552
.IFDEF INTMGR16
553
              INITIALIZE_IO_INTMGR16      ; Setup the 16-bit IF
554
.ELSE
555
              INITIALIZE_IO_INTMGR        ; Setup the 8-bit IF
556
.ENDIF
557
; Once the external interrupt manager is configured, enable the CPU interrupts
558
              ENABLE_CPU_INTS             ; Enable the CPU interrupt inputs
559
 
560
; Like the task switcher ISR, restore the full CPU state for the first task
561 304 jshamlet
              INIT_NEXT_TASK              ; Reset the next task to task 0
562
              AWAKEN_NEXT_TASK            ; Load task 0's context to system
563 301 jshamlet
 
564
; Create all of the task loops here.
565 304 jshamlet
              INSTANCE_TASK_LOOPS         ; Instantiate the main task loops
566 301 jshamlet
.ENDM
567
;------------------------------------------------------------------------------
568
 
569
;------------------------------------------------------------------------------
570
; Task Loops
571
;------------------------------------------------------------------------------
572
 
573
; INSTANCE_MAIN_LOOP:
574
; These loops represent each task's "main()", and should never "exit".
575
; Each task's func.s file should declare two required functions, TASKn_INIT and
576
; TASKn_EXEC
577
;
578
; Note that the call to the task switch ISR occurs prior to the task's exec
579
;  function to allow every task to finish its setup BEFORE any task begins
580
;  processing.
581
;
582
; Last, the final branch is only taken if the I bit is still NOT set. If it
583
;  somehow gets set, the task will trigger a system panic (which never returns)
584
 
585
; There should be one loop per task. Note that the labels are used in to create
586
;  the table of entry points
587
 
588
.MACRO INSTANCE_TASK_LOOP
589
TASK\@_MAIN:  JSR  TASK\@_INIT
590
_TASK\@_LOOP: CALL_TASK_SW
591
              JSR  TASK\@_EXEC
592
              BNI  _TASK\@_LOOP
593
              CALL_PANIC
594
.ENDM
595
 
596
; INSTANCE_MAIN_LOOPS expands to create the stub main loops for all of the
597
;  tasks based on the template above. There should be one setup per task, hence
598
;  the repeat based on TASK_COUNT. Note that the output labels will be used to
599
;  populate fields in the task parameter table.
600
.MACRO INSTANCE_TASK_LOOPS
601
              .REPEAT TASK_COUNT
602
              INSTANCE_TASK_LOOP
603
              .ENDR
604
.ENDM
605
;------------------------------------------------------------------------------
606
 
607
;------------------------------------------------------------------------------
608
; Software-callable Interrupts
609
;------------------------------------------------------------------------------
610
 
611
; CALL_PANIC executes the same ISR as a memory fault and triggers the shutdown
612
;  sequence. This requires a hard-reset to recover
613
.MACRO CALL_PANIC
614
              INT  0
615
.ENDM
616
 
617
; CALL_TASK_SW executes the same ISR as the pre-emption timer, and allows tasks
618
;  to give up any remaining time
619
.MACRO CALL_TASK_SW
620
              INT  1
621
.ENDM
622
 
623
; Interrupt 2 is reserved for the external interrupt manager. Calling it would
624
;  likely be harmless, but do no real work.
625
 
626
; CALL_SUPV_FNn allow tasks to execute code in an interrupt/supervisor context
627
;  and should be used with caution.
628
.MACRO CALL_SUPV_FN0
629
              INT  3
630
.ENDM
631
 
632
.MACRO CALL_SUPV_FN1
633
              INT  4
634
.ENDM
635
 
636
.MACRO CALL_SUPV_FN2
637
              INT  5
638
.ENDM
639
 
640
.MACRO CALL_SUPV_FN3
641
              INT  6
642
.ENDM
643
 
644
.MACRO CALL_SUPV_FN4
645
              INT  7
646
.ENDM
647
 
648
;------------------------------------------------------------------------------
649
 
650
;------------------------------------------------------------------------------
651
;  CPU Interrupt Control Macros
652
;------------------------------------------------------------------------------
653
.MACRO DISABLE_CPU_INTS
654
              CLR  R0
655
              SMSK
656
.ENDM
657
 
658
.MACRO ENABLE_CPU_INTS
659
              LDI  R0, #CPU_INT_ENABLES
660
              SMSK
661
.ENDM
662
;------------------------------------------------------------------------------
663
 
664
;------------------------------------------------------------------------------
665
; RAM Access Fault Shutdown (CALL_PANIC)
666
;  If a task manages to cause a memory fault, sets default conditions and
667
;   then soft-halts the CPU.
668
;  Note that DISABLE_PREEMPTION_TIMER, SET_FAULT_FLAGS are defined in
669
;   "main_const.s", while PANIC_HALT macro calls each task's PANICn_HALT macro
670
;------------------------------------------------------------------------------
671
 
672
.MACRO PROCESS_RAM_FAULT
673
              DISABLE_CPU_INTS         ; Disable interrupts
674
              DISABLE_PREEMPTION_TIMER ; Disable the task timer
675
              SET_FAULT_FLAGS          ; Copy the faulting task info
676
              EXEC_PANIC_HALT          ; Run any necessary shutdown code
677
_RFLT_HALT:   WAI                      ; Soft-Halt the CPU
678
              JMP  _RFLT_HALT          ; This shouldn't happen, but if it does
679
.ENDM
680
 
681
.MACRO CREATE_PANIC_TASK_BLOCK
682
              LDI  R0, #\@
683
              LDI  R1, #PARAM_TABLE_OFFSET
684
              MUL  R1
685
 
686
              LDA  R2, TASK_PARAMS_PTR + 0  ; Load R3:R2 with the start of the
687
              LDA  R3, TASK_PARAMS_PTR + 1  ;  task parameter region
688
 
689
              ADD  R2                  ; Add [R3:R2] + [R1:R0] -> [R3:R2]
690
              T0X  R2
691
              TX0  R1
692
              ADC  R3
693
              T0X  R3
694
 
695
              ; Update the WQL for the task's panic code so each task isn't
696
              ;  doing this on its own
697
 
698
              LDO  R2, PARAM_WQL_LOW
699
              STA  R0, IO_WRITE_QUAL
700
 
701
              TASK\@_PANIC
702
.ENDM
703
 
704
.MACRO EXEC_PANIC_HALT
705
              .REPEAT TASK_COUNT
706
              CREATE_PANIC_TASK_BLOCK
707
              .ENDR
708
.ENDM
709
 
710
;------------------------------------------------------------------------------
711
 
712
;------------------------------------------------------------------------------
713
; Task Switcher ISR (CALL_TASK_SW)
714
;
715
; Handles switching context between tasks when called.
716
;------------------------------------------------------------------------------
717
 
718
.MACRO SWITCH_TASKS
719 304 jshamlet
              SUSPEND_THIS_TASK
720 301 jshamlet
              AWAKEN_NEXT_TASK
721
.ENDM
722
 
723
;------------------------------------------------------------------------------
724
 
725
;------------------------------------------------------------------------------
726
; External System Interrupt Map & ISR Macros
727
; This code configures the external I/O interrupt manager at startup
728
;------------------------------------------------------------------------------
729
 
730
; Setup the external I/O Interrupt manager by writing the mask registers and
731
;  clearing any pending interrupts. Note that the interrupt enable constants
732
;  are defined in ext_isr_config.s
733
 
734
.MACRO INITIALIZE_IO_INTMGR
735
              CLR  R0                     ; Disable all external interrupts
736
              STA  R0, EXT_INT_MASK
737
 
738
              LDI  R0, #SEMAPHORE_VAL     ; Clear any pending interrupts
739
              STA  R0, EXT_INT_PEND       ;  and do a master acknowledge
740
              STA  R0, EXT_INT_ACK
741
 
742
              LDI  R0, #EXT_INTERRUPT_EN_L; Re-enable the external interrupts
743
              STA  R0, EXT_INT_MASK
744
.ENDM
745
 
746
.MACRO INITIALIZE_IO_INTMGR16
747
              CLR  R0                     ; Disable all external interrupts
748
              STA  R0, EXT_INT16_MASK_L
749
              STA  R0, EXT_INT16_MASK_H
750
 
751
              LDI  R0, #SEMAPHORE_VAL     ; Clear any pending interrupts
752
              STA  R0, EXT_INT16_PEND_L   ;  and do a master acknowledge
753
              STA  R0, EXT_INT16_PEND_H
754
              STA  R0, EXT_INT16_ACK
755
 
756
              LDI  R0, #EXT_INTERRUPT_EN_L; Re-enable the external interrupts
757
              STA  R0, EXT_INT16_MASK_L
758
 
759
              LDI  R0, #EXT_INTERRUPT_EN_H; Re-enable the external interrupts
760
              STA  R0, EXT_INT16_MASK_H
761
.ENDM
762
 
763
; Sets up an individual external interrupt macro. Note that these refer to
764
;  macros defined in ext_isr_config.s
765
 
766
.MACRO PROCESS_EXT_ISR
767
              SET_INT\@_FLAGS
768
 
769
              TX0  R3                  ; When done with the flags, update the
770
              LDI  R1, #EXT_INT\@_BIT  ;  mask clear register with the ext bit
771
              OR   R1                  ;  and restore it to R3. Then, before
772
              T0X  R3                  ;  falling into the next check, make
773
              TX0  R2                  ;  sure to restore the current ints
774
.ENDM
775
 
776
; This code checks the external I/O interrupt manager status and processes the
777
;  flag code for each interrupt source.
778
 
779
.MACRO CHECK_EXTERNAL_IO_INTS
780
_EXT_INT_STRT:PSH  R0
781
              PSH  R1
782
              PSH  R2
783
              PSH  R3
784
 
785
_EXT_INT_LO:  CLR  R0                  ; R3 will be our pending mask clear reg,
786
              T0X  R3                  ;  so clear it here
787
 
788
              LDA  R0, EXT_INT_PEND    ; R2 will be our current pending reg, so
789
              T0X  R2                  ;  load it from the hardware here
790
 
791
_EXT_INT_0:   BTT  0
792
              BRZ  _EXT_INT_1
793
              PROCESS_EXT_ISR
794
 
795
_EXT_INT_1:   BTT  1
796
              BRZ  _EXT_INT_2
797
              PROCESS_EXT_ISR
798
 
799
_EXT_INT_2:   BTT  2
800
              BRZ  _EXT_INT_3
801
              PROCESS_EXT_ISR
802
 
803
_EXT_INT_3:   BTT  3
804
              BRZ  _EXT_INT_4
805
              PROCESS_EXT_ISR
806
 
807
_EXT_INT_4:   BTT  4
808
              BRZ  _EXT_INT_5
809
              PROCESS_EXT_ISR
810
 
811
_EXT_INT_5:   BTT  5
812
              BRZ  _EXT_INT_6
813
              PROCESS_EXT_ISR
814
 
815
_EXT_INT_6:   BTT  6
816
              BRZ  _EXT_INT_7
817
              PROCESS_EXT_ISR
818
 
819
_EXT_INT_7:   BTT  7
820
              BRZ  _EXT_INT_CLR
821
              PROCESS_EXT_ISR
822
 
823
_EXT_INT_CLR: STA  R3, EXT_INT_PEND
824
 
825
              STA  R3, EXT_INT_ACK     ; pending ints and ack the HW
826
 
827
              POP  R3
828
              POP  R2
829
              POP  R1
830
              POP  R0
831
              RTI
832
.ENDM
833
 
834
.MACRO CHECK_EXTERNAL_IO_INTS16
835
_EXT_INT_STRT:PSH  R0
836
              PSH  R1
837
              PSH  R2
838
              PSH  R3
839
 
840
_EXT_INT_LO:  CLR  R0                  ; R3 will be our pending mask clear reg,
841
              T0X  R3                  ;  so clear it here
842
 
843
              LDA  R0, EXT_INT16_PEND_L; R2 will be our current pending reg, so
844
              T0X  R2                  ;  load it from the hardware here
845
 
846
_EXT_INT_0:   BTT  0
847
              BRZ  _EXT_INT_1
848
              PROCESS_EXT_ISR
849
 
850
_EXT_INT_1:   BTT  1
851
              BRZ  _EXT_INT_2
852
              PROCESS_EXT_ISR
853
 
854
_EXT_INT_2:   BTT  2
855
              BRZ  _EXT_INT_3
856
              PROCESS_EXT_ISR
857
 
858
_EXT_INT_3:   BTT  3
859
              BRZ  _EXT_INT_4
860
              PROCESS_EXT_ISR
861
 
862
_EXT_INT_4:   BTT  4
863
              BRZ  _EXT_INT_5
864
              PROCESS_EXT_ISR
865
 
866
_EXT_INT_5:   BTT  5
867
              BRZ  _EXT_INT_6
868
              PROCESS_EXT_ISR
869
 
870
_EXT_INT_6:   BTT  6
871
              BRZ  _EXT_INT_7
872
              PROCESS_EXT_ISR
873
 
874
_EXT_INT_7:   BTT  7
875
              BRZ  _EXT_INT_CLRL
876
              PROCESS_EXT_ISR
877
 
878
_EXT_INT_CLRL:STA  R3, EXT_INT16_PEND_L
879
 
880
_EXT_INT_HI:  CLR  R0
881
              T0X  R3
882
 
883
              LDA  R0, EXT_INT16_PEND_H
884
              T0X  R2
885
 
886
_EXT_INT_8:   BTT  0
887
              BRZ  _EXT_INT_9
888
              PROCESS_EXT_ISR
889
 
890
_EXT_INT_9:   BTT  1
891
              BRZ  _EXT_INT_10
892
              PROCESS_EXT_ISR
893
 
894
_EXT_INT_10:  BTT  2
895
              BRZ  _EXT_INT_11
896
              PROCESS_EXT_ISR
897
 
898
_EXT_INT_11:  BTT  3
899
              BRZ  _EXT_INT_12
900
              PROCESS_EXT_ISR
901
 
902
_EXT_INT_12:  BTT  4
903
              BRZ  _EXT_INT_13
904
              PROCESS_EXT_ISR
905
 
906
_EXT_INT_13:  BTT  5
907
              BRZ  _EXT_INT_14
908
              PROCESS_EXT_ISR
909
 
910
_EXT_INT_14:  BTT  6
911
              BRZ  _EXT_INT_15
912
              PROCESS_EXT_ISR
913
 
914
_EXT_INT_15:  BTT  7
915
              BRZ  _EXT_INT_CLRH
916
              PROCESS_EXT_ISR
917
 
918
_EXT_INT_CLRH:STA  R3, EXT_INT16_PEND_H
919
 
920
_EXT_ACK_HW:  STA  R3, EXT_INT16_ACK     ; pending ints and ack the HW
921
 
922
              POP  R3
923
              POP  R2
924
              POP  R1
925
              POP  R0
926
              RTI
927
.ENDM
928
;------------------------------------------------------------------------------
929
 
930
;------------------------------------------------------------------------------
931
; ISR/Supervisory Mode Functions - Allows tasks to define up to 5 functions
932
;  that will operate in supervisor mode by calling a soft-int.
933
;
934 302 jshamlet
; Note 1: that using these functions requires at least 5 free bytes of stack
935
;
936
; Note 2: Due to assembler limitations, it is actually necessary for each task
937 301 jshamlet
;  to define all 5 sets of these macros, even if not used. These are defined
938
;  in the pattern of TASKx_SPV_FUNCy, where x is the task number and
939
;  y is the function 0-4.
940
;
941 302 jshamlet
; Note 3: Task code for these functions should NOT use RTS or RTI, as this WILL
942 301 jshamlet
;  corrupt their stacks and likely crash the whole system. These are intended
943
;  for operations that are atomic in nature, or that require supervisor perms
944 302 jshamlet
;  due to write access (writing flags/messages to other tasks) Registers will
945
;  be preserved in local system memory and restored prior to entering the stub
946
;  effectively meaning that registers will retain their state through the
947
;  function call. The state of system flags will NOT be retained, however.
948 301 jshamlet
;
949 302 jshamlet
; Note 4: These functions will run to completion (or hang) regardless of the
950 301 jshamlet
;  task timer, as interrupts can't pre-empt each other, so caution should be
951
;  used with them. However, both the internal and external interrupt managers
952
;  will latch incoming interrupts while these are running.
953
;------------------------------------------------------------------------------
954
 
955
; CREATE_SUPV_FUNC creates an individual supervisory task function, which is
956
;  referenced in the ISR table. (EXEC_SUPVn is used in the interrupt table)
957
 
958
.MACRO CREATE_SUPV_FUNC
959 302 jshamlet
EXEC_SUPV\@:  STA  R0, TaskMgr.Temp_R0  ; Copy R0-R3 to local RAM, not stack
960
              STA  R1, TaskMgr.Temp_R1
961
              STA  R2, TaskMgr.Temp_R2
962
              STA  R3, TaskMgr.Temp_R3
963 301 jshamlet
 
964
              REINIT_TASK_TABLE_PTR    ; Setup R3:R2 to point to the task table
965
 
966
              LDO  R2, SUPV_FN\@_ENTRY_HIGH
967
              PSH  R0
968
 
969
              LDO  R2, SUPV_FN\@_ENTRY_LOW
970
              PSH  R0
971
 
972 302 jshamlet
              LDA  R3, TaskMgr.Temp_R3 ; Replace R0-R3 from local RAM so that
973
              LDA  R2, TaskMgr.Temp_R2 ;  the stub has the same register space
974
              LDA  R1, TaskMgr.Temp_R1 ; as a function call - less the flag
975
              LDA  R0, TaskMgr.Temp_R0 ; state, which isn't preserved
976
 
977 301 jshamlet
              RTS                      ; Use RTS to "return" to our jump addr
978
 
979 302 jshamlet
              .REPEAT TASK_COUNT       ; Create a stub for each task. The final
980
              CREATE_F\@_FUNCTION_STUB ;  RTI will be handled in the stubs
981
              .ENDR
982 301 jshamlet
.ENDM
983
 
984
; CREATE_Fn_FUNCTION_STUB creates an entry point that is referenced in the
985
;  TASK_PARAM_TABLE, and is "RTS JMP'ed" to by the code from CREATE_SUPV_FUNC.
986
;  Because RTS was used to reach the code generated in these blocks, a final
987
;  JMP instruction will return to the calling supervisory function without
988
;  disrupting the stack. (These aren't technically subroutines)
989
 
990
.MACRO CREATE_F0_FUNCTION_STUB
991 302 jshamlet
_F0_EXE_S\@:  TASK\@_SUPV_FN0          ; Run the stub code from the task
992
              RTI                      ; Return from the interrupt
993 301 jshamlet
.ENDM
994
 
995
.MACRO CREATE_F1_FUNCTION_STUB
996 302 jshamlet
_F1_EXE_S\@:  TASK\@_SUPV_FN1          ; Run the stub code from the task
997
              RTI                      ; Return from the interrupt
998 301 jshamlet
.ENDM
999
 
1000
.MACRO CREATE_F2_FUNCTION_STUB
1001 302 jshamlet
_F2_EXE_S\@:  TASK\@_SUPV_FN2          ; Run the stub code from the task
1002
              RTI                      ; Return from the interrupt
1003 301 jshamlet
.ENDM
1004
 
1005
.MACRO CREATE_F3_FUNCTION_STUB
1006 302 jshamlet
_F3_EXE_S\@:  TASK\@_SUPV_FN3          ; Run the stub code from the task
1007
              RTI                      ; Return from the interrupt
1008 301 jshamlet
.ENDM
1009
 
1010
.MACRO CREATE_F4_FUNCTION_STUB
1011 302 jshamlet
_F4_EXE_S\@:  TASK\@_SUPV_FN4          ; Run the stub code from the task
1012
              RTI                      ; Return from the interrupt
1013 301 jshamlet
.ENDM
1014
 
1015
; INSTANCE_SUPV_FUNCS creates all 5 supervisory function entry points and a set
1016
;  of stub functions for each task and is used to place everything in ROM
1017
.MACRO INSTANCE_SUPV_FUNCS
1018
              .REPEAT 5
1019
              CREATE_SUPV_FUNC
1020
              .ENDR
1021
.ENDM
1022
 
1023
;------------------------------------------------------------------------------

powered by: WebSVN 2.1.0

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