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 303

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

powered by: WebSVN 2.1.0

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