Way back on 10 May 99, John Payson wtote: >|Does any of you has an idea of a multitask kernel (2 tasks should cover >|most applications) without using interrupt facilities in order to be put >|on a PIC 12C509 for example ? > >Here's a nice simple method, assuming one of the tasks will fit within >256 bytes of codespace, won't call subroutines more than 1-deep, and no >task switch will need to occur within a subroutine. > >Define a register called "VirtPC". When it starts up, your main task >should set it equal to the start address of your "alternate" task. You >should also have a code address called "Springboard" at which is coded: > >Springboard: > movf VirtPC,w > movwf PC > >From the main program, when you want to yield control to the alternate >task you just use the two instructions: > > call Springboard > movwf VirtPC > >When your alternate program wants to yield control, it should do > > retlw $+1 I've used state machines to manage multiple tasks in the past and thought I'd give John's method a try. The target is a 12 bit core device which limits my options. It occured to me that there is a tiny bit more overhead in John's technique than necessary. Here is my reasoning. Anything that modifies PCL on the 12 bit core must live within the first 256 words of a page (512 spaces per page). Bit 8 of the PC is always cleared. If the code is small enough to fit in a small device (12c508), you can shave 1 cycle off John's method *and* allow 2 levels of subroutine to be used in either task. All you do is set PCL to the entry point of the 2nd task. The main task looks like this: ;jump to 2nd task. 3 cycle call, 4 cycle return movfw TSK2PC movwf PCL Tsk2Rtn movwf TSK2PC ;rest of main task All subtasks are located within the 1st 256 codespaces. Each subtask ends with the following: movlw $+2 ;or 'movlw label' to re-enter somewhere else goto Tsk2Rtn Thats it! The downside is that each subtask occupies 1 more codespace than John's method. Things are a tiny bit more interesting when dealing with a larger 12 bit core device such as the 12c509. With both methods, you have to manipulate the page bit to ensure you end up where you want to be. When using John's method, you can simply set the page bit to the proper value so long as anything else that modifies PCL is on the same page as the 2nd task - it is still just 8 cycles total since the stack contains the full return address. If anything changes the page bit, you have to add 2 cycles for a total of 10. In my case, the 2nd task is going to have to be on the 2nd page since I have have numerous table jumps in the main task on the 1st page. I also have to add the 2 cycles to set and clr the page bit, leaving me with a 9 cycle context change. The revised version looks like this: The main task looks like this: ;jump to 2nd task. 4 cycle call, 5 cycle return bsf PAGE ;STATUS,5 movfw TSK2PC movwf PCL Tsk2Rtn movwf TSK2PC ;rest of main task All subtasks are located within the 1st 256 codespaces on page 1. Each subtask ends with the following: bcf PAGE movlw $+2 ;or 'movlw label' to re-enter somewhere else goto Tsk2Rtn Thoughts, opinions anyone? dwayne Dwayne Reid Trinity Electronics Systems Ltd Edmonton, AB, CANADA (780) 489-3199 voice (780) 487-6397 fax Celebrating 15 years of Engineering Innovation (1984 - 1999) * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Do NOT send unsolicited commercial email to this email address. My posting messages to Usenet neither grants consent to receive unsolicited commercial email nor is intended to solicit commercial email.