.module kernel.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 0006 _kdb_trace:: 0006 .blkb 2 .area idata 0006 0001 .word 1 .area data 0008 _kdb_trace_cycle:: 0008 .blkb 2 .area idata 0008 0000 .word 0 .area data .area text 0000 _error_msg:: 0000 756E696D706C696D656E746564206675 .byte 'u,'n,'i,'m,'p,'l,'i,'m,'e,'n,'t,'e,'d,32,'f,'u 0010 6E6374696F6E00 .byte 'n,'c,'t,'i,'o,'n,0 0017 0000 .byte 0,0 0019 73796E746178206572726F7200 .byte 's,'y,'n,'t,'a,'x,32,'e,'r,'r,'o,'r,0 0026 00000000000000000000 .word 0,0,0,0,0 0030 0000 .byte 0,0 0032 696C6C6567616C207461736B20494400 .byte 'i,'l,'l,'e,'g,'a,'l,32,'t,'a,'s,'k,32,'I,'D,0 0042 000000000000000000 .byte 0,0,0,0,0,0,0,0,0 004B 696C6C6567616C207461736B20737461 .byte 'i,'l,'l,'e,'g,'a,'l,32,'t,'a,'s,'k,32,'s,'t,'a 005B 746500 .byte 't,'e,0 005E 000000000000 .byte 0,0,0,0,0,0 0064 696C6C6567616C207461736B20707269 .byte 'i,'l,'l,'e,'g,'a,'l,32,'t,'a,'s,'k,32,'p,'r,'i 0074 6F7269747900 .byte 'o,'r,'i,'t,'y,0 007A 000000 .byte 0,0,0 007D 6F7574206F66206D656D6F727900 .byte 'o,'u,'t,32,'o,'f,32,'m,'e,'m,'o,'r,'y,0 008B 00000000000000000000 .word 0,0,0,0,0 0095 00 .byte 0 0096 696C6C6567616C207265736F75726365 .byte 'i,'l,'l,'e,'g,'a,'l,32,'r,'e,'s,'o,'u,'r,'c,'e 00A6 20494400 .byte 32,'I,'D,0 00AA 0000000000 .byte 0,0,0,0,0 00AF 696C6C6567616C207265736F75726365 .byte 'i,'l,'l,'e,'g,'a,'l,32,'r,'e,'s,'o,'u,'r,'c,'e 00BF 20737461746500 .byte 32,'s,'t,'a,'t,'e,0 00C6 0000 .byte 0,0 00C8 63616E6E6F7420637265617465207461 .byte 'c,'a,'n,'n,'o,'t,32,'c,'r,'e,'a,'t,'e,32,'t,'a 00D8 736B00 .byte 's,'k,0 00DB 000000000000 .byte 0,0,0,0,0,0 00E1 _error_src:: 00E1 6B65726E656C206572726F723A00 .byte 'k,'e,'r,'n,'e,'l,32,'e,'r,'r,'o,'r,58,0 00EF 00000000 .byte 0,0,0,0 00F3 6B65726E656C2E63206572726F723A00 .byte 'k,'e,'r,'n,'e,'l,46,'c,32,'e,'r,'r,'o,'r,58,0 0103 0000 .byte 0,0 0105 6B65726E656C20525449206572726F72 .byte 'k,'e,'r,'n,'e,'l,32,'R,'T,'I,32,'e,'r,'r,'o,'r 0115 3A00 .byte 58,0 0117 7368656C6C206572726F723A00 .byte 's,'h,'e,'l,'l,32,'e,'r,'r,'o,'r,58,0 0124 0000000000 .byte 0,0,0,0,0 0129 73656D6C69622E63206572726F723A00 .byte 's,'e,'m,'l,'i,'b,46,'c,32,'e,'r,'r,'o,'r,58,0 0139 0000 .byte 0,0 013B ; lreg1 -> -4,x 013B ; lreg2 -> -8,x 013B ; ?temp -> -19,x 013B ; ?temp -> -19,x 013B ; ?temp -> -19,x 013B ; ?temp -> -21,x 013B ; ?temp -> -19,x 013B ; id -> -17,x 013B ; result -> -15,x 013B ; priority_check -> -13,x 013B ; deadline -> -12,x 013B ; i -> -10,x 013B _main:: 013B 34 pshx 013C B775 tfr s,x 013E 1BF1E2 leas -30,sp 0141 ; /* RLPOS: RLPotter Operating System 0141 ; 0141 ; Version 0.7 for the 68HC12D60A microcontroller 0141 ; by Ryan Potter 0141 ; ryan@rlpotter.com 0141 ; 0141 ; 0141 ; v0.7 April 25, 2003: 11174 bytes: 0141 ; - combined kernel.c & semlib.c with rlpos.c to make one big kernel.c 0141 ; - changed context switch mechanism to give each task a dedicated 0141 ; stack, making the kernel context switches >400% faster. 0141 ; - added a basic timer task that will eventually keep system time/date. 0141 ; 0141 ; v0.6 April 24, 2003: 11042 bytes 0141 ; - made the task block and the task control block dynamic, so that 0141 ; now tasks can create tasks, and can also start/stop them 0141 ; - implemented the sysInit() task for kicking off a user system 0141 ; - implemented a kernel debug command for tracing code execution 0141 ; - implemented small msg box system in kernel for tasks 0141 ; - implemented COP watchdog reset timer 0141 ; - added system resources to semlib 0141 ; - added skeleton ISR_handler() code for the other interrupts 0141 ; - implemented _HC12Setup.c to initialize/harden the system 0141 ; 0141 ; v0.5 April 16, 2003: 0141 ; - added priority preemption 0141 ; - finished kernel task state switcher 0141 ; - it is now officially a legitimate 0141 ; rate monotonic 0141 ; priority preemptive 0141 ; multitasking 0141 ; Real Time Operating System :) 0141 ; - made kernel.c and semlib.c consistent with the 0141 ; rest of the kernel 0141 ; - included the early framework for a msg box system 0141 ; 0141 ; v0.4 April 13, 2003: 8096 bytes 0141 ; - gerneralized the shell command-line input parser: 0141 ; cmd (up to 32 chars) 0141 ; - added kernel and shell functions 0141 ; 0141 ; v0.3 April 12, 2003: 6155 bytes 0141 ; - added a beginning shell user interface. 0141 ; - added a resource control block and basic semaphore functions. 0141 ; - added basic kernel functions 0141 ; 0141 ; v0.2 April 9, 2003: 0141 ; - able to round-robin with RTI interrupt. 0141 ; - bonified/certified multitasking with 3 tasks. :) 0141 ; 0141 ; v0.1 April 3, 2003: 0141 ; - able to round-robin without interrupts. 0141 ; - not multitasking, really. 0141 ; 0141 ; v0.0 started April 1, 2003; 0 bytes 0141 ; - no idea where to start. 0141 ; - don't want to look at anyone else's work. ;0) 0141 ; 0141 ; 0141 ; 0141 ; 0141 ; Architecture/C assumptions: 0141 ; 1) 'D' register is the accumulator 0141 ; 2) 'X' register points to the top of the current stack 0141 ; 3) 'Y' register is for general use in indexed operations 0141 ; 4) the heap grows upward and mem segments allocated by malloc, 0141 ; realloc, and calloc are linear and contiguous. 0141 ; 5) the stack grows downwards, and there is no boundary checking. 0141 ; 0141 ; Potential problem areas: 0141 ; 1) 'running' section of the kernel get's compiled using extra 0141 ; push and pop instructions 0141 ; 2) run out of ram (global + stack + heap) 0141 ; 0141 ; */ 0141 ; 0141 ; 0141 ; 0141 ; #include <912d60.h> 0141 ; #include 0141 ; #include 0141 ; #include 0141 ; #include "kernel.h" 0141 ; 0141 ; 0141 ; 0141 ; // FUNCTION PROTOTYPES 0141 ; void RTI_handler(void); 0141 ; void sysInit(void); 0141 ; void shell(void); 0141 ; void sysTime(void); 0141 ; void (*task_ptr[MAXTASKS])(void); 0141 ; 0141 ; 0141 ; 0141 ; 0141 ; // GLOBAL VARIABLES 0141 ; unsigned char *main_frame_ptr = NULL; // bottom of main() frame 0141 ; unsigned char *main_frame_x_ptr = NULL; // top of main() frame (x-reg ptr) 0141 ; unsigned char *temp_task_frame_ptr = NULL; // temp CCR pointer for RTI 0141 ; 0141 ; 0141 ; unsigned int current; // current task id number 0141 ; unsigned long int system_tick; 0141 ; unsigned int cop_cycle; 0141 ; 0141 ; unsigned long int time_tick; 0141 ; unsigned long int delta_t; 0141 ; unsigned long int last_time_mark; 0141 ; 0141 ; 0141 ; // task control block 0141 ; typedef struct task_block { 0141 ; void (*address)(); // Address of the task 0141 ; unsigned char id; // ID of task 0141 ; char name[9]; // Name 0141 ; enum task_state state; // State 0141 ; unsigned char priority; // Priority 0141 ; unsigned long int period_tick; // for determining if deadline is up 0141 ; unsigned int interrupt_msg_box; // flags for pending interrupts 0141 ; enum message_box message; // misc flags 0141 ; unsigned char message_data[2]; // data for misc_msg_box flags 0141 ; unsigned int stack_size; // heap allocated for task stack 0141 ; unsigned char *top_of_stack; // top of task stack in the heap 0141 ; unsigned char *frame_ptr; // CCR pointer in idle stack 0141 ; }; 0141 ; 0141 ; 0141 ; // resource control block 0141 ; typedef struct resource_block { 0141 ; unsigned char id; // ID of resource 0141 ; char name[5]; // Name of resource 0141 ; enum resource_state state; // State (busy, free...) 0141 ; unsigned char owner; // Current resource owner 0141 ; signed char queue[3]; // Tasks waiting on resource 0141 ; unsigned char queue_ptr; // Next free spot in queue 0141 ; }; 0141 ; 0141 ; 0141 ; struct task_block *task[MAXTASKS]; 0141 ; struct resource_block resource[NUMRESOURCES]; 0141 ; 0141 ; 0141 ; int kdb_trace = 1; 0141 ; int kdb_trace_cycle = 0; 0141 ; 0141 ; 0141 ; // global interrupt flags 0141 ; //unsigned int interrupt_flags_ADC; 0141 ; //unsigned int interrupt_flags_TC; 0141 ; 0141 ; 0141 ; 0141 ; 0141 ; // error massages 0141 ; const char error_msg[][25] = {"unimplimented function", // error 0 0141 ; "syntax error", // error 1 0141 ; "illegal task ID", // error 2 0141 ; "illegal task state", // error 3 0141 ; "illegal task priority", // error 4 0141 ; "out of memory", // error 5 0141 ; "illegal resource ID", // error 6 0141 ; "illegal resource state", // error 7 0141 ; "cannot create task" // error 8 0141 ; }; 0141 ; const char error_src[][18] = {"kernel error:", // source 0 0141 ; "kernel.c error:", // source 1 0141 ; "kernel RTI error:", // source 2 0141 ; "shell error:", // source 3 0141 ; "semlib.c error:" // source 4 0141 ; }; 0141 ; 0141 ; 0141 ; 0141 ; 0141 ; 0141 ; main() { 0141 ; 0141 ; // LOCAL VARIABLES 0141 ; int result, id, i; 0141 ; unsigned char priority_check; 0141 ; unsigned int deadline; 0141 ; extern int _bss_end, _textmode; 0141 ; 0141 ; 0141 ; _textmode = 1; // maps '\n' to "CR/LF" for Windows terminals 0141 CC0001 ldd #1 0144 7C0000 std __textmode 0147 ; current = 0; // start the shell first 0147 CC0000 ldd #0 014A 7C0052 std _current 014D ; cop_cycle = 0; // fresh watchdog 014D CC0000 ldd #0 0150 7C004C std _cop_cycle 0153 CC0000 ldd #0 0156 6C16 std -10,x 0158 L4: 0158 CC000C ldd #12 015B ED16 ldy -10,x 015D 1813 emuls 015F C30000 addd #_resource 0162 B7C6 xgdy 0164 EC16 ldd -10,x 0166 6B40 stab 0,y 0168 CC000C ldd #12 016B ED16 ldy -10,x 016D 1813 emuls 016F C30006 addd #_resource+6 0172 B7C6 xgdy 0174 6940 clr 0,y 0176 CC000C ldd #12 0179 ED16 ldy -10,x 017B 1813 emuls 017D C30007 addd #_resource+7 0180 B7C6 xgdy 0182 C6FF ldab #255 0184 6B40 stab 0,y 0186 CC000C ldd #12 0189 ED16 ldy -10,x 018B 1813 emuls 018D C3000B addd #_resource+11 0190 B7C6 xgdy 0192 6940 clr 0,y 0194 L5: 0194 ; 0194 ; 0194 ; /* redundant... done by _startup() 0194 ; // initialize the task pointer array and the tcb array. 0194 ; for (i=0; i= KDB_CYCLES) 0231 FC0008 ldd _kdb_trace_cycle 0234 8C0004 cpd #4 0237 2D06 blt L25 0239 ; kdb_trace = 0; 0239 CC0000 ldd #0 023C 7C0006 std _kdb_trace 023F L25: 023F ; 023F ; #ifdef KDB_TRACE_LEVEL_1 023F ; if (kdb_trace) puts("kDB2.1"); 023F ; #endif 023F ; 023F ; 023F ; /* No interrupts allowed inside of main(). Only allowed 023F ; inside of non-critical sections of tasks */ 023F ; INTR_OFF(); 023F 1410 sei 0241 0241 ; 0241 ; 0241 ; // PET THE DOG: cop watchdog reset timer (pet freq = 2x COP freq) 0241 ; if (cop_cycle == 4) { 0241 FC004C ldd _cop_cycle 0244 8C0004 cpd #4 0247 2610 bne L27 0249 ; COP_PET(0x55); 0249 C655 ldab #85 024B 7B0017 stab 0x17 024E ; COP_PET(0xAA); 024E C6AA ldab #170 0250 7B0017 stab 0x17 0253 ; cop_cycle = 0; 0253 CC0000 ldd #0 0256 7C004C std _cop_cycle 0259 ; } 0259 L27: 0259 CC0000 ldd #0 025C 6C16 std -10,x 025E L29: 025E ; #ifdef KDB_TRACE_LEVEL_1 025E ; if (kdb_trace) puts("kDB2.2-1"); 025E ; #endif 025E ; 025E ; 025E ; 025E ; // CHANGE STATES ACCORDING TO MESSAGES 025E ; // 'waiting' needs to have highest precedence here 025E ; for (i=0; imessage && STATE_FLAG) { 026C EC16 ldd -10,x 026E 59 lsld 026F C30030 addd #_task 0272 B7C6 xgdy 0274 ED40 ldy 0,y 0276 E7E814 tst 20,y 0279 2732 beq L35 027B ; // set task state to what the message says 027B ; task[i]->state = task[i]->message_data[STATE_BOX]; 027B EC16 ldd -10,x 027D 59 lsld 027E C30030 addd #_task 0281 B7C6 xgdy 0283 ED40 ldy 0,y 0285 6DE1ED sty -19,x 0288 EDE1ED ldy -19,x 028B E6E815 ldab 21,y 028E EDE1ED ldy -19,x 0291 6B4C stab 12,y 0293 ; // clear the STATE_FLAG 0293 ; task[i]->message &= ~(STATE_FLAG); 0293 EC16 ldd -10,x 0295 59 lsld 0296 C30030 addd #_task 0299 B7C6 xgdy 029B EC40 ldd 0,y 029D C30014 addd #20 02A0 6CE1EB std -21,x 02A3 B746 tfr d,y 02A5 35 pshy ; spill 02A6 EDE1EB ldy -21,x 02A9 31 puly ; reload 02AA 0D4001 bclr 0,y,#0x1 02AD ; #ifdef KDB_TRACE_LEVEL_2 02AD ; if (kdb_trace) puts("kDB2.3-2a"); 02AD ; #endif 02AD ; } 02AD L35: 02AD L30: 02AD EC16 ldd -10,x 02AF C30001 addd #1 02B2 6C16 std -10,x 02B4 EC16 ldd -10,x 02B6 8C0008 cpd #8 02B9 2DA3 blt L29 02BB CC0000 ldd #0 02BE 6C16 std -10,x 02C0 L37: 02C0 ; #ifdef KDB_TRACE_LEVEL_2 02C0 ; if (kdb_trace) puts("kDB2.3-2b"); 02C0 ; #endif 02C0 ; } 02C0 ; #ifdef KDB_TRACE_LEVEL_1 02C0 ; if (kdb_trace) puts("kDB2.3-1"); 02C0 ; #endif 02C0 ; 02C0 ; 02C0 ; 02C0 ; // RT PRIORITY BLOCK: 02C0 ; // set the current task id based on priority and deadline 02C0 ; 02C0 ; // determine if the deadline is up for idle tasks 02C0 ; /* deadline, is equal to period plus an initial time (t0) reference 02C0 ; (t0 = system_tick). Period = priority + 1. 02C0 ; Changing the state from idle to PENDING occurs here. */ 02C0 ; for (i=0; istate == IDLE) { 02C0 EC16 ldd -10,x 02C2 59 lsld 02C3 C30030 addd #_task 02C6 B7C6 xgdy 02C8 ED40 ldy 0,y 02CA E74C tst 12,y 02CC 2655 bne L41 02CE ; deadline = task[i]->period_tick + (task[i]->priority + 1); 02CE EC16 ldd -10,x 02D0 59 lsld 02D1 C30030 addd #_task 02D4 B7C6 xgdy 02D6 ED40 ldy 0,y 02D8 6DE1ED sty -19,x 02DB EDE1ED ldy -19,x 02DE E64D ldab 13,y 02E0 87 clra 02E1 C30001 addd #1 02E4 160000 jsr __d2lreg2 02E7 EDE1ED ldy -19,x 02EA 194E leay 14,y 02EC 1802401C movw 0,y,-4,x 02F0 1802421E movw 2,y,-2,x 02F4 160000 jsr __ladd 02F7 160000 jsr __lreg2d 02FA 6C14 std -12,x 02FC ; if (system_tick >= deadline) { 02FC CD004E ldy #_system_tick 02FF 1802401C movw 0,y,-4,x 0303 1802421E movw 2,y,-2,x 0307 EC14 ldd -12,x 0309 6C1A std -6,x 030B 1800180000 movw #0,-8,x 0310 160000 jsr __lcmp 0313 250E blo L43 0315 ; task[i]->state = PENDING; // change state at deadline 0315 EC16 ldd -10,x 0317 59 lsld 0318 C30030 addd #_task 031B B7C6 xgdy 031D ED40 ldy 0,y 031F C601 ldab #1 0321 6B4C stab 12,y 0323 ; #ifdef KDB_TRACE_LEVEL_2 0323 ; if (kdb_trace) puts("kDB2.4-2"); 0323 ; #endif 0323 ; } 0323 L43: 0323 ; } 0323 L41: 0323 L38: 0323 EC16 ldd -10,x 0325 C30001 addd #1 0328 6C16 std -10,x 032A EC16 ldd -10,x 032C 8C0008 cpd #8 032F 2D8F blt L37 0331 ; // if (task[i]->message) {} ??? 0331 ; } 0331 ; #ifdef KDB_TRACE_LEVEL_1 0331 ; if (kdb_trace) puts("kDB2.4-1"); 0331 ; #endif 0331 ; 0331 ; 0331 ; // set current = to highest priority pending/running task. 0331 ; priority_check = 255; // lowest possible 0331 C6FF ldab #255 0333 6B13 stab -13,x 0335 CC0000 ldd #0 0338 6C16 std -10,x 033A L45: 033A ; 033A ; for (i=0; istate == PENDING) || (task[i]->state == RUNNING)) { 0363 ; if (task[i]->priority <= priority_check) { 0363 EC16 ldd -10,x 0365 59 lsld 0366 C30030 addd #_task 0369 B7C6 xgdy 036B ED40 ldy 0,y 036D E64D ldab 13,y 036F E113 cmpb -13,x 0371 2213 bhi L54 0373 ; current = i; 0373 EC16 ldd -10,x 0375 7C0052 std _current 0378 ; priority_check = task[i]->priority; 0378 EC16 ldd -10,x 037A 59 lsld 037B C30030 addd #_task 037E B7C6 xgdy 0380 ED40 ldy 0,y 0382 E64D ldab 13,y 0384 6B13 stab -13,x 0386 ; #ifdef KDB_TRACE_LEVEL_2 0386 ; if (kdb_trace) puts("kDB2.5-2"); 0386 ; #endif 0386 ; } 0386 L54: 0386 ; } 0386 L51: 0386 ; } 0386 L49: 0386 L46: 0386 EC16 ldd -10,x 0388 C30001 addd #1 038B 6C16 std -10,x 038D EC16 ldd -10,x 038F 8C0008 cpd #8 0392 2DA6 blt L45 0394 FC0052 ldd _current 0397 59 lsld 0398 C30030 addd #_task 039B B7C6 xgdy 039D ED40 ldy 0,y 039F E64C ldab 12,y 03A1 87 clra 03A2 6CE1ED std -19,x 03A5 182700B1 lbeq L57 03A9 ECE1ED ldd -19,x 03AC 8C0001 cpd #1 03AF 2722 beq L60 03B1 ECE1ED ldd -19,x 03B4 8C0002 cpd #2 03B7 1827007C lbeq L61 03BB ECE1ED ldd -19,x 03BE 8C0003 cpd #3 03C1 18270095 lbeq L57 03C5 ECE1ED ldd -19,x 03C8 8C0004 cpd #4 03CB 1827008B lbeq L57 03CF 1820007B lbra L56 03D3 X0: 03D3 ; } 03D3 ; #ifdef KDB_TRACE_LEVEL_1 03D3 ; if (kdb_trace) puts("kDB2.5-1"); 03D3 ; #endif 03D3 ; 03D3 ; 03D3 ; 03D3 ; // DISPATCH, or otherwise deal with the current task 03D3 ; // KDB_TRACE Section 3 03D3 ; 03D3 ; #ifdef KDB_TRACE_LEVEL_2 03D3 ; if (kdb_trace) { 03D3 ; printf("task[%d]->state = %d\n", current, task[current]->state); 03D3 ; printf("task[%d]->prior = %d\n", current, task[current]->priority); 03D3 ; } 03D3 ; #endif 03D3 ; 03D3 ; switch (task[current]->state) { 03D3 ; case IDLE: // skip task 03D3 ; #ifdef KDB_TRACE_LEVEL_1 03D3 ; if (kdb_trace) puts("kDB3.1-1"); 03D3 ; #endif 03D3 ; break; 03D3 L60: 03D3 ; case PENDING: // ready and waiting to run 03D3 ; #ifdef KDB_TRACE_LEVEL_1 03D3 ; if (kdb_trace) puts("kDB3.2-1"); 03D3 ; #endif 03D3 ; #ifdef KDB_TRACE_LEVEL_2 03D3 ; if (kdb_trace) { 03D3 ; //puts("kDB3.2-2"); 03D3 ; putchar('S'); 03D3 ; putchar(current+48); 03D3 ; putchar('\n'); 03D3 ; } 03D3 ; #endif 03D3 ; task[current]->state = RUNNING; 03D3 FC0052 ldd _current 03D6 59 lsld 03D7 C30030 addd #_task 03DA B7C6 xgdy 03DC ED40 ldy 0,y 03DE C602 ldab #2 03E0 6B4C stab 12,y 03E2 ; task[current]->period_tick = system_tick; 03E2 FC0052 ldd _current 03E5 59 lsld 03E6 C30030 addd #_task 03E9 B7C6 xgdy 03EB ED40 ldy 0,y 03ED 194E leay 14,y 03EF 35 pshy ; spill 03F0 CD004E ldy #_system_tick 03F3 1802401C movw 0,y,-4,x 03F7 1802421E movw 2,y,-2,x 03FB 31 puly ; reload 03FC 18021C40 movw -4,x,0,y 0400 18021E42 movw -2,x,2,y 0404 ; temp_task_frame_ptr = task[current]->top_of_stack; 0404 FC0052 ldd _current 0407 59 lsld 0408 C30030 addd #_task 040B B7C6 xgdy 040D ED40 ldy 0,y 040F EDE819 ldy 25,y 0412 7D0004 sty _temp_task_frame_ptr 0415 ; asm("LDS _temp_task_frame_ptr"); // set the SP 0415 FF0004 LDS _temp_task_frame_ptr 0418 0418 ; (*task_ptr[current])(); // start the task 0418 FC0052 ldd _current 041B 59 lsld 041C C30054 addd #_task_ptr 041F B7C6 xgdy 0421 ED40 ldy 0,y 0423 1540 jsr 0,y 0425 ; asm("LDS _main_frame_ptr"); // reset the SP 0425 FF0000 LDS _main_frame_ptr 0428 0428 ; task[current]->state = IDLE; // task finished 0428 FC0052 ldd _current 042B 59 lsld 042C C30030 addd #_task 042F B7C6 xgdy 0431 ED40 ldy 0,y 0433 694C clr 12,y 0435 ; #ifdef KDB_TRACE_LEVEL_1 0435 ; if (kdb_trace) puts("kDB3.3-1"); 0435 ; #endif 0435 ; #ifdef KDB_TRACE_LEVEL_2 0435 ; if (kdb_trace) { 0435 ; //puts("kDB3.3-2"); 0435 ; putchar('F'); 0435 ; putchar(current+48); 0435 ; putchar('\n'); 0435 ; } 0435 ; #endif 0435 ; break; 0435 2023 bra L57 0437 L61: 0437 ; case RUNNING: // interrupted. continue running. 0437 ; // restore context and run 0437 ; temp_task_frame_ptr = task[current]->frame_ptr; 0437 FC0052 ldd _current 043A 59 lsld 043B C30030 addd #_task 043E B7C6 xgdy 0440 ED40 ldy 0,y 0442 EDE81B ldy 27,y 0445 7D0004 sty _temp_task_frame_ptr 0448 ; asm("LDS _temp_task_frame_ptr"); 0448 FF0004 LDS _temp_task_frame_ptr 044B 044B ; asm("RTI"); 044B 0B RTI 044C 044C ; break; 044C 200C bra L57 044E X1: 044E ; case WAITING: // waiting on a resource 044E ; #ifdef KDB_TRACE_LEVEL_1 044E ; if (kdb_trace) puts("kDB3.5-1"); 044E ; #endif 044E ; break; 044E ; case STOPPED: // done running until later 044E ; #ifdef KDB_TRACE_LEVEL_1 044E ; if (kdb_trace) puts("kDB3.6-1"); 044E ; #endif 044E ; break; 044E L56: 044E ; default: // shouldn't happen, but, error if so. 044E ; puts("KERNEL: task state error\n"); 044E CC0B06 ldd #L64 0451 160000 jsr _puts 0454 ; exit(1); 0454 CC0001 ldd #1 0457 160000 jsr _exit 045A ; } // end switch 045A L57: 045A L23: 045A 1820FDD3 lbra L22 045E X2: 045E ; 045E ; } // end while(1) 045E ; 045E ; return 0; 045E CC0000 ldd #0 0461 L3: 0461 B757 tfr x,s 0463 30 pulx 0464 .dbline 0 ; func end 0464 3D rts 0465 ; lreg1 -> -4,x 0465 ; lreg2 -> -8,x 0465 ; local_thp -> -14,x 0465 ; i -> -12,x 0465 ; frame_size -> -10,x 0465 _RTI_handler:: 0465 34 pshx 0466 B775 tfr s,x 0468 1B92 leas -14,sp 046A ; 046A ; } // end main() 046A ; 046A ; 046A ; 046A ; #pragma interrupt_handler RTI_handler() 046A ; 046A ; void RTI_handler(void) { 046A ; 046A ; size_t frame_size; 046A ; unsigned int i; 046A ; unsigned char *local_thp; 046A ; 046A ; 046A ; //ACKNOWLEDGE THE INTERRUPT 046A ; RTIFLG = 0x0080; // acknowledge/clear the interrupt 046A C680 ldab #128 046C 7B0015 stab 0x15 046F ; 046F ; 046F ; #ifdef KDB_TRACE_LEVEL_1 046F ; if (kdb_trace) putchar('.'); 046F ; #endif 046F ; 046F ; 046F ; // SET THE FRAME POINTER for the interupted task. 046F ; // should point to the CCR entry on the stack. 046F ; asm("TFR x,d"); // start of RTI stack 046F B754 TFR x,d 0471 0471 ; asm("ADDD #2"); // adjust to CCR stack entry 0471 C30002 ADDD #2 0474 0474 ; asm("STD _temp_task_frame_ptr"); // put into task_frame_ptr 0474 7C0004 STD _temp_task_frame_ptr 0477 0477 ; task[current]->frame_ptr = temp_task_frame_ptr; 0477 FC0052 ldd _current 047A 59 lsld 047B C30030 addd #_task 047E B7C6 xgdy 0480 ED40 ldy 0,y 0482 FC0004 ldd _temp_task_frame_ptr 0485 6CE81B std 27,y 0488 ; 0488 ; 0488 ; 0488 ; // update system time base and cop reset counter 0488 ; system_tick++; 0488 CD004E ldy #_system_tick 048B 1802401C movw 0,y,-4,x 048F 1802421E movw 2,y,-2,x 0493 CD0B02 ldy #L66 0496 18024018 movw 0,y,-8,x 049A 1802421A movw 2,y,-6,x 049E 160000 jsr __ladd 04A1 CD004E ldy #_system_tick 04A4 18021C40 movw -4,x,0,y 04A8 18021E42 movw -2,x,2,y 04AC ; cop_cycle++; 04AC FC004C ldd _cop_cycle 04AF C30001 addd #1 04B2 7C004C std _cop_cycle 04B5 ; 04B5 ; 04B5 ; 04B5 ; // RETURN: simulate a RTS instruction 04B5 ; // set stack pointer for main() 04B5 ; asm("LDS _main_frame_ptr"); 04B5 FF0000 LDS _main_frame_ptr 04B8 04B8 ; asm("LDX _main_frame_x_ptr"); 04B8 FE0002 LDX _main_frame_x_ptr 04BB 04BB ; /* return to main() at the reentry point 04BB ; and must be adjusted after each kernel mod/compilation!! */ 04BB ; asm("JMP $125B"); 04BB 06125B JMP $125B 04BE 04BE ; 04BE ; 04BE ; // return (0) -- NOT used 04BE ; /* this ISR should never use the 'return x' command. 04BE ; It doesn't make sense since it always interrupts a Task, but 04BE ; never returns to it... but to main() instead. */ 04BE ; 04BE ; } 04BE L65: 04BE B757 tfr x,s 04C0 30 pulx 04C1 .dbline 0 ; func end 04C1 0B rti 04C2 ; id -> 3,x 04C2 _get_task_address:: 04C2 3B pshd 04C3 34 pshx 04C4 B775 tfr s,x 04C6 ; 04C6 ; 04C6 ; 04C6 ; 04C6 ; 04C6 ; // KERNEL FUNCTIONS 04C6 ; 04C6 ; int get_task_address(char id) { 04C6 ; 04C6 ; return (int)task[id]->address; 04C6 E603 ldab 3,x 04C8 87 clra 04C9 59 lsld 04CA C30030 addd #_task 04CD B7C6 xgdy 04CF ECEB0000 ldd [0,y] 04D3 L67: 04D3 B757 tfr x,s 04D5 30 pulx 04D6 1B82 leas 2,sp 04D8 .dbline 0 ; func end 04D8 3D rts 04D9 _get_task_id:: 04D9 ; 04D9 ; } 04D9 ; 04D9 ; 04D9 ; 04D9 ; 04D9 ; char get_task_id() { 04D9 ; 04D9 ; return task[current]->id; 04D9 FC0052 ldd _current 04DC 59 lsld 04DD C30030 addd #_task 04E0 B7C6 xgdy 04E2 ED40 ldy 0,y 04E4 E642 ldab 2,y 04E6 87 clra 04E7 L68: 04E7 .dbline 0 ; func end 04E7 3D rts 04E8 ; id -> 3,x 04E8 _get_task_name:: 04E8 3B pshd 04E9 34 pshx 04EA B775 tfr s,x 04EC ; } 04EC ; 04EC ; 04EC ; 04EC ; char *get_task_name(unsigned char id) { 04EC ; if (task[id] == NULL) 04EC E603 ldab 3,x 04EE 87 clra 04EF 59 lsld 04F0 C30030 addd #_task 04F3 B7C6 xgdy 04F5 EC40 ldd 0,y 04F7 2605 bne L70 04F9 ; return NULL; 04F9 CC0000 ldd #0 04FC 200E bra L69 04FE L70: 04FE ; else 04FE ; return task[id]->name; 04FE E603 ldab 3,x 0500 87 clra 0501 59 lsld 0502 C30030 addd #_task 0505 B7C6 xgdy 0507 EC40 ldd 0,y 0509 C30003 addd #3 050C L69: 050C B757 tfr x,s 050E 30 pulx 050F 1B82 leas 2,sp 0511 .dbline 0 ; func end 0511 3D rts 0512 ; id -> 3,x 0512 _get_task_state:: 0512 3B pshd 0513 34 pshx 0514 B775 tfr s,x 0516 ; } 0516 ; 0516 ; 0516 ; 0516 ; 0516 ; int get_task_state(unsigned char id) { 0516 ; 0516 ; if (task[id] == NULL) 0516 E603 ldab 3,x 0518 87 clra 0519 59 lsld 051A C30030 addd #_task 051D B7C6 xgdy 051F EC40 ldd 0,y 0521 2605 bne L73 0523 ; return -1; 0523 CCFFFF ldd #-1 0526 2019 bra L72 0528 L73: 0528 ; else if (id < MAXTASKS) 0528 E603 ldab 3,x 052A C108 cmpb #8 052C 2410 bhs L75 052E ; return task[id]->state; 052E E603 ldab 3,x 0530 87 clra 0531 59 lsld 0532 C30030 addd #_task 0535 B7C6 xgdy 0537 ED40 ldy 0,y 0539 E64C ldab 12,y 053B 87 clra 053C 2003 bra L72 053E L75: 053E ; else { 053E ; #ifdef KERNEL_ERROR_MSG 053E ; puts(error_src[1]); puts(error_msg[3]); 053E ; #endif 053E ; return -1; 053E CCFFFF ldd #-1 0541 L72: 0541 B757 tfr x,s 0543 30 pulx 0544 1B82 leas 2,sp 0546 .dbline 0 ; func end 0546 3D rts 0547 ; id -> 3,x 0547 _get_task_messages:: 0547 3B pshd 0548 34 pshx 0549 B775 tfr s,x 054B ; } 054B ; 054B ; } 054B ; 054B ; 054B ; 054B ; int get_task_messages(unsigned char id) { 054B ; 054B ; if (task[id] == NULL) 054B E603 ldab 3,x 054D 87 clra 054E 59 lsld 054F C30030 addd #_task 0552 B7C6 xgdy 0554 EC40 ldd 0,y 0556 2605 bne L78 0558 ; return -1; 0558 CCFFFF ldd #-1 055B 201A bra L77 055D L78: 055D ; else if (id < MAXTASKS) 055D E603 ldab 3,x 055F C108 cmpb #8 0561 2411 bhs L80 0563 ; return task[id]->message; 0563 E603 ldab 3,x 0565 87 clra 0566 59 lsld 0567 C30030 addd #_task 056A B7C6 xgdy 056C ED40 ldy 0,y 056E E6E814 ldab 20,y 0571 87 clra 0572 2003 bra L77 0574 L80: 0574 ; else { 0574 ; #ifdef KERNEL_ERROR_MSG 0574 ; puts(error_src[1]); puts(error_msg[3]); 0574 ; #endif 0574 ; return -1; 0574 CCFFFF ldd #-1 0577 L77: 0577 B757 tfr x,s 0579 30 pulx 057A 1B82 leas 2,sp 057C .dbline 0 ; func end 057C 3D rts 057D ; id -> 3,x 057D _get_task_priority:: 057D 3B pshd 057E 34 pshx 057F B775 tfr s,x 0581 ; } 0581 ; 0581 ; } 0581 ; 0581 ; 0581 ; 0581 ; int get_task_priority(unsigned char id) { 0581 ; 0581 ; INTR_OFF(); 0581 1410 sei 0583 0583 ; 0583 ; if (id < MAXTASKS) { 0583 E603 ldab 3,x 0585 C108 cmpb #8 0587 2412 bhs L83 0589 ; INTR_ON(); 0589 10EF cli 058B 058B ; return task[id]->priority; 058B E603 ldab 3,x 058D 87 clra 058E 59 lsld 058F C30030 addd #_task 0592 B7C6 xgdy 0594 ED40 ldy 0,y 0596 E64D ldab 13,y 0598 87 clra 0599 2005 bra L82 059B L83: 059B ; } 059B ; else { 059B ; #ifdef KERNEL_ERROR_MSG 059B ; puts(error_src[1]); puts(error_msg[4]); 059B ; #endif 059B ; INTR_ON(); 059B 10EF cli 059D 059D ; return -1; 059D CCFFFF ldd #-1 05A0 L82: 05A0 B757 tfr x,s 05A2 30 pulx 05A3 1B82 leas 2,sp 05A5 .dbline 0 ; func end 05A5 3D rts 05A6 ; ?temp -> -4,x 05A6 ; ?temp -> -4,x 05A6 ; ?temp -> -4,x 05A6 ; ?temp -> -4,x 05A6 ; ?temp -> -4,x 05A6 ; ?temp -> -2,x 05A6 ; newstate -> 7,x 05A6 ; id -> 3,x 05A6 _set_task_state:: 05A6 3B pshd 05A7 34 pshx 05A8 B775 tfr s,x 05AA 1B9C leas -4,sp 05AC ; } 05AC ; 05AC ; } 05AC ; 05AC ; 05AC ; 05AC ; int set_task_state(unsigned char id, unsigned char newstate) { 05AC ; 05AC ; 05AC ; INTR_OFF(); 05AC 1410 sei 05AE 05AE ; 05AE ; 05AE ; // check id validity 05AE ; if (id < MAXTASKS) { 05AE E603 ldab 3,x 05B0 C108 cmpb #8 05B2 182401D9 lbhs L86 05B6 ; 05B6 ; if (task[id] == NULL) { 05B6 E603 ldab 3,x 05B8 87 clra 05B9 59 lsld 05BA C30030 addd #_task 05BD B7C6 xgdy 05BF EC40 ldd 0,y 05C1 2609 bne L88 05C3 ; #ifdef KERNEL_ERROR_MSG 05C3 ; puts(error_src[1]); puts(error_msg[2]); 05C3 ; #endif 05C3 ; INTR_ON(); 05C3 10EF cli 05C5 05C5 ; return -1; 05C5 CCFFFF ldd #-1 05C8 182001CF lbra L85 05CC L88: 05CC ; } 05CC ; 05CC ; 05CC ; // check newstate validity 05CC ; if ((newstate == RUNNING) || 05CC E607 ldab 7,x 05CE C102 cmpb #2 05D0 270C beq L93 05D2 E607 ldab 7,x 05D4 C103 cmpb #3 05D6 2706 beq L93 05D8 E607 ldab 7,x 05DA C104 cmpb #4 05DC 2309 bls L90 05DE L93: 05DE ; (newstate == WAITING) || 05DE ; (newstate > STOPPED)) { 05DE ; #ifdef KERNEL_ERROR_MSG 05DE ; puts(error_src[1]); puts(error_msg[3]); 05DE ; #endif 05DE ; INTR_ON(); 05DE 10EF cli 05E0 05E0 ; return -1; 05E0 CCFFFF ldd #-1 05E3 182001B4 lbra L85 05E7 L90: 05E7 E603 ldab 3,x 05E9 87 clra 05EA 59 lsld 05EB C30030 addd #_task 05EE B7C6 xgdy 05F0 ED40 ldy 0,y 05F2 E64C ldab 12,y 05F4 87 clra 05F5 6C1E std -2,x 05F7 271F beq L97 05F9 EC1E ldd -2,x 05FB 8C0001 cpd #1 05FE 1827009C lbeq L104 0602 EC1E ldd -2,x 0604 8C0002 cpd #2 0607 182700F0 lbeq L111 060B EC1E ldd -2,x 060D 8C0004 cpd #4 0610 18270128 lbeq L114 0614 18200170 lbra L94 0618 X3: 0618 ; } 0618 ; 0618 ; // referenced to the task's current state: 0618 ; switch (task[id]->state) { 0618 L97: 0618 ; case IDLE: 0618 ; if (newstate == IDLE) { // no change 0618 E707 tst 7,x 061A 2609 bne L98 061C ; INTR_ON(); 061C 10EF cli 061E 061E ; return 0; 061E CC0000 ldd #0 0621 18200176 lbra L85 0625 L98: 0625 ; } 0625 ; else if (newstate == PENDING) { 0625 E607 ldab 7,x 0627 C101 cmpb #1 0629 2632 bne L100 062B ; // pass msg to task[id]->msgbox; 062B ; task[id]->message |= STATE_FLAG; 062B E603 ldab 3,x 062D 87 clra 062E 59 lsld 062F C30030 addd #_task 0632 B7C6 xgdy 0634 EC40 ldd 0,y 0636 C30014 addd #20 0639 6C1C std -4,x 063B B746 tfr d,y 063D 35 pshy ; spill 063E ED1C ldy -4,x 0640 31 puly ; reload 0641 0C4001 bset 0,y,#1 0644 ; task[id]->message_data[STATE_BOX] = PENDING; 0644 E603 ldab 3,x 0646 87 clra 0647 59 lsld 0648 C30030 addd #_task 064B B7C6 xgdy 064D ED40 ldy 0,y 064F C601 ldab #1 0651 6BE815 stab 21,y 0654 ; INTR_ON(); 0654 10EF cli 0656 0656 ; return 0; 0656 CC0000 ldd #0 0659 1820013E lbra L85 065D L100: 065D ; } 065D ; else if (newstate == STOPPED) { 065D E607 ldab 7,x 065F C104 cmpb #4 0661 2632 bne L102 0663 ; // pass msg to task[id]->msgbox; 0663 ; task[id]->message |= STATE_FLAG; 0663 E603 ldab 3,x 0665 87 clra 0666 59 lsld 0667 C30030 addd #_task 066A B7C6 xgdy 066C EC40 ldd 0,y 066E C30014 addd #20 0671 6C1C std -4,x 0673 B746 tfr d,y 0675 35 pshy ; spill 0676 ED1C ldy -4,x 0678 31 puly ; reload 0679 0C4001 bset 0,y,#1 067C ; task[id]->message_data[STATE_BOX] = STOPPED; 067C E603 ldab 3,x 067E 87 clra 067F 59 lsld 0680 C30030 addd #_task 0683 B7C6 xgdy 0685 ED40 ldy 0,y 0687 C604 ldab #4 0689 6BE815 stab 21,y 068C ; INTR_ON(); 068C 10EF cli 068E 068E ; return 0; 068E CC0000 ldd #0 0691 18200106 lbra L85 0695 L102: 0695 ; } 0695 ; else { // nothing else is legal; 0695 ; #ifdef KERNEL_ERROR_MSG 0695 ; puts(error_src[1]); puts(error_msg[3]); 0695 ; #endif 0695 ; INTR_ON(); 0695 10EF cli 0697 0697 ; return -1; 0697 CCFFFF ldd #-1 069A 182000FD lbra L85 069E X4: 069E ; } 069E ; break; 069E L104: 069E ; case PENDING: 069E ; if (newstate == PENDING) { // no change 069E E607 ldab 7,x 06A0 C101 cmpb #1 06A2 2609 bne L105 06A4 ; INTR_ON(); 06A4 10EF cli 06A6 06A6 ; return 0; 06A6 CC0000 ldd #0 06A9 182000EE lbra L85 06AD L105: 06AD ; } 06AD ; else if (newstate == IDLE) { 06AD E707 tst 7,x 06AF 2609 bne L107 06B1 ; // pass msg to task[id]->msgbox; 06B1 ; #ifdef KERNEL_ERROR_MSG 06B1 ; puts(error_src[1]); puts(error_msg[0]); 06B1 ; #endif 06B1 ; INTR_ON(); 06B1 10EF cli 06B3 06B3 ; return -1; 06B3 CCFFFF ldd #-1 06B6 182000E1 lbra L85 06BA L107: 06BA ; } 06BA ; else if (newstate == STOPPED) { 06BA E607 ldab 7,x 06BC C104 cmpb #4 06BE 2632 bne L109 06C0 ; // pass msg to task[id]->msgbox; 06C0 ; task[id]->message |= STATE_FLAG; 06C0 E603 ldab 3,x 06C2 87 clra 06C3 59 lsld 06C4 C30030 addd #_task 06C7 B7C6 xgdy 06C9 EC40 ldd 0,y 06CB C30014 addd #20 06CE 6C1C std -4,x 06D0 B746 tfr d,y 06D2 35 pshy ; spill 06D3 ED1C ldy -4,x 06D5 31 puly ; reload 06D6 0C4001 bset 0,y,#1 06D9 ; task[id]->message_data[STATE_BOX] = STOPPED; 06D9 E603 ldab 3,x 06DB 87 clra 06DC 59 lsld 06DD C30030 addd #_task 06E0 B7C6 xgdy 06E2 ED40 ldy 0,y 06E4 C604 ldab #4 06E6 6BE815 stab 21,y 06E9 ; INTR_ON(); 06E9 10EF cli 06EB 06EB ; return 0; 06EB CC0000 ldd #0 06EE 182000A9 lbra L85 06F2 L109: 06F2 ; } 06F2 ; else { 06F2 ; #ifdef KERNEL_ERROR_MSG 06F2 ; puts(error_src[1]); puts(error_msg[3]); 06F2 ; #endif 06F2 ; INTR_ON(); 06F2 10EF cli 06F4 06F4 ; return -1; 06F4 CCFFFF ldd #-1 06F7 182000A0 lbra L85 06FB X5: 06FB ; } 06FB ; break; 06FB L111: 06FB ; case RUNNING: 06FB ; if (newstate == STOPPED) { 06FB E607 ldab 7,x 06FD C104 cmpb #4 06FF 2632 bne L112 0701 ; // pass msg to task[id]->msgbox; 0701 ; task[id]->message |= STATE_FLAG; 0701 E603 ldab 3,x 0703 87 clra 0704 59 lsld 0705 C30030 addd #_task 0708 B7C6 xgdy 070A EC40 ldd 0,y 070C C30014 addd #20 070F 6C1C std -4,x 0711 B746 tfr d,y 0713 35 pshy ; spill 0714 ED1C ldy -4,x 0716 31 puly ; reload 0717 0C4001 bset 0,y,#1 071A ; task[id]->message_data[STATE_BOX] = STOPPED; 071A E603 ldab 3,x 071C 87 clra 071D 59 lsld 071E C30030 addd #_task 0721 B7C6 xgdy 0723 ED40 ldy 0,y 0725 C604 ldab #4 0727 6BE815 stab 21,y 072A ; 072A ; INTR_ON(); 072A 10EF cli 072C 072C ; return 0; 072C CC0000 ldd #0 072F 18200068 lbra L85 0733 L112: 0733 ; } 0733 ; else { 0733 ; #ifdef KERNEL_ERROR_MSG 0733 ; puts(error_src[1]); puts(error_msg[3]); 0733 ; #endif 0733 ; INTR_ON(); 0733 10EF cli 0735 0735 ; return -1; 0735 CCFFFF ldd #-1 0738 1820005F lbra L85 073C X6: 073C ; } 073C ; break; 073C L114: 073C ; case STOPPED: 073C ; if (newstate == STOPPED) { // no change 073C E607 ldab 7,x 073E C104 cmpb #4 0740 2609 bne L115 0742 ; INTR_ON(); 0742 10EF cli 0744 0744 ; return 0; 0744 CC0000 ldd #0 0747 18200050 lbra L85 074B L115: 074B ; } 074B ; else if (newstate == PENDING) { 074B E607 ldab 7,x 074D C101 cmpb #1 074F 2630 bne L117 0751 ; // pass msg to task[id]->msgbox; 0751 ; task[id]->message |= STATE_FLAG; 0751 E603 ldab 3,x 0753 87 clra 0754 59 lsld 0755 C30030 addd #_task 0758 B7C6 xgdy 075A EC40 ldd 0,y 075C C30014 addd #20 075F 6C1C std -4,x 0761 B746 tfr d,y 0763 35 pshy ; spill 0764 ED1C ldy -4,x 0766 31 puly ; reload 0767 0C4001 bset 0,y,#1 076A ; task[id]->message_data[STATE_BOX] = PENDING; 076A E603 ldab 3,x 076C 87 clra 076D 59 lsld 076E C30030 addd #_task 0771 B7C6 xgdy 0773 ED40 ldy 0,y 0775 C601 ldab #1 0777 6BE815 stab 21,y 077A ; INTR_ON(); 077A 10EF cli 077C 077C ; return 0; 077C CC0000 ldd #0 077F 201A bra L85 0781 L117: 0781 ; } 0781 ; else { 0781 ; #ifdef KERNEL_ERROR_MSG 0781 ; puts(error_src[1]); puts(error_msg[3]); 0781 ; #endif 0781 ; INTR_ON(); 0781 10EF cli 0783 0783 ; return -1; 0783 CCFFFF ldd #-1 0786 2013 bra L85 0788 X7: 0788 ; } 0788 ; break; 0788 L94: 0788 ; default: 0788 ; #ifdef KERNEL_ERROR_MSG 0788 ; puts(error_src[1]); puts(error_msg[3]); 0788 ; #endif 0788 ; INTR_ON(); 0788 10EF cli 078A 078A ; return -1; 078A CCFFFF ldd #-1 078D 200C bra L85 078F X8: 078F ; break; 078F L86: 078F ; 078F ; } // end switch (task[id]->state) 078F ; 078F ; } // if (id < MAXTASKS) 078F ; 078F ; else { 078F ; #ifdef KERNEL_ERROR_MSG 078F ; puts(error_src[1]); puts(error_msg[2]); 078F ; #endif 078F ; INTR_ON(); 078F 10EF cli 0791 0791 ; return -1; 0791 CCFFFF ldd #-1 0794 2005 bra L85 0796 X9: 0796 ; } 0796 ; 0796 ; INTR_ON(); 0796 10EF cli 0798 0798 ; return 0; 0798 CC0000 ldd #0 079B L85: 079B B757 tfr x,s 079D 30 pulx 079E 1B82 leas 2,sp 07A0 .dbline 0 ; func end 07A0 3D rts 07A1 ; priority -> 7,x 07A1 ; id -> 3,x 07A1 _set_task_priority:: 07A1 3B pshd 07A2 34 pshx 07A3 B775 tfr s,x 07A5 ; 07A5 ; } 07A5 ; 07A5 ; 07A5 ; 07A5 ; int set_task_priority(unsigned char id, unsigned char priority) { 07A5 ; 07A5 ; if (priority == 0) // priority 0 is reserved for the shell 07A5 E707 tst 7,x 07A7 2604 bne L120 07A9 ; priority = 1; 07A9 C601 ldab #1 07AB 6B07 stab 7,x 07AD L120: 07AD ; 07AD ; if (id >= (MAXTASKS)) { 07AD E603 ldab 3,x 07AF C108 cmpb #8 07B1 2505 blo L122 07B3 ; #ifdef KERNEL_ERROR_MSG 07B3 ; puts(error_src[1]); puts(error_msg[4]); 07B3 ; #endif 07B3 ; return -1; 07B3 CCFFFF ldd #-1 07B6 2021 bra L119 07B8 L122: 07B8 E607 ldab 7,x 07BA C1FF cmpb #255 07BC 2204 bhi L126 07BE E707 tst 7,x 07C0 2405 bhs L124 07C2 L126: 07C2 ; } 07C2 ; else if ((priority > 255) || (priority < 0)) { 07C2 ; #ifdef KERNEL_ERROR_MSG 07C2 ; puts(error_src[1]); puts(error_msg[4]); 07C2 ; #endif 07C2 ; return -1; 07C2 CCFFFF ldd #-1 07C5 2012 bra L119 07C7 L124: 07C7 ; } 07C7 ; else { 07C7 ; task[id]->priority = priority; 07C7 E603 ldab 3,x 07C9 87 clra 07CA 59 lsld 07CB C30030 addd #_task 07CE B7C6 xgdy 07D0 ED40 ldy 0,y 07D2 E607 ldab 7,x 07D4 6B4D stab 13,y 07D6 ; return 0; 07D6 CC0000 ldd #0 07D9 L119: 07D9 B757 tfr x,s 07DB 30 pulx 07DC 1B82 leas 2,sp 07DE .dbline 0 ; func end 07DE 3D rts 07DF ; lreg1 -> -4,x 07DF ; lreg2 -> -8,x 07DF ; ?temp -> -15,x 07DF ; ?temp -> -13,x 07DF ; ?temp -> -11,x 07DF ; id -> -9,x 07DF ; stack_size -> 12,x 07DF ; state -> 10,x 07DF ; priority -> 9,x 07DF ; addr -> 6,x 07DF ; name -> 2,x 07DF _create_task:: 07DF 3B pshd 07E0 34 pshx 07E1 B775 tfr s,x 07E3 1BF1EA leas -22,sp 07E6 ; } 07E6 ; } 07E6 ; 07E6 ; 07E6 ; 07E6 ; 07E6 ; int create_task(char *name, 07E6 ; void (*addr)(), 07E6 ; unsigned char priority, 07E6 ; int state, 07E6 ; int stack_size) { 07E6 ; 07E6 ; // LOCAL VARIABLES 07E6 ; unsigned char id; 07E6 ; 07E6 ; 07E6 ; INTR_OFF(); // critical section 07E6 1410 sei 07E8 07E8 6917 clr -9,x 07EA 2015 bra L131 07EC L128: 07EC E617 ldab -9,x 07EE 87 clra 07EF 59 lsld 07F0 C30054 addd #_task_ptr 07F3 B7C6 xgdy 07F5 EC40 ldd 0,y 07F7 270E beq L130 07F9 L129: 07F9 E617 ldab -9,x 07FB 87 clra 07FC C30001 addd #1 07FF 6B17 stab -9,x 0801 L131: 0801 ; 0801 ; 0801 ; //if (get_free_memory() > 64) { 0801 ; 0801 ; // determine lowest free id available to assign to this task 0801 ; for (id=0; idaddress = addr; 0837 E617 ldab -9,x 0839 87 clra 083A 59 lsld 083B C30030 addd #_task 083E B7C6 xgdy 0840 ED40 ldy 0,y 0842 EC06 ldd 6,x 0844 6C40 std 0,y 0846 ; task[id]->id = id; 0846 E617 ldab -9,x 0848 87 clra 0849 59 lsld 084A C30030 addd #_task 084D B7C6 xgdy 084F ED40 ldy 0,y 0851 E617 ldab -9,x 0853 6B42 stab 2,y 0855 ; strcpy(task[id]->name, name); 0855 18020280 movw 2,x,0,sp 0859 E617 ldab -9,x 085B 87 clra 085C 59 lsld 085D C30030 addd #_task 0860 B7C6 xgdy 0862 EC40 ldd 0,y 0864 C30003 addd #3 0867 160000 jsr _strcpy 086A ; task[id]->state = state; 086A E617 ldab -9,x 086C 87 clra 086D 59 lsld 086E C30030 addd #_task 0871 B7C6 xgdy 0873 ED40 ldy 0,y 0875 EC0A ldd 10,x 0877 6B4C stab 12,y 0879 ; task[id]->priority = priority; 0879 E617 ldab -9,x 087B 87 clra 087C 59 lsld 087D C30030 addd #_task 0880 B7C6 xgdy 0882 ED40 ldy 0,y 0884 E609 ldab 9,x 0886 6B4D stab 13,y 0888 ; task[id]->period_tick = 0; 0888 E617 ldab -9,x 088A 87 clra 088B 59 lsld 088C C30030 addd #_task 088F B7C6 xgdy 0891 ED40 ldy 0,y 0893 194E leay 14,y 0895 35 pshy ; spill 0896 CD0B2D ldy #L20 0899 1802401C movw 0,y,-4,x 089D 1802421E movw 2,y,-2,x 08A1 31 puly ; reload 08A2 18021C40 movw -4,x,0,y 08A6 18021E42 movw -2,x,2,y 08AA ; task[id]->interrupt_msg_box = NULL; 08AA E617 ldab -9,x 08AC 87 clra 08AD 59 lsld 08AE C30030 addd #_task 08B1 B7C6 xgdy 08B3 ED40 ldy 0,y 08B5 CC0000 ldd #0 08B8 6CE812 std 18,y 08BB ; task[id]->message = NULL; 08BB E617 ldab -9,x 08BD 87 clra 08BE 59 lsld 08BF C30030 addd #_task 08C2 B7C6 xgdy 08C4 ED40 ldy 0,y 08C6 69E814 clr 20,y 08C9 ; task[id]->message_data[0] = NULL; 08C9 E617 ldab -9,x 08CB 87 clra 08CC 59 lsld 08CD C30030 addd #_task 08D0 B7C6 xgdy 08D2 ED40 ldy 0,y 08D4 69E815 clr 21,y 08D7 ; task[id]->message_data[1] = NULL; 08D7 E617 ldab -9,x 08D9 87 clra 08DA 59 lsld 08DB C30030 addd #_task 08DE B7C6 xgdy 08E0 ED40 ldy 0,y 08E2 69E816 clr 22,y 08E5 ; if (stack_size == 0) stack_size = DEFAULT_STACK_SIZE; 08E5 EC0C ldd 12,x 08E7 2605 bne L136 08E9 CC0040 ldd #64 08EC 6C0C std 12,x 08EE L136: 08EE ; task[id]->stack_size = stack_size; 08EE E617 ldab -9,x 08F0 87 clra 08F1 59 lsld 08F2 C30030 addd #_task 08F5 B7C6 xgdy 08F7 ED40 ldy 0,y 08F9 EC0C ldd 12,x 08FB 6CE817 std 23,y 08FE ; task[id]->top_of_stack = malloc(task[id]->stack_size); 08FE E617 ldab -9,x 0900 87 clra 0901 59 lsld 0902 C30030 addd #_task 0905 B7C6 xgdy 0907 ED40 ldy 0,y 0909 6D15 sty -11,x 090B ED15 ldy -11,x 090D ECE817 ldd 23,y 0910 160000 jsr _malloc 0913 6CE1EC std -20,x 0916 ED15 ldy -11,x 0918 ECE1EC ldd -20,x 091B 6CE819 std 25,y 091E ; task[id]->top_of_stack += task[id]->stack_size; 091E E617 ldab -9,x 0920 87 clra 0921 59 lsld 0922 C30030 addd #_task 0925 B7C6 xgdy 0927 ED40 ldy 0,y 0929 6D13 sty -13,x 092B EC13 ldd -13,x 092D C30019 addd #25 0930 6C11 std -15,x 0932 ED13 ldy -13,x 0934 ECE817 ldd 23,y 0937 E3E3FFF1 addd [-15,x] 093B ED11 ldy -15,x 093D 6C40 std 0,y 093F ; task[id]->frame_ptr = NULL; 093F E617 ldab -9,x 0941 87 clra 0942 59 lsld 0943 C30030 addd #_task 0946 B7C6 xgdy 0948 ED40 ldy 0,y 094A CC0000 ldd #0 094D 6CE81B std 27,y 0950 ; 0950 ; } 0950 ; //} 0950 ; INTR_ON(); 0950 10EF cli 0952 0952 ; 0952 ; return id; 0952 E617 ldab -9,x 0954 87 clra 0955 L127: 0955 B757 tfr x,s 0957 30 pulx 0958 1B82 leas 2,sp 095A .dbline 0 ; func end 095A 3D rts 095B ; rid -> 3,x 095B _get_resource_state:: 095B 3B pshd 095C 34 pshx 095D B775 tfr s,x 095F ; 095F ; } 095F ; 095F ; 095F ; 095F ; 095F ; int get_resource_state(unsigned char rid) { 095F ; 095F ; if (rid < NUMRESOURCES) { 095F E603 ldab 3,x 0961 C104 cmpb #4 0963 2414 bhs L139 0965 ; return resource[rid].state; 0965 E603 ldab 3,x 0967 87 clra 0968 B7C6 xgdy 096A CC000C ldd #12 096D 1813 emuls 096F C30006 addd #_resource+6 0972 B7C6 xgdy 0974 E640 ldab 0,y 0976 87 clra 0977 2003 bra L138 0979 L139: 0979 ; } 0979 ; else { 0979 ; #ifdef KERNEL_ERROR_MSG 0979 ; puts(error_src[1]); puts(error_msg[6]); 0979 ; #endif 0979 ; return -1; 0979 CCFFFF ldd #-1 097C L138: 097C B757 tfr x,s 097E 30 pulx 097F 1B82 leas 2,sp 0981 .dbline 0 ; func end 0981 3D rts 0982 ; rid -> 3,x 0982 _get_resource_owner:: 0982 3B pshd 0983 34 pshx 0984 B775 tfr s,x 0986 ; } 0986 ; 0986 ; } 0986 ; 0986 ; 0986 ; 0986 ; 0986 ; 0986 ; int get_resource_owner(unsigned char rid) { 0986 ; 0986 ; if (rid < NUMRESOURCES) { 0986 E603 ldab 3,x 0988 C104 cmpb #4 098A 2414 bhs L143 098C ; return resource[rid].owner; 098C E603 ldab 3,x 098E 87 clra 098F B7C6 xgdy 0991 CC000C ldd #12 0994 1813 emuls 0996 C30007 addd #_resource+7 0999 B7C6 xgdy 099B E640 ldab 0,y 099D 87 clra 099E 2003 bra L142 09A0 L143: 09A0 ; } 09A0 ; else { 09A0 ; #ifdef KERNEL_ERROR_MSG 09A0 ; puts(error_src[1]); puts(error_msg[6]); 09A0 ; #endif 09A0 ; return -1; 09A0 CCFFFF ldd #-1 09A3 L142: 09A3 B757 tfr x,s 09A5 30 pulx 09A6 1B82 leas 2,sp 09A8 .dbline 0 ; func end 09A8 3D rts 09A9 ; rid -> 3,x 09A9 _get_resource_queuelen:: 09A9 3B pshd 09AA 34 pshx 09AB B775 tfr s,x 09AD ; } 09AD ; 09AD ; } 09AD ; 09AD ; 09AD ; 09AD ; 09AD ; int get_resource_queuelen(unsigned char rid) { 09AD ; 09AD ; if (rid < NUMRESOURCES) { 09AD E603 ldab 3,x 09AF C104 cmpb #4 09B1 2414 bhs L147 09B3 ; return resource[rid].queue_ptr; 09B3 E603 ldab 3,x 09B5 87 clra 09B6 B7C6 xgdy 09B8 CC000C ldd #12 09BB 1813 emuls 09BD C3000B addd #_resource+11 09C0 B7C6 xgdy 09C2 E640 ldab 0,y 09C4 87 clra 09C5 2003 bra L146 09C7 L147: 09C7 ; } 09C7 ; else { 09C7 ; #ifdef KERNEL_ERROR_MSG 09C7 ; puts(error_src[1]); puts(error_msg[6]); 09C7 ; #endif 09C7 ; return -1; 09C7 CCFFFF ldd #-1 09CA L146: 09CA B757 tfr x,s 09CC 30 pulx 09CD 1B82 leas 2,sp 09CF .dbline 0 ; func end 09CF 3D rts 09D0 ; last -> -6,x 09D0 ; memory -> -4,x 09D0 ; i -> -2,x 09D0 _get_free_memory:: 09D0 34 pshx 09D1 B775 tfr s,x 09D3 1B98 leas -8,sp 09D5 ; } 09D5 ; 09D5 ; } 09D5 ; 09D5 ; 09D5 ; 09D5 ; 09D5 ; int get_free_memory(void) { 09D5 ; 09D5 ; // LOCAL VARIABLES 09D5 ; char *memory, *last; 09D5 ; int i; 09D5 ; 09D5 ; 09D5 ; INTR_OFF(); 09D5 1410 sei 09D7 09D7 CC0000 ldd #0 09DA 6C1E std -2,x 09DC L151: 09DC ; // check for largest free memory block 09DC ; for (i=0; i -6,x 0A0B ; ?temp -> -4,x 0A0B ; ?temp -> -2,x 0A0B ; rid -> 3,x 0A0B _sem_get:: 0A0B 3B pshd 0A0C 34 pshx 0A0D B775 tfr s,x 0A0F 1B98 leas -8,sp 0A11 ; 0A11 ; } 0A11 ; 0A11 ; 0A11 ; 0A11 ; 0A11 ; int sem_get(char rid) { 0A11 ; 0A11 ; /* Gives a resource to a requesting task. 0A11 ; returns the resource id number (0,1,2,...) if free. 0A11 ; otherwise returns -1. 0A11 ; 0A11 ; At this point, semaphores are a procedural control 0A11 ; that the tasks have to follow to avoid resource contention. 0A11 ; There is no kernel control over resources yet. */ 0A11 ; 0A11 ; 0A11 ; // critical section 0A11 ; INTR_OFF(); 0A11 1410 sei 0A13 0A13 ; 0A13 ; 0A13 ; 0A13 ; // GET SEMAPHORE 0A13 ; // give semaphore to task 0A13 ; if (resource[rid].state == NOTBUSY) { 0A13 E603 ldab 3,x 0A15 87 clra 0A16 B7C6 xgdy 0A18 CC000C ldd #12 0A1B 1813 emuls 0A1D C30006 addd #_resource+6 0A20 B7C6 xgdy 0A22 E740 tst 0,y 0A24 2630 bne L158 0A26 ; resource[rid].state = BUSY; 0A26 E603 ldab 3,x 0A28 87 clra 0A29 B7C6 xgdy 0A2B CC000C ldd #12 0A2E 1813 emuls 0A30 C30006 addd #_resource+6 0A33 B7C6 xgdy 0A35 C601 ldab #1 0A37 6B40 stab 0,y 0A39 ; resource[rid].owner = current; 0A39 E603 ldab 3,x 0A3B 87 clra 0A3C B7C6 xgdy 0A3E CC000C ldd #12 0A41 1813 emuls 0A43 C30007 addd #_resource+7 0A46 B7C6 xgdy 0A48 FC0052 ldd _current 0A4B 6B40 stab 0,y 0A4D ; 0A4D ; INTR_ON(); 0A4D 10EF cli 0A4F 0A4F ; return rid; 0A4F E603 ldab 3,x 0A51 87 clra 0A52 18200084 lbra L157 0A56 L158: 0A56 ; } 0A56 ; 0A56 ; // resource is taken/busy so make task wait 0A56 ; else { 0A56 ; task[current]->message |= STATE_FLAG; 0A56 FC0052 ldd _current 0A59 59 lsld 0A5A C30030 addd #_task 0A5D B7C6 xgdy 0A5F EC40 ldd 0,y 0A61 C30014 addd #20 0A64 6C1E std -2,x 0A66 B746 tfr d,y 0A68 35 pshy ; spill 0A69 ED1E ldy -2,x 0A6B 31 puly ; reload 0A6C 0C4001 bset 0,y,#1 0A6F ; task[current]->message_data[STATE_BOX] = WAITING; 0A6F FC0052 ldd _current 0A72 59 lsld 0A73 C30030 addd #_task 0A76 B7C6 xgdy 0A78 ED40 ldy 0,y 0A7A C603 ldab #3 0A7C 6BE815 stab 21,y 0A7F ; 0A7F ; // put waiting task into the resources queue if there's space 0A7F ; if (resource[rid].queue_ptr < 3) { 0A7F E603 ldab 3,x 0A81 87 clra 0A82 B7C6 xgdy 0A84 CC000C ldd #12 0A87 1813 emuls 0A89 C3000B addd #_resource+11 0A8C B7C6 xgdy 0A8E E640 ldab 0,y 0A90 C103 cmpb #3 0A92 2441 bhs L163 0A94 ; resource[rid].queue[resource[rid].queue_ptr] = current; 0A94 E603 ldab 3,x 0A96 87 clra 0A97 B7C6 xgdy 0A99 CC000C ldd #12 0A9C 1813 emuls 0A9E 6C1C std -4,x 0AA0 C3000B addd #_resource+11 0AA3 B7C6 xgdy 0AA5 E640 ldab 0,y 0AA7 87 clra 0AA8 3B pshd ; spill 0AA9 EC1C ldd -4,x 0AAB C30008 addd #_resource+8 0AAE 6C18 std -8,x 0AB0 3A puld ; reload 0AB1 E318 addd -8,x 0AB3 B7C6 xgdy 0AB5 F60053 ldab _current+1 0AB8 6B40 stab 0,y 0ABA ; resource[rid].queue_ptr++; 0ABA E603 ldab 3,x 0ABC 87 clra 0ABD B7C6 xgdy 0ABF CC000C ldd #12 0AC2 1813 emuls 0AC4 C3000B addd #_resource+11 0AC7 6C1A std -6,x 0AC9 B746 tfr d,y 0ACB E640 ldab 0,y 0ACD 87 clra 0ACE C30001 addd #1 0AD1 ED1A ldy -6,x 0AD3 6B40 stab 0,y 0AD5 ; } 0AD5 L163: 0AD5 ; 0AD5 ; INTR_ON(); 0AD5 10EF cli 0AD7 0AD7 ; return -1; 0AD7 CCFFFF ldd #-1 0ADA L157: 0ADA B757 tfr x,s 0ADC 30 pulx 0ADD 1B82 leas 2,sp 0ADF .dbline 0 ; func end 0ADF 3D rts 0AE0 ; rid -> 3,x 0AE0 _sem_give:: 0AE0 3B pshd 0AE1 34 pshx 0AE2 B775 tfr s,x 0AE4 ; } 0AE4 ; 0AE4 ; } 0AE4 ; 0AE4 ; 0AE4 ; 0AE4 ; 0AE4 ; int sem_give(char rid) { 0AE4 ; 0AE4 ; /* Takes a resource back from a task. 0AE4 ; will (eventually) pass a message to a waiting task. 0AE4 ; 0AE4 ; At this point, semaphores are a procedural control 0AE4 ; that the tasks have to follow to avoid resource contention. 0AE4 ; There is no kernel control over resources yet. */ 0AE4 ; 0AE4 ; 0AE4 ; // critical section 0AE4 ; INTR_OFF(); 0AE4 1410 sei 0AE6 0AE6 ; 0AE6 ; 0AE6 ; // return the resource 0AE6 ; resource[rid].state = NOTBUSY; 0AE6 E603 ldab 3,x 0AE8 87 clra 0AE9 B7C6 xgdy 0AEB CC000C ldd #12 0AEE 1813 emuls 0AF0 C30006 addd #_resource+6 0AF3 B7C6 xgdy 0AF5 6940 clr 0,y 0AF7 ; //resource[rid].owner = NULL; 0AF7 ; 0AF7 ; INTR_ON(); 0AF7 10EF cli 0AF9 0AF9 ; 0AF9 ; return 0; 0AF9 CC0000 ldd #0 0AFC L169: 0AFC B757 tfr x,s 0AFE 30 pulx 0AFF 1B82 leas 2,sp 0B01 .dbline 0 ; func end 0B01 3D rts .area bss 0000 _resource:: 0000 .blkb 48 0030 _task:: 0030 .blkb 16 0040 _last_time_mark:: 0040 .blkb 4 0044 _delta_t:: 0044 .blkb 4 0048 _time_tick:: 0048 .blkb 4 004C _cop_cycle:: 004C .blkb 2 004E _system_tick:: 004E .blkb 4 0052 _current:: 0052 .blkb 2 0054 _task_ptr:: 0054 .blkb 16 .area text 0B02 L66: 0B02 00000001 .word 0,1 0B06 L64: 0B06 4B45524E454C3A207461736B20737461 .byte 'K,'E,'R,'N,'E,'L,58,32,'t,'a,'s,'k,32,'s,'t,'a 0B16 7465206572726F720A00 .byte 't,'e,32,'e,'r,'r,'o,'r,10,0 0B20 L21: 0B20 726C704F532076302E370A0A00 .byte 'r,'l,'p,'O,'S,32,'v,48,46,55,10,10,0 0B2D L20: 0B2D 00000000 .word 0,0 0B31 L19: 0B31 7368656C6C206661696C75726500 .byte 's,'h,'e,'l,'l,32,'f,'a,'i,'l,'u,'r,'e,0 0B3F L18: 0B3F 7368656C6C00 .byte 's,'h,'e,'l,'l,0 0B45 L15: 0B45 737973496E6974206661696C75726500 .byte 's,'y,'s,'I,'n,'i,'t,32,'f,'a,'i,'l,'u,'r,'e,0 0B55 L14: 0B55 737973496E697400 .byte 's,'y,'s,'I,'n,'i,'t,0