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 302

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

powered by: WebSVN 2.1.0

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