Pic'xe is a simple macro based task scheduler for PIC micro-processors. It can be used with any Microchip processor, but for DELAY macros requires processors with TMR0 and interuppt support.
It is released under the GPL license, for commercial projects contact me via email.
Pic'xe was developed using GPASM and MPASM.
To download the code please use the Sourceforge Download page.
Here is a simple example written using relocatable assembler directives. It has three tasks, each task produces a pulsed signal on a different pin on Port A.
list p=16f628a ; list directive to define processor #include; processor specific variable definitions #include "scheduler.inc" ; Scheduler Macros __CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _LVP_OFF & _DATA_CP_OFF &_MCLRE_OFF ;******************************************************************************** ; ; Example code on how to use the scheduler macros with a relocatable compiler ; ; It has three seperate tasks. ; Task1 pulses Port A bit 0 every 100 milliseconds ; Task2 pulses Port A bit 1 every 5 seconds ; Task3 pulses Port A bit 2 whenever it can ; ;******************************************************************************** ; First use a macro to define the Timer0 values. ; ; P1 = Frequency in Hertz ; P2 = Tick size in milliseconds CALC_TMR0 4000000,1 ; 4Mhz Clk, 1 Millisec Tick ;***** VARIABLE DEFINITIONS ; Define Intialised data area in Bank0 Ram IDATA 0x20 TCB1 TCB ; One TCB macro is required for each task TCB2 TCB ; and they must be contigious TCB3 TCB #define NUM_TCBS 3 ; Constant for number of tasks ; Define Scheduler data areas using macro SCHEDULER_DATA w_temp res 1 ; variable used for context saving status_temp res 1 ; variable used for context saving ; Now define Code ;********************************************************************** RESET_VECTOR CODE 0x000 ; processor reset vector movlw high start ; load upper byte of 'start' label movwf PCLATH ; initialize PCLATH goto start ; go to beginning of program INT_VECTOR CODE 0x004 ; interrupt vector location movwf w_temp ; save off current W register contents movf STATUS,w ; move status register into W register bcf STATUS,RP0 ; ensure file register bank set to 0 movwf status_temp ; save off contents of STATUS register ; Use macro to define code that processed Timer0 tick ; ; P1 = Address of first TCB ; P2 = Number of TCB's in the list PROCESS_TICK TCB1,NUM_TCBS ; Test Tmr0 and process the Tick Counters movf status_temp,w ; retrieve copy of STATUS register movwf STATUS ; restore pre-isr STATUS register contents swapf w_temp,f swapf w_temp,w ; restore pre-isr W register contents retfie ; return from interrupt ; Start of main code MAIN CODE start ; Initialise Port A TRIS movlw 0 BANKSEL TRISA movwf TRISA ; Use macro to initialise Timer0 INIT_TMR0 ; Initialise TMR0 ; Initialise each TCB ; P1 = Address for the TCB ; P2 = Address of first instruction NEWTASK TCB1,task1 NEWTASK TCB2,task2 NEWTASK TCB3,task3 ; Use macro to define scheduler code ; P1 = Address of first TCB ; P2 = Number of TCBs in the list SCHEDULER TCB1, NUM_TCBS ; Now define the tasks. ; These are fairly trivial, but can be as complex as you need. ; One caveat, all calls to the Scheduler (DELAY, YIELD etc) must be at the outer ; level of the code, they cannot be called from within a subroutine. task1 bsf PORTA,0 ; Set PORTA bit 0 DELAY TCB1, d'100' ; Wait 100 Milliseconds bcf PORTA,0 ; Clear PORTA bit 0 DELAY TCB1, d'100' ; Wait 100 Milliseconds goto task1 ; Go back and try again task2 bsf PORTA,1 ; Set PORTA bit 1 DELAY TCB2, d'5000' ; Wait 5 seconds bcf PORTA,1 ; Clear PORTA bit 1 DELAY TCB2, d'5000' ; Wait 5 seconds goto task2 ; Go back and try again task3 bsf PORTA,2 ; Set PORTA bit 1 YIELD TCB3 ; Release CPU bcf PORTA,2 ; Clear PORTA bit 1 YIELD TCB3 ; Release CPU goto task3 ; Go back and try again END
If you need any support, extra features etc. please use the Sourceforge Tracker.