.module rlpos.c .area data 0000 _main_frame_ptr:: 0000 .blkb 2 .area idata 0000 0000 .word 0 .area data 0002 _main_frame_x_ptr:: 0002 .blkb 2 .area idata 0002 0000 .word 0 .area data 0004 _temp_task_frame_ptr:: 0004 .blkb 2 .area idata 0004 0000 .word 0 .area data .area text ; lreg1 -> -4,x ; lreg2 -> -8,x ; ?temp -> -27,x ; ?temp -> -27,x ; ?temp -> -27,x ; ?temp -> -29,x ; ?temp -> -27,x ; addr -> -25,x ; result -> -23,x ; id -> -21,x ; temp_heap_ptr -> -19,x ; temp -> -17,x ; cop_cycle -> -16,x ; temp_heap_size -> -15,x ; priority_check -> -13,x ; deadline -> -12,x ; i -> -10,x 0000 _main:: 0000 34 pshx 0001 B775 tfr s,x 0003 1BF1D6 leas -42,sp 0006 ; /* RLPOS: RLPotter Operating System 0006 ; 0006 ; Version 0.5.2 for the 68HC12D60A microcontroller 0006 ; by Ryan Potter 0006 ; ryan@rlpotter.com 0006 ; 0006 ; 0006 ; v0.5.2: 0006 ; - make task_block dynamic 0006 ; 0006 ; v0.5.1: 0006 ; - implemented task msg box system for states in kernel 0006 ; - implemented COP watchdog reset timer 0006 ; - added system resources to semlib 0006 ; - added skeleton ISR_handler() code for the other interrupts 0006 ; - implemented _HC12Setup.c to initialize/harden the system 0006 ; 0006 ; v0.5 April 16, 2003: 0006 ; - added priority preemption 0006 ; - finished kernel task state switcher 0006 ; - it is now officially a legitimate 0006 ; rate monotonic 0006 ; priority preemptive 0006 ; multitasking 0006 ; Real Time Operating System :) 0006 ; - made kernel.c and semlib.c consistent with the 0006 ; rest of the kernel 0006 ; - included the early framework for a msg box system 0006 ; 0006 ; v0.4 April 13, 2003: 8096 bytes 0006 ; - gerneralized the shell command-line input parser: 0006 ; cmd (up to 32 chars) 0006 ; - added kernel and shell functions 0006 ; 0006 ; v0.3 April 12, 2003: 6155 bytes 0006 ; - added a beginning shell user interface. 0006 ; - added a resource control block and basic semaphore functions. 0006 ; - added basic kernel functions 0006 ; 0006 ; v0.2 April 9, 2003: 0006 ; - able to round-robin with RTI interrupt. 0006 ; - bonified/certified multitasking with 3 tasks. :) 0006 ; 0006 ; v0.1 April 3, 2003: 0006 ; - able to round-robin without interrupts. 0006 ; - not multitasking, really. 0006 ; 0006 ; v0.0 started April 1, 2003; 0 bytes 0006 ; - no idea where to start. 0006 ; - don't want to look at anyone else's work. ;0) 0006 ; 0006 ; 0006 ; 0006 ; 0006 ; Architecture/C assumptions: 0006 ; 1) 'D' register is the accumulator 0006 ; 2) 'X' register points to the top of the current stack 0006 ; 3) 'Y' register is for general use in indexed operations 0006 ; 4) the heap grows upward and mem segments allocated by malloc, 0006 ; realloc, and calloc are linear and contiguous. 0006 ; 5) the stack grows downwards, and there is no boundary checking. 0006 ; 0006 ; Potential problem areas: 0006 ; 1) 'running' section of the kernel get's compiled using extra 0006 ; push and pop instructions 0006 ; 2) run out of ram (global + stack + heap) 0006 ; 0006 ; */ 0006 ; 0006 ; 0006 ; 0006 ; #include <912d60.h> 0006 ; #include 0006 ; #include 0006 ; #include 0006 ; #include "kernel.h" 0006 ; 0006 ; 0006 ; 0006 ; 0006 ; // FUNCTION PROTOTYPES 0006 ; void RTI_handler(void); 0006 ; void sysInit(void); 0006 ; void shell(void); 0006 ; void sysTime(void); 0006 ; void (*task_ptr[NUMTASKS])(void); 0006 ; 0006 ; 0006 ; 0006 ; 0006 ; // GLOBAL VARIABLES 0006 ; unsigned char *main_frame_ptr = NULL; // bottom of main() frame 0006 ; unsigned char *main_frame_x_ptr = NULL; // top of main() frame (x-reg ptr) 0006 ; unsigned char *temp_task_frame_ptr = NULL; // temp CCR pointer for RTI 0006 ; 0006 ; 0006 ; extern unsigned int current; // current task id number 0006 ; extern unsigned long int system_tick; 0006 ; 0006 ; 0006 ; // task control block 0006 ; extern struct task_block { 0006 ; void (*address)(); // Address of the task 0006 ; unsigned char id; // ID of task 0006 ; char name[9]; // Name 0006 ; enum task_state state; // State 0006 ; unsigned char priority; // Priority 0006 ; unsigned long int period_tick; // for determining if deadline is up 0006 ; unsigned int interrupt_msg_box; // flags for pending interrupts 0006 ; enum message_box message; // misc flags 0006 ; unsigned char message_data[2]; // data for misc_msg_box flags 0006 ; unsigned char *heap_ptr; // heap addr while not current task 0006 ; unsigned int heap_size; // heap size 0006 ; unsigned char *frame_ptr; // CCR pointer 0006 ; }; 0006 ; 0006 ; 0006 ; // resource control block 0006 ; extern struct resource_block { 0006 ; unsigned char id; // ID of resource 0006 ; char name[5]; // Name of resource 0006 ; enum resource_state state; // State (busy, free...) 0006 ; unsigned char owner; // Current resource owner 0006 ; signed char queue[3]; // Tasks waiting on resource 0006 ; unsigned char queue_ptr; // Next free spot in queue 0006 ; }; 0006 ; 0006 ; 0006 ; extern struct task_block *task[NUMTASKS]; 0006 ; extern struct resource_block resource[NUMRESOURCES]; 0006 ; 0006 ; 0006 ; extern char error_msg[9][25]; 0006 ; extern char error_src[5][18]; 0006 ; 0006 ; 0006 ; extern char kdb_trace; 0006 ; 0006 ; 0006 ; 0006 ; 0006 ; 0006 ; main() { 0006 ; 0006 ; // LOCAL VARIABLES 0006 ; int result, id; 0006 ; unsigned int i, addr, temp_heap_size; 0006 ; unsigned char *temp_heap_ptr, temp, priority_check, cop_cycle; 0006 ; unsigned int deadline; 0006 ; 0006 ; extern int _bss_end, _textmode; 0006 ; 0006 ; _textmode = 1; // maps '\n' to "CR/LF" for Windows terminals 0006 CC0001 ldd #1 0009 7C0000 std __textmode 000C ; current = 0; // start the shell first 000C CC0000 ldd #0 000F 7C0000 std _current 0012 ; cop_cycle = 0; // fresh watchdog 0012 6910 clr -16,x 0014 ; 0014 ; 0014 ; // initialize the task block 0014 ; for (i=0; i= 0) { 00A9 CC0000 ldd #0 00AC 6C82 std 2,sp 00AE CC0000 ldd #_sysInit 00B1 6C80 std 0,sp 00B3 CC074D ldd #L21 00B6 160000 jsr _create_task 00B9 6CE1E0 std -32,x 00BC 6CE1EB std -21,x 00BF ECE1E0 ldd -32,x 00C2 2D1F blt L19 00C4 ; task_ptr[id] = sysInit; 00C4 ECE1EB ldd -21,x 00C7 59 lsld 00C8 C30000 addd #_task_ptr 00CB B7C6 xgdy 00CD CC0000 ldd #_sysInit 00D0 6C40 std 0,y 00D2 ; task[id]->state = PENDING; 00D2 ECE1EB ldd -21,x 00D5 59 lsld 00D6 C30000 addd #_task 00D9 B7C6 xgdy 00DB ED40 ldy 0,y 00DD C601 ldab #1 00DF 6B4C stab 12,y 00E1 ; } 00E1 2010 bra L20 00E3 L19: 00E3 ; else { 00E3 ; if (KERNEL_ERROR_MSGS) 00E3 ; printf("%s %s\n", error_src[0], error_msg[8]); 00E3 CC00C8 ldd #_error_msg+200 00E6 6C82 std 2,sp 00E8 CC0000 ldd #_error_src 00EB 6C80 std 0,sp 00ED CC0746 ldd #L24 00F0 160000 jsr _printf 00F3 L22: 00F3 ; } 00F3 L20: 00F3 ; #ifdef KDB_TRACE_LEVEL_1 00F3 ; if (kdb_trace) puts("kDB1-1"); 00F3 F70000 tst _kdb_trace 00F6 2706 beq L26 00F8 CC073F ldd #L28 00FB 160000 jsr _puts 00FE L26: 00FE ; #endif 00FE ; 00FE ; 00FE ; 00FE ; // create the shell 00FE ; if ((id = create_task("shell", &shell, 1)) >= 0) 00FE CC0001 ldd #1 0101 6C82 std 2,sp 0103 CC0000 ldd #_shell 0106 6C80 std 0,sp 0108 CC0739 ldd #L31 010B 160000 jsr _create_task 010E 6CE1DE std -34,x 0111 6CE1EB std -21,x 0114 ECE1DE ldd -34,x 0117 2D0E blt L29 0119 ; set_task_state(id, PENDING); 0119 CC0001 ldd #1 011C 6C80 std 0,sp 011E ECE1EB ldd -21,x 0121 87 clra 0122 160000 jsr _set_task_state 0125 2010 bra L30 0127 L29: 0127 ; else { 0127 ; if (KERNEL_ERROR_MSGS) 0127 ; printf("%s %s\n", error_src[0], error_msg[8]); 0127 CC00C8 ldd #_error_msg+200 012A 6C82 std 2,sp 012C CC0000 ldd #_error_src 012F 6C80 std 0,sp 0131 CC0746 ldd #L24 0134 160000 jsr _printf 0137 L32: 0137 ; } 0137 L30: 0137 ; #ifdef KDB_TRACE_LEVEL_1 0137 ; if (kdb_trace) puts("kDB1-2"); 0137 F70000 tst _kdb_trace 013A 2706 beq L35 013C CC0732 ldd #L37 013F 160000 jsr _puts 0142 L35: 0142 ; #endif 0142 ; 0142 ; 0142 ; 0142 ; // create sysTime 0142 ; if ((id = create_task("sysTime", &sysTime, 5)) >= 0) 0142 CC0005 ldd #5 0145 6C82 std 2,sp 0147 CC0000 ldd #_sysTime 014A 6C80 std 0,sp 014C CC072A ldd #L40 014F 160000 jsr _create_task 0152 6CE1DC std -36,x 0155 6CE1EB std -21,x 0158 ECE1DC ldd -36,x 015B 2D0E blt L38 015D ; set_task_state(id, STOPPED); 015D CC0004 ldd #4 0160 6C80 std 0,sp 0162 ECE1EB ldd -21,x 0165 87 clra 0166 160000 jsr _set_task_state 0169 2010 bra L39 016B L38: 016B ; else { 016B ; if (KERNEL_ERROR_MSGS) 016B ; printf("%s %s\n", error_src[0], error_msg[8]); 016B CC00C8 ldd #_error_msg+200 016E 6C82 std 2,sp 0170 CC0000 ldd #_error_src 0173 6C80 std 0,sp 0175 CC0746 ldd #L24 0178 160000 jsr _printf 017B L41: 017B ; } 017B L39: 017B ; #ifdef KDB_TRACE_LEVEL_1 017B ; if (kdb_trace) puts("kDB1-3"); 017B F70000 tst _kdb_trace 017E 2706 beq L44 0180 CC0723 ldd #L46 0183 160000 jsr _puts 0186 L44: 0186 ; #endif 0186 ; 0186 ; 0186 ; 0186 ; // treat the COP and system tick 0186 ; COP_PET(0x55); 0186 C655 ldab #85 0188 7B0017 stab 0x17 018B ; COP_PET(0xAA); 018B C6AA ldab #170 018D 7B0017 stab 0x17 0190 ; system_tick = 0; 0190 CD071F ldy #L47 0193 1802401C movw 0,y,-4,x 0197 1802421E movw 2,y,-2,x 019B CD0000 ldy #_system_tick 019E 18021C40 movw -4,x,0,y 01A2 18021E42 movw -2,x,2,y 01A6 ; 01A6 ; 01A6 ; // print the opening comments 01A6 ; puts("rlpOS v0.5.2\n\n"); 01A6 CC0710 ldd #L48 01A9 160000 jsr _puts 01AC 18200396 lbra L50 01B0 L49: 01B0 ; 01B0 ; 01B0 ; 01B0 ; 01B0 ; // MULTITASKING KERNEL: Priority Preemptive, Real Time, multitasking 01B0 ; // KDB_TRACE Section 2 01B0 ; while(1) { 01B0 ; 01B0 ; /* REENTRY POINT after either 01B0 ; 1) task finishes, or 01B0 ; 2) RTI 01B0 ; */ 01B0 ; #ifdef KDB_TRACE_LEVEL_1 01B0 ; if (kdb_trace) puts("kDB2.1"); 01B0 F70000 tst _kdb_trace 01B3 2706 beq L52 01B5 CC0709 ldd #L54 01B8 160000 jsr _puts 01BB L52: 01BB ; #endif 01BB ; 01BB ; 01BB ; /* No interrupts allowed inside of main(). Only allowed 01BB ; inside of non-critical sections of tasks */ 01BB ; INTR_OFF(); 01BB 1410 sei 01BD 01BD ; 01BD ; 01BD ; // PET THE DOG: cop watchdog reset timer (pet freq = 2x COP freq) 01BD ; if (cop_cycle == 4) { 01BD E610 ldab -16,x 01BF C104 cmpb #4 01C1 260E bne L55 01C3 ; COP_PET(0x55); 01C3 C655 ldab #85 01C5 7B0017 stab 0x17 01C8 ; COP_PET(0xAA); 01C8 C6AA ldab #170 01CA 7B0017 stab 0x17 01CD ; cop_cycle = 0; 01CD 6910 clr -16,x 01CF ; } 01CF 2008 bra L56 01D1 L55: 01D1 ; else 01D1 ; cop_cycle++; 01D1 E610 ldab -16,x 01D3 87 clra 01D4 C30001 addd #1 01D7 6B10 stab -16,x 01D9 L56: 01D9 ; #ifdef KDB_TRACE_LEVEL_1 01D9 ; if (kdb_trace) puts("kDB2.2-1"); 01D9 F70000 tst _kdb_trace 01DC 2706 beq L57 01DE CC0700 ldd #L59 01E1 160000 jsr _puts 01E4 L57: 01E4 CC0000 ldd #0 01E7 6C16 std -10,x 01E9 205E bra L63 01EB L60: 01EB ; #endif 01EB ; 01EB ; 01EB ; 01EB ; 01EB ; // CHANGE STATES ACCORDING TO MESSAGES 01EB ; // 'waiting' needs to have highest precedence here 01EB ; for (i=0; imessage && STATE_FLAG) { 01EB EC16 ldd -10,x 01ED 59 lsld 01EE C30000 addd #_task 01F1 B7C6 xgdy 01F3 ED40 ldy 0,y 01F5 E7E814 tst 20,y 01F8 273D beq L64 01FA ; // set task state to what the message says 01FA ; task[i]->state = task[i]->message_data[STATE_BOX]; 01FA EC16 ldd -10,x 01FC 59 lsld 01FD C30000 addd #_task 0200 B7C6 xgdy 0202 ED40 ldy 0,y 0204 6DE1E5 sty -27,x 0207 EDE1E5 ldy -27,x 020A E6E815 ldab 21,y 020D EDE1E5 ldy -27,x 0210 6B4C stab 12,y 0212 ; // clear the STATE_FLAG 0212 ; task[i]->message &= ~(STATE_FLAG); 0212 EC16 ldd -10,x 0214 59 lsld 0215 C30000 addd #_task 0218 B7C6 xgdy 021A EC40 ldd 0,y 021C C30014 addd #20 021F 6CE1E3 std -29,x 0222 B746 tfr d,y 0224 35 pshy ; spill 0225 EDE1E3 ldy -29,x 0228 31 puly ; reload 0229 0D4001 bclr 0,y,#0x1 022C ; #ifdef KDB_TRACE_LEVEL_2 022C ; if (kdb_trace) puts("kDB2.3-2a"); 022C F70000 tst _kdb_trace 022F 2706 beq L66 0231 CC06F6 ldd #L68 0234 160000 jsr _puts 0237 L66: 0237 ; #endif 0237 ; } 0237 L64: 0237 ; #ifdef KDB_TRACE_LEVEL_2 0237 ; if (kdb_trace) puts("kDB2.3-2b"); 0237 F70000 tst _kdb_trace 023A 2706 beq L69 023C CC06EC ldd #L71 023F 160000 jsr _puts 0242 L69: 0242 L61: 0242 EC16 ldd -10,x 0244 C30001 addd #1 0247 6C16 std -10,x 0249 L63: 0249 EC16 ldd -10,x 024B 8C0008 cpd #8 024E 259B blo L60 0250 ; #endif 0250 ; } 0250 ; #ifdef KDB_TRACE_LEVEL_1 0250 ; if (kdb_trace) puts("kDB2.3-1"); 0250 F70000 tst _kdb_trace 0253 2706 beq L72 0255 CC06E3 ldd #L74 0258 160000 jsr _puts 025B L72: 025B CC0000 ldd #0 025E 6C16 std -10,x 0260 18200075 lbra L78 0264 L75: 0264 ; #endif 0264 ; 0264 ; 0264 ; 0264 ; // RT PRIORITY BLOCK: 0264 ; // set the current task id based on priority and deadline 0264 ; 0264 ; // determine if the deadline is up for idle tasks 0264 ; /* deadline, is equal to period plus an initial time (t0) reference 0264 ; (t0 = system_tick). Period = priority + 1. 0264 ; Changing the state from idle to PENDING occurs here. */ 0264 ; for (i=0; istate == IDLE) { 0264 EC16 ldd -10,x 0266 59 lsld 0267 C30000 addd #_task 026A B7C6 xgdy 026C ED40 ldy 0,y 026E E74C tst 12,y 0270 2660 bne L79 0272 ; deadline = task[i]->period_tick + (task[i]->priority + 1); 0272 EC16 ldd -10,x 0274 59 lsld 0275 C30000 addd #_task 0278 B7C6 xgdy 027A ED40 ldy 0,y 027C 6DE1E5 sty -27,x 027F EDE1E5 ldy -27,x 0282 E64D ldab 13,y 0284 87 clra 0285 C30001 addd #1 0288 160000 jsr __d2lreg2 028B EDE1E5 ldy -27,x 028E 194E leay 14,y 0290 1802401C movw 0,y,-4,x 0294 1802421E movw 2,y,-2,x 0298 160000 jsr __ladd 029B 160000 jsr __lreg2d 029E 6C14 std -12,x 02A0 ; if (system_tick >= deadline) { 02A0 CD0000 ldy #_system_tick 02A3 1802401C movw 0,y,-4,x 02A7 1802421E movw 2,y,-2,x 02AB EC14 ldd -12,x 02AD 6C1A std -6,x 02AF 1800180000 movw #0,-8,x 02B4 160000 jsr __lcmp 02B7 2519 blo L81 02B9 ; task[i]->state = PENDING; // change state at deadline 02B9 EC16 ldd -10,x 02BB 59 lsld 02BC C30000 addd #_task 02BF B7C6 xgdy 02C1 ED40 ldy 0,y 02C3 C601 ldab #1 02C5 6B4C stab 12,y 02C7 ; #ifdef KDB_TRACE_LEVEL_2 02C7 ; if (kdb_trace) puts("kDB2.4-2"); 02C7 F70000 tst _kdb_trace 02CA 2706 beq L83 02CC CC06DA ldd #L85 02CF 160000 jsr _puts 02D2 L83: 02D2 ; #endif 02D2 ; } 02D2 L81: 02D2 ; } 02D2 L79: 02D2 L76: 02D2 EC16 ldd -10,x 02D4 C30001 addd #1 02D7 6C16 std -10,x 02D9 L78: 02D9 EC16 ldd -10,x 02DB 8C0008 cpd #8 02DE 1825FF82 lblo L75 02E2 ; // if (task[i]->message) {} 02E2 ; } 02E2 ; #ifdef KDB_TRACE_LEVEL_1 02E2 ; if (kdb_trace) puts("kDB2.4-1"); 02E2 F70000 tst _kdb_trace 02E5 2706 beq L86 02E7 CC06D1 ldd #L88 02EA 160000 jsr _puts 02ED L86: 02ED ; #endif 02ED ; 02ED ; 02ED ; // set current = to highest priority pending/running task. 02ED ; priority_check = 255; // lowest possible 02ED C6FF ldab #255 02EF 6B13 stab -13,x 02F1 CC0000 ldd #0 02F4 6C16 std -10,x 02F6 205E bra L92 02F8 L89: 02F8 ; 02F8 ; for (i=0; istate == PENDING) || (task[i]->state == RUNNING)) { 0321 ; if (task[i]->priority <= priority_check) { 0321 EC16 ldd -10,x 0323 59 lsld 0324 C30000 addd #_task 0327 B7C6 xgdy 0329 ED40 ldy 0,y 032B E64D ldab 13,y 032D E113 cmpb -13,x 032F 221E bhi L98 0331 ; current = i; 0331 1805160000 movw -10,x,_current 0336 ; priority_check = task[i]->priority; 0336 EC16 ldd -10,x 0338 59 lsld 0339 C30000 addd #_task 033C B7C6 xgdy 033E ED40 ldy 0,y 0340 E64D ldab 13,y 0342 6B13 stab -13,x 0344 ; #ifdef KDB_TRACE_LEVEL_2 0344 ; if (kdb_trace) puts("kDB2.5-2"); 0344 F70000 tst _kdb_trace 0347 2706 beq L100 0349 CC06C8 ldd #L102 034C 160000 jsr _puts 034F L100: 034F ; #endif 034F ; } 034F L98: 034F ; } 034F L95: 034F ; } 034F L93: 034F L90: 034F EC16 ldd -10,x 0351 C30001 addd #1 0354 6C16 std -10,x 0356 L92: 0356 EC16 ldd -10,x 0358 8C0008 cpd #8 035B 259B blo L89 035D ; } 035D ; #ifdef KDB_TRACE_LEVEL_1 035D ; if (kdb_trace) puts("kDB2.5-1"); 035D F70000 tst _kdb_trace 0360 2706 beq L103 0362 CC06BF ldd #L105 0365 160000 jsr _puts 0368 L103: 0368 ; #endif 0368 ; 0368 ; 0368 ; 0368 ; // DISPATCH, or otherwise deal with the current task 0368 ; // KDB_TRACE Section 3 0368 ; 0368 ; #ifdef KDB_TRACE_LEVEL_2 0368 ; if (kdb_trace) { 0368 F70000 tst _kdb_trace 036B 2736 beq L106 036D ; printf("task[%d]->state = %d\n", current, task[current]->state); 036D FC0000 ldd _current 0370 59 lsld 0371 C30000 addd #_task 0374 B7C6 xgdy 0376 ED40 ldy 0,y 0378 E64C ldab 12,y 037A 87 clra 037B 6C82 std 2,sp 037D 1801800000 movw _current,0,sp 0382 CC06A9 ldd #L108 0385 160000 jsr _printf 0388 ; printf("task[%d]->prior = %d\n", current, task[current]->priority); 0388 FC0000 ldd _current 038B 59 lsld 038C C30000 addd #_task 038F B7C6 xgdy 0391 ED40 ldy 0,y 0393 E64D ldab 13,y 0395 87 clra 0396 6C82 std 2,sp 0398 1801800000 movw _current,0,sp 039D CC0693 ldd #L109 03A0 160000 jsr _printf 03A3 ; } 03A3 L106: 03A3 FC0000 ldd _current 03A6 59 lsld 03A7 C30000 addd #_task 03AA B7C6 xgdy 03AC ED40 ldy 0,y 03AE E64C ldab 12,y 03B0 87 clra 03B1 6CE1E5 std -27,x 03B4 272A beq L113 03B6 ECE1E5 ldd -27,x 03B9 8C0001 cpd #1 03BC 2733 beq L117 03BE ECE1E5 ldd -27,x 03C1 8C0002 cpd #2 03C4 182700C6 lbeq L128 03C8 ECE1E5 ldd -27,x 03CB 8C0003 cpd #3 03CE 1827014E lbeq L138 03D2 ECE1E5 ldd -27,x 03D5 8C0004 cpd #4 03D8 18270151 lbeq L142 03DC 1820015A lbra L110 03E0 X0: 03E0 ; #endif 03E0 ; 03E0 ; switch (task[current]->state) { 03E0 L113: 03E0 ; case IDLE: // skip task 03E0 ; #ifdef KDB_TRACE_LEVEL_1 03E0 ; if (kdb_trace) puts("kDB3.1-1"); 03E0 F70000 tst _kdb_trace 03E3 1827015F lbeq L111 03E7 CC068A ldd #L116 03EA 160000 jsr _puts 03ED ; #endif 03ED ; break; 03ED 18200155 lbra L111 03F1 L117: 03F1 ; case PENDING: // ready and waiting to run 03F1 ; task[current]->state = RUNNING; 03F1 FC0000 ldd _current 03F4 59 lsld 03F5 C30000 addd #_task 03F8 B7C6 xgdy 03FA ED40 ldy 0,y 03FC C602 ldab #2 03FE 6B4C stab 12,y 0400 ; task[current]->period_tick = system_tick; 0400 FC0000 ldd _current 0403 59 lsld 0404 C30000 addd #_task 0407 B7C6 xgdy 0409 ED40 ldy 0,y 040B 194E leay 14,y 040D 35 pshy ; spill 040E CD0000 ldy #_system_tick 0411 1802401C movw 0,y,-4,x 0415 1802421E movw 2,y,-2,x 0419 31 puly ; reload 041A 18021C40 movw -4,x,0,y 041E 18021E42 movw -2,x,2,y 0422 ; #ifdef KDB_TRACE_LEVEL_1 0422 ; if (kdb_trace) puts("kDB3.2-1"); 0422 F70000 tst _kdb_trace 0425 2706 beq L118 0427 CC0681 ldd #L120 042A 160000 jsr _puts 042D L118: 042D ; #endif 042D ; #ifdef KDB_TRACE_LEVEL_2 042D ; if (kdb_trace) { 042D F70000 tst _kdb_trace 0430 2716 beq L121 0432 ; //puts("kDB3.2-2"); 0432 ; putchar('S'); 0432 CC0053 ldd #83 0435 160000 jsr _putchar 0438 ; putchar(current+48); 0438 FC0000 ldd _current 043B C30030 addd #48 043E 87 clra 043F 160000 jsr _putchar 0442 ; putchar('\n'); 0442 CC000A ldd #10 0445 160000 jsr _putchar 0448 ; } 0448 L121: 0448 ; #endif 0448 ; (*task_ptr[current])(); // start the task 0448 FC0000 ldd _current 044B 59 lsld 044C C30000 addd #_task_ptr 044F B7C6 xgdy 0451 ED40 ldy 0,y 0453 1540 jsr 0,y 0455 ; task[current]->state = IDLE; // task finished 0455 FC0000 ldd _current 0458 59 lsld 0459 C30000 addd #_task 045C B7C6 xgdy 045E ED40 ldy 0,y 0460 694C clr 12,y 0462 ; #ifdef KDB_TRACE_LEVEL_1 0462 ; if (kdb_trace) puts("kDB3.3-1"); 0462 F70000 tst _kdb_trace 0465 2706 beq L123 0467 CC0678 ldd #L125 046A 160000 jsr _puts 046D L123: 046D ; #endif 046D ; #ifdef KDB_TRACE_LEVEL_2 046D ; if (kdb_trace) { 046D F70000 tst _kdb_trace 0470 182700D2 lbeq L111 0474 ; //puts("kDB3.3-2"); 0474 ; putchar('S'); 0474 CC0053 ldd #83 0477 160000 jsr _putchar 047A ; putchar(current+48); 047A FC0000 ldd _current 047D C30030 addd #48 0480 87 clra 0481 160000 jsr _putchar 0484 ; putchar('\n'); 0484 CC000A ldd #10 0487 160000 jsr _putchar 048A ; } 048A ; #endif 048A ; break; 048A 182000B8 lbra L111 048E L128: 048E ; case RUNNING: // interrupted. continue running. 048E ; // restore the task heap to the stack 048E ; #ifdef KDB_TRACE_LEVEL_1 048E ; if (kdb_trace) puts("kDB3.4-1"); 048E F70000 tst _kdb_trace 0491 2706 beq L129 0493 CC066F ldd #L131 0496 160000 jsr _puts 0499 L129: 0499 ; #endif 0499 ; #ifdef KDB_TRACE_LEVEL_2 0499 ; if (kdb_trace) { 0499 F70000 tst _kdb_trace 049C 2716 beq L132 049E ; //puts("kDB3.4-2"); 049E ; putchar('R'); 049E CC0052 ldd #82 04A1 160000 jsr _putchar 04A4 ; putchar(current+48); 04A4 FC0000 ldd _current 04A7 C30030 addd #48 04AA 87 clra 04AB 160000 jsr _putchar 04AE ; putchar('\n'); 04AE CC000A ldd #10 04B1 160000 jsr _putchar 04B4 ; } 04B4 L132: 04B4 ; #endif 04B4 ; temp_heap_size = task[current]->heap_size; 04B4 FC0000 ldd _current 04B7 59 lsld 04B8 C30000 addd #_task 04BB B7C6 xgdy 04BD ED40 ldy 0,y 04BF EDE819 ldy 25,y 04C2 6D11 sty -15,x 04C4 ; temp_heap_ptr = task[current]->heap_ptr; 04C4 FC0000 ldd _current 04C7 59 lsld 04C8 C30000 addd #_task 04CB B7C6 xgdy 04CD ED40 ldy 0,y 04CF EDE817 ldy 23,y 04D2 6DE1ED sty -19,x 04D5 CC0000 ldd #0 04D8 6C16 std -10,x 04DA 2027 bra L137 04DC L134: 04DC EC16 ldd -10,x 04DE E3E1ED addd -19,x 04E1 B7C6 xgdy 04E3 E640 ldab 0,y 04E5 6BE1EF stab -17,x 04E8 FC0000 ldd _main_frame_ptr 04EB A311 subd -15,x 04ED 6CE1DA std -38,x 04F0 EC16 ldd -10,x 04F2 E3E1DA addd -38,x 04F5 B7C6 xgdy 04F7 E6E1EF ldab -17,x 04FA 6B40 stab 0,y 04FC L135: 04FC EC16 ldd -10,x 04FE C30001 addd #1 0501 6C16 std -10,x 0503 L137: 0503 ; for (i=0; iframe_ptr; 0509 FC0000 ldd _current 050C 59 lsld 050D C30000 addd #_task 0510 B7C6 xgdy 0512 ED40 ldy 0,y 0514 EDE81B ldy 27,y 0517 7D0004 sty _temp_task_frame_ptr 051A ; asm("LDS _temp_task_frame_ptr"); 051A FF0004 LDS _temp_task_frame_ptr 051D 051D ; asm("RTI"); 051D 0B RTI 051E 051E ; break; 051E 2026 bra L111 0520 L138: 0520 ; case WAITING: // waiting on a resource 0520 ; #ifdef KDB_TRACE_LEVEL_1 0520 ; if (kdb_trace) puts("kDB3.5-1"); 0520 F70000 tst _kdb_trace 0523 2721 beq L111 0525 CC0666 ldd #L141 0528 160000 jsr _puts 052B ; #endif 052B ; break; 052B 2019 bra L111 052D L142: 052D ; case STOPPED: // done running until later 052D ; #ifdef KDB_TRACE_LEVEL_1 052D ; if (kdb_trace) puts("kDB3.6-1"); 052D F70000 tst _kdb_trace 0530 2714 beq L111 0532 CC065D ldd #L145 0535 160000 jsr _puts 0538 ; #endif 0538 ; break; 0538 200C bra L111 053A L110: 053A ; default: // shouldn't happen, but, error if so. 053A ; puts("KERNEL: task state error\n"); 053A CC0643 ldd #L146 053D 160000 jsr _puts 0540 ; exit(1); 0540 CC0001 ldd #1 0543 160000 jsr _exit 0546 ; } // end switch 0546 L111: 0546 L50: 0546 1820FC66 lbra L49 054A X1: 054A ; 054A ; } // end while(1) 054A ; 054A ; return 0; 054A CC0000 ldd #0 054D L3: 054D B757 tfr x,s 054F 30 pulx 0550 .dbline 0 ; func end 0550 3D rts 0551 ; lreg1 -> -4,x 0551 ; lreg2 -> -8,x 0551 ; ?temp -> -16,x 0551 ; local_thp -> -14,x 0551 ; frame_size -> -12,x 0551 ; i -> -10,x 0551 _RTI_handler:: 0551 34 pshx 0552 B775 tfr s,x 0554 1BF1EC leas -20,sp 0557 ; 0557 ; } // end main() 0557 ; 0557 ; 0557 ; 0557 ; #pragma interrupt_handler RTI_handler() 0557 ; 0557 ; void RTI_handler(void) { 0557 ; 0557 ; size_t frame_size; 0557 ; unsigned int i; 0557 ; unsigned char *local_thp; 0557 ; 0557 ; 0557 ; //ACKNOWLEDGE THE INTERRUPT 0557 ; INTR_OFF(); // redundant. automatically done by the processor 0557 1410 sei 0559 0559 ; RTIFLG = 0x0080; // acknowledge/clear the interrupt 0559 C680 ldab #128 055B 7B0015 stab 0x15 055E ; 055E ; 055E ; #ifdef KBD_TRACE_LEVEL_1 055E ; if (kbd_trace) putchar('.'); 055E ; #endif 055E ; 055E ; 055E ; // SET THE FRAME POINTER for the interupted task. 055E ; // should point to the CCR entry on the stack. 055E ; asm("TFR x,d"); // start of RTI stack 055E B754 TFR x,d 0560 0560 ; asm("ADDD #2"); // adjust to CCR stack entry 0560 C30002 ADDD #2 0563 0563 ; asm("STD _temp_task_frame_ptr"); // put into task_frame_ptr 0563 7C0004 STD _temp_task_frame_ptr 0566 0566 ; task[current]->frame_ptr = temp_task_frame_ptr; 0566 FC0000 ldd _current 0569 59 lsld 056A C30000 addd #_task 056D B7C6 xgdy 056F ED40 ldy 0,y 0571 FC0004 ldd _temp_task_frame_ptr 0574 6CE81B std 27,y 0577 ; 0577 ; 0577 ; 0577 ; //PLACE CURRENT TASK CONTEXT ONTO THE HEAP 0577 ; // determine size of heap segment needed 0577 ; frame_size = main_frame_ptr - temp_task_frame_ptr; // always positive 0577 FC0000 ldd _main_frame_ptr 057A B30004 subd _temp_task_frame_ptr 057D 6C14 std -12,x 057F ; task[current]->heap_size = (int)frame_size; 057F FC0000 ldd _current 0582 59 lsld 0583 C30000 addd #_task 0586 B7C6 xgdy 0588 ED40 ldy 0,y 058A EC14 ldd -12,x 058C 6CE819 std 25,y 058F ; 058F ; // reallocate heap memory 058F ; task[current]->heap_ptr = realloc(task[current]->heap_ptr, frame_size); 058F 18021480 movw -12,x,0,sp 0593 FC0000 ldd _current 0596 59 lsld 0597 C30000 addd #_task 059A B7C6 xgdy 059C EC40 ldd 0,y 059E C30017 addd #23 05A1 6C10 std -16,x 05A3 ECE3FFF0 ldd [-16,x] 05A7 160000 jsr _realloc 05AA 6CE1EE std -18,x 05AD ED10 ldy -16,x 05AF ECE1EE ldd -18,x 05B2 6C40 std 0,y 05B4 ; local_thp = task[current]->heap_ptr; 05B4 FC0000 ldd _current 05B7 59 lsld 05B8 C30000 addd #_task 05BB B7C6 xgdy 05BD ED40 ldy 0,y 05BF EDE817 ldy 23,y 05C2 6D12 sty -14,x 05C4 ; 05C4 ; if (local_thp == NULL) { 05C4 EC12 ldd -14,x 05C6 260C bne L148 05C8 ; #ifdef KERNEL_ERROR_MSGS 05C8 ; puts("out of heap space!"); 05C8 CC0630 ldd #L150 05CB 160000 jsr _puts 05CE ; #endif 05CE ; exit(0); 05CE CC0000 ldd #0 05D1 160000 jsr _exit 05D4 ; } 05D4 L148: 05D4 CC0000 ldd #0 05D7 6C16 std -10,x 05D9 201A bra L154 05DB L151: 05DB EC16 ldd -10,x 05DD F30004 addd _temp_task_frame_ptr 05E0 B7C6 xgdy 05E2 E640 ldab 0,y 05E4 3B pshd ; spill 05E5 EC16 ldd -10,x 05E7 E312 addd -14,x 05E9 B7C6 xgdy 05EB 3A puld ; reload 05EC 6B40 stab 0,y 05EE L152: 05EE EC16 ldd -10,x 05F0 C30001 addd #1 05F3 6C16 std -10,x 05F5 L154: 05F5 ; 05F5 ; // transfer task frame to the heap one byte at a time. 05F5 ; // assumes the heap grows from low to high addr. 05F5 ; for(i=0; i