.module rlpos.c .area data 0200 _task_ptr:: 0200 .blkw 1 .area idata --- 0000 0000 .word _shell .area data --- 0002 .blkw 1 .area idata --- 0002 0000 .word _task1 .area data --- 0004 .blkw 1 .area idata --- 0004 0000 .word _task2 .area data 0206 _main_frame_ptr:: 0206 .blkb 2 .area idata --- 0006 0000 .word 0 .area data 0208 _main_frame_x_ptr:: 0208 .blkb 2 .area idata --- 0008 0000 .word 0 .area data 020A _temp_task_frame_ptr:: 020A .blkb 2 .area idata --- 000A 0000 .word 0 .area data .area text ; lreg1 -> -4,x ; lreg2 -> -8,x ; ?temp -> -23,x ; result -> -21,x ; temp_heap_ptr -> -19,x ; last_task -> -17,x ; temp -> -15,x ; temp_heap_size -> -14,x ; next_task -> -12,x ; i -> -10,x 102A _main:: 102A 34 pshx 102B B775 tfr s,x 102D 1BF1E2 leas -30,sp 1030 ; /* RLPOS: RLPotter Operating System 1030 ; 1030 ; Version 0.3 for the 68HC12D60A microcontroller 1030 ; by Ryan Potter 1030 ; ryan@rlpotter.com 1030 ; 1030 ; 1030 ; v0.3 April 12, 2003: 1030 ; - added a beginning shell user interface. 1030 ; - added a resource control block and semaphore functions. 1030 ; - added basic kernel functions 1030 ; v0.2 April 9, 2003: 1030 ; - able to round-robin with RTI interrupt. 1030 ; - bonified/certified multitasking with 3 tasks. :) 1030 ; v0.1 April 3, 2003: 1030 ; - able to round-robin without interrupts. 1030 ; - not multitasking, really. 1030 ; v0.0 started April 1, 2003; 1030 ; - no idea where to start. 1030 ; - don't want to look at anyone else's work. ;0) 1030 ; 1030 ; 1030 ; 1030 ; 1030 ; Architecture/C assumptions: 1030 ; 1) 'D' register is the accumulator 1030 ; 2) 'X' register points to the top of the current stack 1030 ; 3) 'Y' register is for general use in indexed operations 1030 ; 4) the heap grows upward and mem segments allocated by malloc, 1030 ; realloc, and calloc are linear and contiguous. 1030 ; 1030 ; Potential problem areas: 1030 ; 1) 'running' section of the kernel get's compiled using extra 1030 ; push and pop instructions 1030 ; 2) run out of ram (global + stack + heap) 1030 ; 3) kernel takes up too large a fraction of the processing time 1030 ; */ 1030 ; 1030 ; 1030 ; 1030 ; #include <912d60.h> 1030 ; #include 1030 ; #include 1030 ; #include "kernel.h" 1030 ; 1030 ; 1030 ; 1030 ; 1030 ; // FUNCTION PROTOTYPES 1030 ; void RTI_handler(void); 1030 ; void shell(void); 1030 ; void task1(void); 1030 ; void task2(void); 1030 ; void (*task_ptr[])(void) = {&shell, &task1, &task2}; 1030 ; 1030 ; 1030 ; 1030 ; 1030 ; // GLOBAL VARIABLES 1030 ; unsigned char *main_frame_ptr = NULL; // bottom of main() frame 1030 ; unsigned char *main_frame_x_ptr = NULL; // top of main() frame (x-reg ptr) 1030 ; unsigned char *temp_task_frame_ptr = NULL; // temp CCR pointer for RTI 1030 ; 1030 ; 1030 ; extern unsigned int current; // current task id number 1030 ; extern unsigned long int system_tick; 1030 ; 1030 ; 1030 ; // task control block 1030 ; extern struct task_block { 1030 ; unsigned char id; // ID of task 1030 ; enum task_state state; // State 1030 ; unsigned char priority; // Priority 1030 ; unsigned char *heap_ptr; // heap addr while not current task 1030 ; unsigned int heap_size; // heap size 1030 ; unsigned char *frame_ptr; // CCR pointer 1030 ; }; 1030 ; 1030 ; 1030 ; // resource control block 1030 ; extern struct resource_block { 1030 ; unsigned char id; // ID of resource 1030 ; enum resource_state state; // State (busy, free...) 1030 ; unsigned char user; // Current resource user/owner 1030 ; signed char queue[4]; // Tasks waiting on resource 1030 ; unsigned char queue_pos; // Next free spot in queue 1030 ; }; 1030 ; 1030 ; 1030 ; extern struct task_block task[numtasks]; 1030 ; extern struct resource_block resource[numresources]; 1030 ; 1030 ; 1030 ; 1030 ; 1030 ; 1030 ; 1030 ; main() { 1030 ; 1030 ; // LOCAL VARIABLES 1030 ; int result; 1030 ; unsigned int i, temp_heap_size; 1030 ; unsigned int last_task = 0; 1030 CC0000 ldd #0 1033 6CE1EF std -17,x 1036 ; unsigned int next_task = 0; 1036 CC0000 ldd #0 1039 6C14 std -12,x 103B ; unsigned char *temp_heap_ptr, temp; 103B ; 103B ; 103B ; // INITIALIZE GLOBAL VARIABLES 103B ; extern int _bss_end, _textmode; 103B ; extern unsigned int current; 103B ; extern unsigned long int system_tick; 103B ; 103B ; 103B ; _textmode = 1; 103B CC0001 ldd #1 103E 7C023D std __textmode 1041 ; current = 0; 1041 CC0000 ldd #0 1044 7C023B std _current 1047 ; system_tick = 0; 1047 CD137F ldy #L4 104A 1802401C movw 0,y,-4,x 104E 1802421E movw 2,y,-2,x 1052 CD0237 ldy #_system_tick 1055 18021C40 movw -4,x,0,y 1059 18021E42 movw -2,x,2,y 105D CC0000 ldd #0 1060 6C16 std -10,x 1062 2064 bra L8 1064 L5: 1064 CC0009 ldd #9 1067 ED16 ldy -10,x 1069 13 emul 106A C3021C addd #_task 106D B7C6 xgdy 106F EC16 ldd -10,x 1071 6B40 stab 0,y 1073 CC0009 ldd #9 1076 ED16 ldy -10,x 1078 13 emul 1079 C3021D addd #_task+1 107C B7C6 xgdy 107E C604 ldab #4 1080 6B40 stab 0,y 1082 CC0009 ldd #9 1085 ED16 ldy -10,x 1087 13 emul 1088 C3021E addd #_task+2 108B B7C6 xgdy 108D C6FF ldab #255 108F 6B40 stab 0,y 1091 CC0009 ldd #9 1094 ED16 ldy -10,x 1096 13 emul 1097 C3021F addd #_task+3 109A B7C6 xgdy 109C CC0000 ldd #0 109F 6C40 std 0,y 10A1 CC0009 ldd #9 10A4 ED16 ldy -10,x 10A6 13 emul 10A7 C30221 addd #_task+5 10AA B7C6 xgdy 10AC CC0000 ldd #0 10AF 6C40 std 0,y 10B1 CC0009 ldd #9 10B4 ED16 ldy -10,x 10B6 13 emul 10B7 C30223 addd #_task+7 10BA B7C6 xgdy 10BC CC0000 ldd #0 10BF 6C40 std 0,y 10C1 L6: 10C1 EC16 ldd -10,x 10C3 C30001 addd #1 10C6 6C16 std -10,x 10C8 L8: 10C8 ; 10C8 ; 10C8 ; // initialize the task structures 10C8 ; for (i=0; i= numtasks) 124D EC14 ldd -12,x 124F 8C0003 cpd #3 1252 2505 blo L49 1254 ; next_task = 0; 1254 CC0000 ldd #0 1257 6C14 std -12,x 1259 L49: 1259 L24: 1259 1820FED9 lbra L23 125D X2: 125D ; 125D ; 125D ; 125D ; // diagnostic 125D ; //putchar(':'); 125D ; 125D ; } // end 'while(1)' 125D ; 125D ; return 0; 125D CC0000 ldd #0 1260 L3: 1260 B757 tfr x,s 1262 30 pulx 1263 .dbline 0 ; func end 1263 3D rts 1264 ; lreg1 -> -4,x 1264 ; lreg2 -> -8,x 1264 ; ?temp -> -16,x 1264 ; local_thp -> -14,x 1264 ; frame_size -> -12,x 1264 ; i -> -10,x 1264 _RTI_handler:: 1264 34 pshx 1265 B775 tfr s,x 1267 1BF1EC leas -20,sp 126A ; } 126A ; 126A ; 126A ; 126A ; #pragma interrupt_handler RTI_handler() 126A ; 126A ; void RTI_handler(void) { 126A ; 126A ; size_t frame_size; 126A ; unsigned int i; 126A ; unsigned char *local_thp; 126A ; 126A ; 126A ; //ACKNOWLEDGE THE INTERRUPT 126A ; INTR_OFF(); // redundant. automatically done by the processor 126A 1410 sei 126C 126C ; RTIFLG = 0x0080; // acknowledge/clear the interrupt 126C C680 ldab #128 126E 7B0015 stab 0x15 1271 ; 1271 ; 1271 ; 1271 ; //putchar('I'); 1271 ; //putchar(current + 48); 1271 ; //putchar('('); 1271 ; 1271 ; 1271 ; 1271 ; // SET THE FRAME POINTER for the interupted task. 1271 ; // should point to the CCR entry on the stack. 1271 ; asm("TFR x,d"); // start of RTI stack 1271 B754 TFR x,d 1273 1273 ; asm("ADDD #2"); // adjust to CCR stack entry 1273 C30002 ADDD #2 1276 1276 ; asm("STD _temp_task_frame_ptr"); // put into task_frame_ptr 1276 7C020A STD _temp_task_frame_ptr 1279 1279 ; task[current].frame_ptr = temp_task_frame_ptr; 1279 CC0009 ldd #9 127C FD023B ldy _current 127F 13 emul 1280 C30223 addd #_task+7 1283 B7C6 xgdy 1285 FC020A ldd _temp_task_frame_ptr 1288 6C40 std 0,y 128A ; 128A ; 128A ; 128A ; //PLACE CURRENT TASK CONTEXT ONTO THE HEAP 128A ; // determine size of heap segment needed 128A ; frame_size = main_frame_ptr - temp_task_frame_ptr; // always positive 128A FC0206 ldd _main_frame_ptr 128D B3020A subd _temp_task_frame_ptr 1290 6C14 std -12,x 1292 ; task[current].heap_size = (int)frame_size; 1292 CC0009 ldd #9 1295 FD023B ldy _current 1298 13 emul 1299 C30221 addd #_task+5 129C B7C6 xgdy 129E EC14 ldd -12,x 12A0 6C40 std 0,y 12A2 ; 12A2 ; // reallocate heap memory 12A2 ; task[current].heap_ptr = realloc(task[current].heap_ptr, frame_size); 12A2 18021480 movw -12,x,0,sp 12A6 CC0009 ldd #9 12A9 FD023B ldy _current 12AC 13 emul 12AD 6C10 std -16,x 12AF C3021F addd #_task+3 12B2 B7C6 xgdy 12B4 EC40 ldd 0,y 12B6 162606 jsr _realloc 12B9 6CE1EE std -18,x 12BC EC10 ldd -16,x 12BE C3021F addd #_task+3 12C1 B7C6 xgdy 12C3 ECE1EE ldd -18,x 12C6 6C40 std 0,y 12C8 ; local_thp = task[current].heap_ptr; 12C8 CC0009 ldd #9 12CB FD023B ldy _current 12CE 13 emul 12CF C3021F addd #_task+3 12D2 B7C6 xgdy 12D4 ED40 ldy 0,y 12D6 6D12 sty -14,x 12D8 ; 12D8 ; if (local_thp == NULL) { 12D8 EC12 ldd -14,x 12DA 260C bne L57 12DC ; puts("out of heap space!"); 12DC CC1344 ldd #L59 12DF 1622ED jsr _puts 12E2 ; exit(0); 12E2 CC0000 ldd #0 12E5 161028 jsr _exit 12E8 ; } 12E8 L57: 12E8 CC0000 ldd #0 12EB 6C16 std -10,x 12ED 201A bra L63 12EF L60: 12EF EC16 ldd -10,x 12F1 F3020A addd _temp_task_frame_ptr 12F4 B7C6 xgdy 12F6 E640 ldab 0,y 12F8 3B pshd ; spill 12F9 EC16 ldd -10,x 12FB E312 addd -14,x 12FD B7C6 xgdy 12FF 3A puld ; reload 1300 6B40 stab 0,y 1302 L61: 1302 EC16 ldd -10,x 1304 C30001 addd #1 1307 6C16 std -10,x 1309 L63: 1309 ; 1309 ; // transfer task frame to the heap one byte at a time. 1309 ; // assumes the heap grows from low to high addr. 1309 ; for(i=0; i -37,x ; j -> -36,x ; cmd -> -35,x ; command -> -33,x ; i -> -1,x 1383 _shell:: 1383 34 pshx 1384 B775 tfr s,x 1386 1BF1D6 leas -42,sp 1389 ; // shell.c 1389 ; 1389 ; 1389 ; #include <912d60.h> 1389 ; #include 1389 ; #include 1389 ; #include "kernel.h" 1389 ; #include "semlib.h" 1389 ; 1389 ; 1389 ; 1389 ; 1389 ; // FUNCTION PROTOTYPES 1389 ; void shellcmd_tcb(void); 1389 ; void shellcmd_rcb(void); 1389 ; void shellcmd_ticks(void); 1389 ; void shellcmd_start_task(unsigned char id); 1389 ; 1389 ; /*void shellcmd_stop_task(unsigned char id); 1389 ; void shellcmd_set_task_priority(unsigned char id, unsigned char priority); 1389 ; void shellcmd_quit_shell(void);*/ 1389 ; 1389 ; 1389 ; 1389 ; 1389 ; // GLOBAL VARIABLES 1389 ; extern unsigned long int system_tick; 1389 ; extern unsigned int current; // current task id number 1389 ; 1389 ; 1389 ; 1389 ; 1389 ; 1389 ; void shell(void) { 1389 ; 1389 ; // LOCAL VARIABLES 1389 ; char command[32], i, j; 1389 ; int cmd; 1389 ; 1389 ; 1389 ; 1389 ; // INITIALIZE 1389 ; sem_get(COM1); // get comm port 1 semaphore 1389 CC0000 ldd #0 138C 1616A3 jsr _sem_get 138F ; INTR_ON(); // enable interrupts 138F 10EF cli 1391 1391 18200121 lbra L5 1395 L4: 1395 ; 1395 ; 1395 ; 1395 ; // COMMAND SHELL 1395 ; while (1) { 1395 ; 1395 ; i = 0; 1395 691F clr -1,x 1397 ; 1397 ; // put a prompt 1397 ; putchar('>'); putchar('>'); putchar(' '); 1397 CC003E ldd #62 139A 161DD2 jsr _putchar 139D CC003E ldd #62 13A0 161DD2 jsr _putchar 13A3 CC0020 ldd #32 13A6 161DD2 jsr _putchar 13A9 2056 bra L8 13AB L7: 13AB ; 13AB ; 13AB ; // get and echo a command 13AB ; while (((command[i]=getchar()) != 0xD) && (i<7)) { 13AB ; putchar(command[i]); 13AB 19E1DF leay -33,x 13AE 6DE1D8 sty -40,x 13B1 E61F ldab -1,x 13B3 87 clra 13B4 E3E1D8 addd -40,x 13B7 B7C6 xgdy 13B9 E640 ldab 0,y 13BB 87 clra 13BC 161DD2 jsr _putchar 13BF ; 13BF ; if (command[i] == 8) { 13BF 19E1DF leay -33,x 13C2 6DE1D8 sty -40,x 13C5 E61F ldab -1,x 13C7 87 clra 13C8 E3E1D8 addd -40,x 13CB B7C6 xgdy 13CD E640 ldab 0,y 13CF C108 cmpb #8 13D1 2626 bne L10 13D3 ; putchar(32); // space 13D3 CC0020 ldd #32 13D6 161DD2 jsr _putchar 13D9 ; putchar(8); // backspace 13D9 CC0008 ldd #8 13DC 161DD2 jsr _putchar 13DF ; command[i] = '\0'; // null 13DF 19E1DF leay -33,x 13E2 6DE1D8 sty -40,x 13E5 E61F ldab -1,x 13E7 87 clra 13E8 E3E1D8 addd -40,x 13EB B7C6 xgdy 13ED 6940 clr 0,y 13EF ; i--; 13EF E61F ldab -1,x 13F1 87 clra 13F2 830001 subd #1 13F5 6B1F stab -1,x 13F7 ; } else 13F7 2008 bra L11 13F9 L10: 13F9 ; i++; 13F9 E61F ldab -1,x 13FB 87 clra 13FC C30001 addd #1 13FF 6B1F stab -1,x 1401 L11: 1401 L8: 1401 161DFA jsr _getchar 1404 6BE1DB stab -37,x 1407 19E1DF leay -33,x 140A 6DE1D8 sty -40,x 140D E61F ldab -1,x 140F 87 clra 1410 E3E1D8 addd -40,x 1413 B7C6 xgdy 1415 E6E1DB ldab -37,x 1418 6B40 stab 0,y 141A E6E1DB ldab -37,x 141D C10D cmpb #13 141F 2708 beq L12 1421 E61F ldab -1,x 1423 C107 cmpb #7 1425 1825FF82 lblo L7 1429 L12: 1429 ; } 1429 ; command[i] = '\0'; 1429 19E1DF leay -33,x 142C 6DE1D8 sty -40,x 142F E61F ldab -1,x 1431 87 clra 1432 E3E1D8 addd -40,x 1435 B7C6 xgdy 1437 6940 clr 0,y 1439 ; putchar('\n'); 1439 CC000A ldd #10 143C 161DD2 jsr _putchar 143F ; 143F ; 143F ; 143F ; // determine/execute the command 143F ; if (command[0] == 0xD) // CR 143F E6E1DF ldab -33,x 1442 C10D cmpb #13 1444 2608 bne L13 1446 ; cmd = 0; 1446 CC0000 ldd #0 1449 6CE1DD std -35,x 144C 2062 bra L14 144E L13: 144E ; else if (strcmp(command, "tcb") == 0) 144E CC1618 ldd #L17 1451 6C80 std 0,sp 1453 19E1DF leay -33,x 1456 B7C6 xgdy 1458 162274 jsr _strcmp 145B 8C0000 cpd #0 145E 2605 bne L15 1460 ; shellcmd_tcb(); 1460 1614C6 jsr _shellcmd_tcb 1463 204B bra L16 1465 L15: 1465 ; else if (strcmp(command, "ticks") == 0) 1465 CC1612 ldd #L20 1468 6C80 std 0,sp 146A 19E1DF leay -33,x 146D B7C6 xgdy 146F 162274 jsr _strcmp 1472 8C0000 cpd #0 1475 2605 bne L18 1477 ; shellcmd_ticks(); 1477 16151E jsr _shellcmd_ticks 147A 2034 bra L19 147C L18: 147C ; else if (strcmp(command, "start") == 0) 147C CC160C ldd #L23 147F 6C80 std 0,sp 1481 19E1DF leay -33,x 1484 B7C6 xgdy 1486 162274 jsr _strcmp 1489 8C0000 cpd #0 148C 2608 bne L21 148E ; shellcmd_start_task(2); 148E CC0002 ldd #2 1491 16154C jsr _shellcmd_start_task 1494 201A bra L22 1496 L21: 1496 ; else if (strcmp(command, "") == 0); 1496 CC160B ldd #L26 1499 6C80 std 0,sp 149B 19E1DF leay -33,x 149E B7C6 xgdy 14A0 162274 jsr _strcmp 14A3 8C0000 cpd #0 14A6 2602 bne L24 14A8 2006 bra L25 14AA L24: 14AA ; else 14AA ; puts("syntax error"); putchar('\n'); 14AA CC15FE ldd #L27 14AD 1622ED jsr _puts 14B0 L25: 14B0 L22: 14B0 L19: 14B0 L16: 14B0 L14: 14B0 CC000A ldd #10 14B3 161DD2 jsr _putchar 14B6 L5: 14B6 1820FEDB lbra L4 14BA X0: 14BA ; 14BA ; 14BA ; } // end while(1) 14BA ; 14BA ; INTR_OFF(); 14BA 1410 sei 14BC 14BC ; sem_give(COM1); 14BC CC0000 ldd #0 14BF 16171C jsr _sem_give 14C2 ; 14C2 ; } 14C2 L3: 14C2 B757 tfr x,s 14C4 30 pulx 14C5 .dbline 0 ; func end 14C5 3D rts 14C6 ; id -> -2,x 14C6 _shellcmd_tcb:: 14C6 34 pshx 14C7 B775 tfr s,x 14C9 1B96 leas -10,sp 14CB ; 14CB ; 14CB ; 14CB ; 14CB ; void shellcmd_tcb(void) { 14CB CC0000 ldd #0 14CE 6C1E std -2,x 14D0 L29: 14D0 CC15DD ldd #L33 14D3 1622ED jsr _puts 14D6 1410 sei 14D8 14D8 EC1E ldd -2,x 14DA 87 clra 14DB 161747 jsr _get_task_state 14DE 6C1C std -4,x 14E0 EC1E ldd -2,x 14E2 87 clra 14E3 161763 jsr _get_task_priority 14E6 87 clra 14E7 6C84 std 4,sp 14E9 EC1C ldd -4,x 14EB 87 clra 14EC 6C82 std 2,sp 14EE 18021E80 movw -2,x,0,sp 14F2 CC15BA ldd #L34 14F5 162325 jsr _printf 14F8 L30: 14F8 ; 14F8 ; // LOCAL VARIABLES 14F8 ; int id; 14F8 ; 14F8 ; 14F8 ; for (id=0; id<3; id++) { 14F8 EC1E ldd -2,x 14FA C30001 addd #1 14FD 6C1E std -2,x 14FF EC1E ldd -2,x 1501 8C0003 cpd #3 1504 2DCA blt L29 1506 ; puts ("----------+----------+---------+"); 1506 ; 1506 ; /* this takes a while, so treat as a critical section in order 1506 ; to get reliable data */ 1506 ; INTR_OFF(); 1506 ; 1506 ; printf("TaskID: %d | State: %d | Prio: %d\n", id, 1506 ; get_task_state(id), 1506 ; get_task_priority(id)); 1506 ; } // end for loop 1506 ; 1506 ; // finished with critical section 1506 ; INTR_ON(); 1506 10EF cli 1508 1508 ; 1508 ; puts ("----------+----------+---------+"); 1508 CC15DD ldd #L33 150B 1622ED jsr _puts 150E ; puts("Idle=0, Pending=1, Running=2, Waiting=3, Finished=4"); 150E CC1586 ldd #L35 1511 1622ED jsr _puts 1514 ; putchar('\n'); 1514 CC000A ldd #10 1517 161DD2 jsr _putchar 151A ; 151A ; 151A ; } 151A L28: 151A B757 tfr x,s 151C 30 pulx 151D .dbline 0 ; func end 151D 3D rts 151E ; lreg1 -> -4,x 151E ; lreg2 -> -8,x 151E _shellcmd_ticks:: 151E 34 pshx 151F B775 tfr s,x 1521 1B94 leas -12,sp 1523 ; 1523 ; 1523 ; 1523 ; 1523 ; void shellcmd_ticks(void) { 1523 ; 1523 ; INTR_OFF(); 1523 1410 sei 1525 1525 ; printf("Ticks: %ld\n", system_tick); 1525 CD0237 ldy #_system_tick 1528 1802401C movw 0,y,-4,x 152C 1802421E movw 2,y,-2,x 1530 1980 leay 0,sp 1532 18021C40 movw -4,x,0,y 1536 18021E42 movw -2,x,2,y 153A CC157A ldd #L37 153D 162325 jsr _printf 1540 ; INTR_ON(); 1540 10EF cli 1542 1542 ; putchar('\n'); 1542 CC000A ldd #10 1545 161DD2 jsr _putchar 1548 ; } 1548 L36: 1548 B757 tfr x,s 154A 30 pulx 154B .dbline 0 ; func end 154B 3D rts 154C ; id -> 3,x 154C _shellcmd_start_task:: 154C 3B pshd 154D 34 pshx 154E B775 tfr s,x 1550 1B9E leas -2,sp 1552 ; 1552 ; 1552 ; 1552 ; 1552 ; void shellcmd_start_task(unsigned char id) { 1552 ; 1552 ; INTR_OFF(); 1552 1410 sei 1554 1554 ; set_task_state(id, 1); 1554 CC0001 ldd #1 1557 6C80 std 0,sp 1559 E603 ldab 3,x 155B 87 clra 155C 16177F jsr _set_task_state 155F ; INTR_ON(); 155F 10EF cli 1561 1561 ; puts("task started"); 1561 CC156D ldd #L39 1564 1622ED jsr _puts 1567 ; } 1567 L38: 1567 B757 tfr x,s 1569 30 pulx 156A 1B82 leas 2,sp 156C .dbline 0 ; func end 156C 3D rts 156D L39: 156D 7461736B207374617274656400 .byte 't,'a,'s,'k,32,'s,'t,'a,'r,'t,'e,'d,0 157A L37: 157A 5469636B733A20256C640A00 .byte 'T,'i,'c,'k,'s,58,32,37,'l,'d,10,0 1586 L35: 1586 49646C653D302C2050656E64696E673D .byte 'I,'d,'l,'e,61,48,44,32,'P,'e,'n,'d,'i,'n,'g,61 1596 312C2052756E6E696E673D322C205761 .byte 49,44,32,'R,'u,'n,'n,'i,'n,'g,61,50,44,32,'W,'a 15A6 6974696E673D332C2046696E69736865 .byte 'i,'t,'i,'n,'g,61,51,44,32,'F,'i,'n,'i,'s,'h,'e 15B6 643D3400 .byte 'd,61,52,0 15BA L34: 15BA 5461736B49443A202564207C20537461 .byte 'T,'a,'s,'k,'I,'D,58,32,37,'d,32,124,32,'S,'t,'a 15CA 74653A202564207C205072696F3A2025 .byte 't,'e,58,32,37,'d,32,124,32,'P,'r,'i,'o,58,32,37 15DA 640A00 .byte 'd,10,0 15DD L33: 15DD 2D2D2D2D2D2D2D2D2D2D2B2D2D2D2D2D .byte 45,45,45,45,45,45,45,45,45,45,43,45,45,45,45,45 15ED 2D2D2D2D2D2B2D2D2D2D2D2D2D2D2D2B .byte 45,45,45,45,45,43,45,45,45,45,45,45,45,45,45,43 15FD 00 .byte 0 15FE L27: 15FE 73796E746178206572726F7200 .byte 's,'y,'n,'t,'a,'x,32,'e,'r,'r,'o,'r,0 160B L26: 160B 00 .byte 0 160C L23: 160C 737461727400 .byte 's,'t,'a,'r,'t,0 1612 L20: 1612 7469636B7300 .byte 't,'i,'c,'k,'s,0 1618 L17: 1618 74636200 .byte 't,'c,'b,0 .module task1.c .area text ; i -> -2,x 161C _task1:: 161C 34 pshx 161D B775 tfr s,x 161F 1B9E leas -2,sp 1621 ; #include 1621 ; #include <912d60.h> 1621 ; #include "semlib.h" 1621 ; 1621 ; 1621 ; 1621 ; /* dummy task to eat up time, and to give the kernel 1621 ; something to multitask with */ 1621 ; void task1 (void) { 1621 ; 1621 ; int i; 1621 ; 1621 ; sem_get(COM1); 1621 CC0000 ldd #0 1624 1616A3 jsr _sem_get 1627 ; INTR_ON(); 1627 10EF cli 1629 1629 CC0000 ldd #0 162C 6C1E std -2,x 162E L4: 162E L5: 162E ; 162E ; 162E ; //puts("T1 Starting"); 162E ; for (i=0; i<0x1800; i++); 162E EC1E ldd -2,x 1630 C30001 addd #1 1633 6C1E std -2,x 1635 EC1E ldd -2,x 1637 8C1800 cpd #6144 163A 2DF2 blt L4 163C CC0000 ldd #0 163F 6C1E std -2,x 1641 L8: 1641 L9: 1641 ; //puts("T1.1"); 1641 ; 1641 ; for (i=0; i<0x1A00; i++); 1641 EC1E ldd -2,x 1643 C30001 addd #1 1646 6C1E std -2,x 1648 EC1E ldd -2,x 164A 8C1A00 cpd #6656 164D 2DF2 blt L8 164F CC0000 ldd #0 1652 6C1E std -2,x 1654 L12: 1654 L13: 1654 ; //puts("T1.2"); 1654 ; 1654 ; for (i=0; i<0x2C00; i++); 1654 EC1E ldd -2,x 1656 C30001 addd #1 1659 6C1E std -2,x 165B EC1E ldd -2,x 165D 8C2C00 cpd #11264 1660 2DF2 blt L12 1662 CC0000 ldd #0 1665 6C1E std -2,x 1667 L16: 1667 L17: 1667 ; //puts("T1.3"); 1667 ; 1667 ; for (i=0; i<0x2E00; i++); 1667 EC1E ldd -2,x 1669 C30001 addd #1 166C 6C1E std -2,x 166E EC1E ldd -2,x 1670 8C2E00 cpd #11776 1673 2DF2 blt L16 1675 ; //puts("T1 Finished"); 1675 ; 1675 ; //puts("-T1-"); 1675 ; 1675 ; 1675 ; INTR_OFF(); 1675 1410 sei 1677 1677 ; sem_give(COM1); 1677 CC0000 ldd #0 167A 16171C jsr _sem_give 167D ; 167D ; } 167D L3: 167D B757 tfr x,s 167F 30 pulx 1680 .dbline 0 ; func end 1680 3D rts .module task2.c .area text ; i -> -2,x 1681 _task2:: 1681 34 pshx 1682 B775 tfr s,x 1684 1B9E leas -2,sp 1686 ; #include 1686 ; #include <912d60.h> 1686 ; #include "kernel.h" 1686 ; 1686 ; 1686 ; 1686 ; /* dummy task to eat up time, and to give the kernel 1686 ; something to multitask with */ 1686 ; void task2 (void) { 1686 ; 1686 ; int i; 1686 ; 1686 ; INTR_ON(); 1686 10EF cli 1688 1688 CC0000 ldd #0 168B 6C1E std -2,x 168D 2007 bra L7 168F L4: 168F L5: 168F EC1E ldd -2,x 1691 C30001 addd #1 1694 6C1E std -2,x 1696 L7: 1696 ; 1696 ; for (i=0; i<0xA000; i++); 1696 EC1E ldd -2,x 1698 8CA000 cpd #0xa000 169B 25F2 blo L4 169D ; //puts("-T2-"); 169D ; 169D ; INTR_OFF(); 169D 1410 sei 169F 169F ; 169F ; } 169F L3: 169F B757 tfr x,s 16A1 30 pulx 16A2 .dbline 0 ; func end 16A2 3D rts .module vectors.c .area memory(abs) .org 0xffd0 FFD0 _interrupt_vectors:: FFD0 FFFF .word 65535 FFD2 FFFF .word 65535 FFD4 FFFF .word 65535 FFD6 FFFF .word 65535 FFD8 FFFF .word 65535 FFDA FFFF .word 65535 FFDC FFFF .word 65535 FFDE FFFF .word 65535 FFE0 FFFF .word 65535 FFE2 FFFF .word 65535 FFE4 FFFF .word 65535 FFE6 FFFF .word 65535 FFE8 FFFF .word 65535 FFEA FFFF .word 65535 FFEC FFFF .word 65535 FFEE FFFF .word 65535 FFF0 1264 .word _RTI_handler FFF2 FFFF .word 65535 FFF4 FFFF .word 65535 FFF6 FFFF .word 65535 FFF8 FFFF .word 65535 FFFA FFFF .word 65535 FFFC FFFF .word 65535 FFFE 1000 .word __start .area data .module semlib.c .area text ; resource_id -> 3,x 16A3 _sem_get:: 16A3 3B pshd 16A4 34 pshx 16A5 B775 tfr s,x 16A7 ; // semlib.c 16A7 ; #include <912d60.h> 16A7 ; #include "kernel.h" 16A7 ; #include "semlib.h" 16A7 ; 16A7 ; 16A7 ; 16A7 ; 16A7 ; // GLOBAL VARIABLES 16A7 ; extern unsigned int current; // current task id number 16A7 ; 16A7 ; // task control block 16A7 ; extern struct task_block { 16A7 ; unsigned char id; // ID of task 16A7 ; enum task_state state; // State 16A7 ; unsigned char priority; // Priority 16A7 ; unsigned char *heap_ptr; // heap addr while not current task 16A7 ; unsigned int heap_size; // heap size 16A7 ; unsigned char *frame_ptr; // CCR pointer 16A7 ; }; 16A7 ; 16A7 ; 16A7 ; // resource control block 16A7 ; extern struct resource_block { 16A7 ; unsigned char id; // ID of resource 16A7 ; enum resource_state state; // State (busy, free...) 16A7 ; unsigned char user; // Current resource user/owner 16A7 ; signed char queue[4]; // Tasks waiting on resource 16A7 ; unsigned char queue_pos; // Next free spot in queue 16A7 ; }; 16A7 ; 16A7 ; 16A7 ; extern struct task_block task[numtasks]; 16A7 ; extern struct resource_block resource[numresources]; 16A7 ; 16A7 ; 16A7 ; 16A7 ; 16A7 ; 16A7 ; 16A7 ; 16A7 ; signed char sem_get(char resource_id) { 16A7 ; 16A7 ; /* Gives a resource to a requesting task. 16A7 ; returns the resource id number (0,1,2,...) if free. 16A7 ; otherwise returns -1. 16A7 ; 16A7 ; At this point, semaphores are a procedural control 16A7 ; that the tasks have to follow to avoid resource contention. 16A7 ; There is no kernel control over resources yet. */ 16A7 ; 16A7 ; 16A7 ; // critical section 16A7 ; INTR_OFF(); 16A7 1410 sei 16A9 16A9 ; 16A9 ; 16A9 ; // GET SEMAPHORE 16A9 ; // give semaphore to task 16A9 ; if (resource[resource_id].state == notbusy) { 16A9 E603 ldab 3,x 16AB 87 clra 16AC 59 lsld 16AD 59 lsld 16AE 59 lsld 16AF C3020D addd #_resource+1 16B2 B7C6 xgdy 16B4 E740 tst 0,y 16B6 2649 bne L4 16B8 ; resource[resource_id].state = busy; 16B8 E603 ldab 3,x 16BA 87 clra 16BB 59 lsld 16BC 59 lsld 16BD 59 lsld 16BE C3020D addd #_resource+1 16C1 B7C6 xgdy 16C3 C601 ldab #1 16C5 6B40 stab 0,y 16C7 ; resource[resource_id].user = current; 16C7 E603 ldab 3,x 16C9 87 clra 16CA 59 lsld 16CB 59 lsld 16CC 59 lsld 16CD C3020E addd #_resource+2 16D0 B7C6 xgdy 16D2 FC023B ldd _current 16D5 6B40 stab 0,y 16D7 ; if (task[current].state == waiting) 16D7 CC0009 ldd #9 16DA FD023B ldy _current 16DD 13 emul 16DE C3021D addd #_task+1 16E1 B7C6 xgdy 16E3 E640 ldab 0,y 16E5 C103 cmpb #3 16E7 2610 bne L9 16E9 ; task[current].state = running; 16E9 CC0009 ldd #9 16EC FD023B ldy _current 16EF 13 emul 16F0 C3021D addd #_task+1 16F3 B7C6 xgdy 16F5 C602 ldab #2 16F7 6B40 stab 0,y 16F9 L9: 16F9 ; INTR_ON(); 16F9 10EF cli 16FB 16FB ; return resource_id; 16FB E603 ldab 3,x 16FD B714 tfr b,d 16FF 2015 bra L3 1701 L4: 1701 ; } 1701 ; // busy 1701 ; else { 1701 ; task[current].state = waiting; 1701 CC0009 ldd #9 1704 FD023B ldy _current 1707 13 emul 1708 C3021D addd #_task+1 170B B7C6 xgdy 170D C603 ldab #3 170F 6B40 stab 0,y 1711 ; INTR_ON(); 1711 10EF cli 1713 1713 ; return -1; 1713 CCFFFF ldd #-1 1716 L3: 1716 B757 tfr x,s 1718 30 pulx 1719 1B82 leas 2,sp 171B .dbline 0 ; func end 171B 3D rts 171C ; resource_id -> 3,x 171C _sem_give:: 171C 3B pshd 171D 34 pshx 171E B775 tfr s,x 1720 ; } 1720 ; } 1720 ; 1720 ; 1720 ; 1720 ; 1720 ; void sem_give(char resource_id) { 1720 ; 1720 ; /* Takes a resource back from a task. 1720 ; will (eventually) pass a message to a waiting task. 1720 ; 1720 ; At this point, semaphores are a procedural control 1720 ; that the tasks have to follow to avoid resource contention. 1720 ; There is no kernel control over resources yet. */ 1720 ; 1720 ; 1720 ; // critical section 1720 ; INTR_OFF(); 1720 1410 sei 1722 1722 ; 1722 ; 1722 ; // return the resource 1722 ; resource[resource_id].state = notbusy; 1722 E603 ldab 3,x 1724 87 clra 1725 59 lsld 1726 59 lsld 1727 59 lsld 1728 C3020D addd #_resource+1 172B B7C6 xgdy 172D 6940 clr 0,y 172F ; 172F ; INTR_ON(); 172F 10EF cli 1731 1731 ; 1731 ; } 1731 L14: 1731 B757 tfr x,s 1733 30 pulx 1734 1B82 leas 2,sp 1736 .dbline 0 ; func end 1736 3D rts .module kernel.c .area text 1737 _get_task_id:: 1737 ; //kernel.c 1737 ; 1737 ; #include "kernel.h" 1737 ; 1737 ; 1737 ; // GLOBAL VARIABLE DEFINITIONS 1737 ; unsigned int current; // current task id number 1737 ; unsigned long int system_tick; 1737 ; 1737 ; 1737 ; // task control block 1737 ; typedef struct task_block { 1737 ; unsigned char id; // ID of task 1737 ; enum task_state state; // State 1737 ; unsigned char priority; // Priority 1737 ; unsigned char *heap_ptr; // heap addr while not current task 1737 ; unsigned int heap_size; // heap size 1737 ; unsigned char *frame_ptr; // CCR pointer 1737 ; }; 1737 ; 1737 ; 1737 ; // resource control block 1737 ; typedef struct resource_block { 1737 ; unsigned char id; // ID of resource 1737 ; enum resource_state state; // State (busy, free...) 1737 ; unsigned char user; // Current resource user/owner 1737 ; signed char queue[4]; // Tasks waiting on resource 1737 ; unsigned char queue_pos; // Next free spot in queue 1737 ; }; 1737 ; 1737 ; 1737 ; struct task_block task[numtasks]; 1737 ; struct resource_block resource[numresources]; 1737 ; 1737 ; 1737 ; 1737 ; // FUNCTIONS 1737 ; 1737 ; unsigned char get_task_id() { 1737 ; return task[current].id; 1737 CC0009 ldd #9 173A FD023B ldy _current 173D 13 emul 173E C3021C addd #_task 1741 B7C6 xgdy 1743 E640 ldab 0,y 1745 87 clra 1746 L1: 1746 .dbline 0 ; func end 1746 3D rts 1747 ; id -> 3,x 1747 _get_task_state:: 1747 3B pshd 1748 34 pshx 1749 B775 tfr s,x 174B ; } 174B ; 174B ; unsigned char get_task_state(unsigned char id) { 174B ; return task[id].state; 174B E603 ldab 3,x 174D 87 clra 174E B7C6 xgdy 1750 CC0009 ldd #9 1753 1813 emuls 1755 C3021D addd #_task+1 1758 B7C6 xgdy 175A E640 ldab 0,y 175C 87 clra 175D L2: 175D B757 tfr x,s 175F 30 pulx 1760 1B82 leas 2,sp 1762 .dbline 0 ; func end 1762 3D rts 1763 ; id -> 3,x 1763 _get_task_priority:: 1763 3B pshd 1764 34 pshx 1765 B775 tfr s,x 1767 ; } 1767 ; 1767 ; unsigned char get_task_priority(unsigned char id) { 1767 ; return task[id].priority; 1767 E603 ldab 3,x 1769 87 clra 176A B7C6 xgdy 176C CC0009 ldd #9 176F 1813 emuls 1771 C3021E addd #_task+2 1774 B7C6 xgdy 1776 E640 ldab 0,y 1778 87 clra 1779 L4: 1779 B757 tfr x,s 177B 30 pulx 177C 1B82 leas 2,sp 177E .dbline 0 ; func end 177E 3D rts 177F ; state -> 7,x 177F ; id -> 3,x 177F _set_task_state:: 177F 3B pshd 1780 34 pshx 1781 B775 tfr s,x 1783 ; } 1783 ; 1783 ; void set_task_state(unsigned char id, unsigned char state) { 1783 ; task[id].state=state; 1783 E603 ldab 3,x 1785 87 clra 1786 B7C6 xgdy 1788 CC0009 ldd #9 178B 1813 emuls 178D C3021D addd #_task+1 1790 B7C6 xgdy 1792 E607 ldab 7,x 1794 6B40 stab 0,y 1796 ; } 1796 L6: 1796 B757 tfr x,s 1798 30 pulx 1799 1B82 leas 2,sp 179B .dbline 0 ; func end 179B 3D rts 179C ; priority -> 7,x 179C ; id -> 3,x 179C _set_task_priority:: 179C 3B pshd 179D 34 pshx 179E B775 tfr s,x 17A0 ; 17A0 ; void set_task_priority(unsigned char id, unsigned char priority) { 17A0 ; 17A0 ; if (priority == 0) priority = 1; 17A0 E707 tst 7,x 17A2 2604 bne L9 17A4 C601 ldab #1 17A6 6B07 stab 7,x 17A8 L9: 17A8 ; task[id].priority=priority; 17A8 E603 ldab 3,x 17AA 87 clra 17AB B7C6 xgdy 17AD CC0009 ldd #9 17B0 1813 emuls 17B2 C3021E addd #_task+2 17B5 B7C6 xgdy 17B7 E607 ldab 7,x 17B9 6B40 stab 0,y 17BB ; } 17BB L8: 17BB B757 tfr x,s 17BD 30 pulx 17BE 1B82 leas 2,sp 17C0 .dbline 0 ; func end 17C0 3D rts .area bss 020C _resource:: 020C .blkb 16 021C _task:: 021C .blkb 27 0237 _system_tick:: 0237 .blkb 4 023B _current:: 023B .blkb 2