.module rlpos.c .area data 0000 _task_ptr:: 0000 .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 0006 _main_frame_ptr:: 0006 .blkb 2 .area idata 0006 0000 .word 0 .area data 0008 _main_frame_x_ptr:: 0008 .blkb 2 .area idata 0008 0000 .word 0 .area data 000A _temp_task_frame_ptr:: 000A .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 0000 _main:: 0000 34 pshx 0001 B775 tfr s,x 0003 1BF1E2 leas -30,sp 0006 ; /* RLPOS: RLPotter Operating System 0006 ; 0006 ; Version 0.4 for the 68HC12D60A microcontroller 0006 ; by Ryan Potter 0006 ; ryan@rlpotter.com 0006 ; 0006 ; 0006 ; v0.4 April 13, 2004: 8043 bytes 0006 ; - gerneralized the shell command-line input parser: 0006 ; cmd (up to 32 chars) 0006 ; - added kernel and shell functions 0006 ; v0.3 April 12, 2003: 6090 bytes 0006 ; - added a beginning shell user interface. 0006 ; - added a resource control block and basic semaphore functions. 0006 ; - added basic kernel functions 0006 ; v0.2 April 9, 2003: 0006 ; - able to round-robin with RTI interrupt. 0006 ; - bonified/certified multitasking with 3 tasks. :) 0006 ; v0.1 April 3, 2003: 0006 ; - able to round-robin without interrupts. 0006 ; - not multitasking, really. 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 ; 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 ; 3) kernel takes up too large a fraction of the processing time 0006 ; */ 0006 ; 0006 ; 0006 ; 0006 ; #include <912d60.h> 0006 ; #include 0006 ; #include 0006 ; #include "kernel.h" 0006 ; 0006 ; 0006 ; 0006 ; 0006 ; // FUNCTION PROTOTYPES 0006 ; void RTI_handler(void); 0006 ; void shell(void); 0006 ; void task1(void); 0006 ; void task2(void); 0006 ; void (*task_ptr[])(void) = {&shell, &task1, &task2}; 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 ; unsigned char id; // ID of task 0006 ; enum task_state state; // State 0006 ; unsigned char priority; // Priority 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 ; enum resource_state state; // State (busy, free...) 0006 ; unsigned char user; // Current resource user/owner 0006 ; signed char queue[4]; // Tasks waiting on resource 0006 ; unsigned char queue_pos; // 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 ; 0006 ; 0006 ; 0006 ; 0006 ; main() { 0006 ; 0006 ; // LOCAL VARIABLES 0006 ; int result; 0006 ; unsigned int i, temp_heap_size; 0006 ; unsigned int last_task = 0; 0006 CC0000 ldd #0 0009 6CE1EF std -17,x 000C ; unsigned int next_task = 0; 000C CC0000 ldd #0 000F 6C14 std -12,x 0011 ; unsigned char *temp_heap_ptr, temp; 0011 ; 0011 ; 0011 ; // INITIALIZE GLOBAL VARIABLES 0011 ; extern int _bss_end, _textmode; 0011 ; extern unsigned int current; 0011 ; extern unsigned long int system_tick; 0011 ; 0011 ; 0011 ; _textmode = 1; 0011 CC0001 ldd #1 0014 7C0000 std __textmode 0017 ; current = 0; 0017 CC0000 ldd #0 001A 7C0000 std _current 001D ; system_tick = 0; 001D CD0355 ldy #L4 0020 1802401C movw 0,y,-4,x 0024 1802421E movw 2,y,-2,x 0028 CD0000 ldy #_system_tick 002B 18021C40 movw -4,x,0,y 002F 18021E42 movw -2,x,2,y 0033 CC0000 ldd #0 0036 6C16 std -10,x 0038 2064 bra L8 003A L5: 003A CC0009 ldd #9 003D ED16 ldy -10,x 003F 13 emul 0040 C30000 addd #_task 0043 B7C6 xgdy 0045 EC16 ldd -10,x 0047 6B40 stab 0,y 0049 CC0009 ldd #9 004C ED16 ldy -10,x 004E 13 emul 004F C30001 addd #_task+1 0052 B7C6 xgdy 0054 C604 ldab #4 0056 6B40 stab 0,y 0058 CC0009 ldd #9 005B ED16 ldy -10,x 005D 13 emul 005E C30002 addd #_task+2 0061 B7C6 xgdy 0063 C6FF ldab #255 0065 6B40 stab 0,y 0067 CC0009 ldd #9 006A ED16 ldy -10,x 006C 13 emul 006D C30003 addd #_task+3 0070 B7C6 xgdy 0072 CC0000 ldd #0 0075 6C40 std 0,y 0077 CC0009 ldd #9 007A ED16 ldy -10,x 007C 13 emul 007D C30005 addd #_task+5 0080 B7C6 xgdy 0082 CC0000 ldd #0 0085 6C40 std 0,y 0087 CC0009 ldd #9 008A ED16 ldy -10,x 008C 13 emul 008D C30007 addd #_task+7 0090 B7C6 xgdy 0092 CC0000 ldd #0 0095 6C40 std 0,y 0097 L6: 0097 EC16 ldd -10,x 0099 C30001 addd #1 009C 6C16 std -10,x 009E L8: 009E ; 009E ; 009E ; // initialize the task structures 009E ; for (i=0; i= numtasks) 0223 EC14 ldd -12,x 0225 8C0003 cpd #3 0228 2505 blo L49 022A ; next_task = 0; 022A CC0000 ldd #0 022D 6C14 std -12,x 022F L49: 022F L24: 022F 1820FED9 lbra L23 0233 X2: 0233 ; 0233 ; 0233 ; 0233 ; // diagnostic 0233 ; //putchar(':'); 0233 ; 0233 ; } // end 'while(1)' 0233 ; 0233 ; return 0; 0233 CC0000 ldd #0 0236 L3: 0236 B757 tfr x,s 0238 30 pulx 0239 .dbline 0 ; func end 0239 3D rts 023A ; lreg1 -> -4,x 023A ; lreg2 -> -8,x 023A ; ?temp -> -16,x 023A ; local_thp -> -14,x 023A ; frame_size -> -12,x 023A ; i -> -10,x 023A _RTI_handler:: 023A 34 pshx 023B B775 tfr s,x 023D 1BF1EC leas -20,sp 0240 ; } 0240 ; 0240 ; 0240 ; 0240 ; #pragma interrupt_handler RTI_handler() 0240 ; 0240 ; void RTI_handler(void) { 0240 ; 0240 ; size_t frame_size; 0240 ; unsigned int i; 0240 ; unsigned char *local_thp; 0240 ; 0240 ; 0240 ; //ACKNOWLEDGE THE INTERRUPT 0240 ; INTR_OFF(); // redundant. automatically done by the processor 0240 1410 sei 0242 0242 ; RTIFLG = 0x0080; // acknowledge/clear the interrupt 0242 C680 ldab #128 0244 7B0015 stab 0x15 0247 ; 0247 ; 0247 ; 0247 ; //putchar('I'); 0247 ; //putchar(current + 48); 0247 ; //putchar('('); 0247 ; 0247 ; 0247 ; 0247 ; // SET THE FRAME POINTER for the interupted task. 0247 ; // should point to the CCR entry on the stack. 0247 ; asm("TFR x,d"); // start of RTI stack 0247 B754 TFR x,d 0249 0249 ; asm("ADDD #2"); // adjust to CCR stack entry 0249 C30002 ADDD #2 024C 024C ; asm("STD _temp_task_frame_ptr"); // put into task_frame_ptr 024C 7C000A STD _temp_task_frame_ptr 024F 024F ; task[current].frame_ptr = temp_task_frame_ptr; 024F CC0009 ldd #9 0252 FD0000 ldy _current 0255 13 emul 0256 C30007 addd #_task+7 0259 B7C6 xgdy 025B FC000A ldd _temp_task_frame_ptr 025E 6C40 std 0,y 0260 ; 0260 ; 0260 ; 0260 ; //PLACE CURRENT TASK CONTEXT ONTO THE HEAP 0260 ; // determine size of heap segment needed 0260 ; frame_size = main_frame_ptr - temp_task_frame_ptr; // always positive 0260 FC0006 ldd _main_frame_ptr 0263 B3000A subd _temp_task_frame_ptr 0266 6C14 std -12,x 0268 ; task[current].heap_size = (int)frame_size; 0268 CC0009 ldd #9 026B FD0000 ldy _current 026E 13 emul 026F C30005 addd #_task+5 0272 B7C6 xgdy 0274 EC14 ldd -12,x 0276 6C40 std 0,y 0278 ; 0278 ; // reallocate heap memory 0278 ; task[current].heap_ptr = realloc(task[current].heap_ptr, frame_size); 0278 18021480 movw -12,x,0,sp 027C CC0009 ldd #9 027F FD0000 ldy _current 0282 13 emul 0283 6C10 std -16,x 0285 C30003 addd #_task+3 0288 B7C6 xgdy 028A EC40 ldd 0,y 028C 160000 jsr _realloc 028F 6CE1EE std -18,x 0292 EC10 ldd -16,x 0294 C30003 addd #_task+3 0297 B7C6 xgdy 0299 ECE1EE ldd -18,x 029C 6C40 std 0,y 029E ; local_thp = task[current].heap_ptr; 029E CC0009 ldd #9 02A1 FD0000 ldy _current 02A4 13 emul 02A5 C30003 addd #_task+3 02A8 B7C6 xgdy 02AA ED40 ldy 0,y 02AC 6D12 sty -14,x 02AE ; 02AE ; if (local_thp == NULL) { 02AE EC12 ldd -14,x 02B0 260C bne L57 02B2 ; puts("out of heap space!"); 02B2 CC031A ldd #L59 02B5 160000 jsr _puts 02B8 ; exit(0); 02B8 CC0000 ldd #0 02BB 160000 jsr _exit 02BE ; } 02BE L57: 02BE CC0000 ldd #0 02C1 6C16 std -10,x 02C3 201A bra L63 02C5 L60: 02C5 EC16 ldd -10,x 02C7 F3000A addd _temp_task_frame_ptr 02CA B7C6 xgdy 02CC E640 ldab 0,y 02CE 3B pshd ; spill 02CF EC16 ldd -10,x 02D1 E312 addd -14,x 02D3 B7C6 xgdy 02D5 3A puld ; reload 02D6 6B40 stab 0,y 02D8 L61: 02D8 EC16 ldd -10,x 02DA C30001 addd #1 02DD 6C16 std -10,x 02DF L63: 02DF ; 02DF ; // transfer task frame to the heap one byte at a time. 02DF ; // assumes the heap grows from low to high addr. 02DF ; for(i=0; i