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 301

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

powered by: WebSVN 2.1.0

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