Hi all,
Anyone out there experienced with multitasking a PIC? I am trying to
implement interrupts to perform the function of a multitasking a PIC with
all sorts of trouble and was hoping there is already something written I
could 'borrow' to do the same thing.
john
There is not a widely-used multitasking OS for PIC's because they aren't
well suited to it.
1) They are pretty small (memory-wise, especially), so they couldn't hold a
very complex OS.
2) They are pretty cheap, and generally used in applications that don't need
particularly complex software.
3) The usual way for an OS to manage multitasking is by switching stack
pointers. The PIC's hardware stack makes this so difficult and inefficient
that it generally isn't worth the pain.
That said, there are still plenty of methods in a good programmer's bag of
tricks that can be applied to get a PIC to do more than one thing at a time,
which is the essence of multitasking. Interrupts are one way -- do one
task, say in response to a timer interrupt, and another in the background at
the non-interrupt level.
State machines are another way. Electrical engineers are used to using them
to design digital logic, but they can be used to design software as well.
It's not an operating system, but you might take a look at the Realizer
package here: http://www.actum.com/actum.htm
It's an extremely clever system to convert logic and state diagrams into
code for PIC's and other microcontrollers. If only they didn't have to work
for a living and could afford to give it away... They are pretty reasonable
for such a professional package, but they aren't free, and the free demo is
so limited it's hard even to play with it.
Something like this would work for two tasks in the same page. A more
generic solution would be an interesting challenge but seemingly doable.
Certainly this kind of thing is way more efficient than using explicit
state machines.
> Something like this would work for two tasks in the same page. A more
> generic solution would be an interesting challenge but seemingly doable.
> Certainly this kind of thing is way more efficient than using explicit
> state machines.
if you're willing to add one variable for each task, you can stream line
this somewhat
Hi Scott, actually I was shooting for small code since all must fit in one
page. Later I thought of a way to cut 'switch' to one instruction, it
ain't gonna get any smaller than that :)
switch macro
retlw $+1 ; return 'return'
endm
context equ 0x20
movlw task1 ; note task 1 will run first
movwf context
movlw task2
; task switcher
call $+2 ; make a place for 'switch' to return to
goto $-1 ; (i.e. here!)
xorlw context,f ; then exchange w and context
xorlw context,w
xorlw context,f
movwf pcl ; and jmp to w
> if you're willing to add one variable for each task, you can stream
> line this somewhat
>
> switch macro _from_, _to_
> movlw $+4
> movwf _from_
> movf _to_,w
> movwf pcl
> endm
>
> now the 18cxxx.... well there's probably a dozen ways to do this. I
> wish I had time right now to explore them...
>
> Scott
> Hi Scott, actually I was shooting for small code since all must fit in one
> page. Later I thought of a way to cut 'switch' to one instruction, it
> ain't gonna get any smaller than that :)
Cool! Now that you write this, I recall someone else (I believe it was
Payson) doing something similar. Now that you've got the 'context
switching' all confined to one section, you've opened up the possibilities
of extending its functionality (without having duplicate code snippets
scattered throughout).
1) You could easily add additional tasks. Cycling through each can be
done in a 'round-robin' fashion. For example, after task A then run task
B, C,..., N, and back to A.
2) You could add priorities to the tasks.
3) With an extra instruction in the 'switch' macro, you could handle
multiple pages:
switch macro
movlw HIGH($+2)
retlw $+1
endm
-----------------------
If you're using the 12bit core, then you might consider populating the
stack with the address of the context switcher. You could do the same with
the 14bit core - but chances are you're more likely to need the stack for
making calls. (on the 12bit core, the stack is only 2 levels ) Once the
stack is filled, then the retlw's will take advantage of stack roll overs.
movlw task1
movwf context
movlw task2
setc
clrf first_time
goto l2
l1 rlf first_time,f
btfss first_time,1
l2 call l1
l3 xorlw context,f ; then exchange w and context
xorlw context,w
xorlw context,f
movwf pcl ; and jmp to w
for the 14bit core you could fill the stack:
movlw task1
movwf context
movlw task2
setc
clrf first_time
goto l2
l1 rlf first_time,f
btfss first_time,7
l2 call l1
l3 xorlw context,f ; then exchange w and context
xorlw context,w
xorlw context,f
movwf pcl ; and jmp to w
I haven't tried this, but once you get the stack 'primed', you can save 4
execution cycles.
> Cool! Now that you write this, I recall someone else (I believe it was
> Payson) doing something similar. Now that you've got the 'context
> switching' all confined to one section, you've opened up the possibilities
> of extending its functionality (without having duplicate code snippets
> scattered throughout).
>
> 1) You could easily add additional tasks. Cycling through each can be
> done in a 'round-robin' fashion. For example, after task A then run task
> B, C,..., N, and back to A.
This should be doable with N-1 bytes of context and N-1 'exchange w with
context+X' tuples.
Can't see a clean way to make it work across the address space though.
Your stack preload idea got me to thinking I could use the stack as a
context table for 8 tasks, i.e. 'switch' would be 'call dispatch',
dispatch would increment the stack pointer and return. But... there's no
way to increment the stack pointer... and anyway, subroutines are our
friends. :) --- Rich
> On Thu, 10 Feb 2000, Scott Dattalo wrote:
>
> > Cool! Now that you write this, I recall someone else (I believe it was
> > Payson) doing something similar. Now that you've got the 'context
> > switching' all confined to one section, you've opened up the possibilities
> > of extending its functionality (without having duplicate code snippets
> > scattered throughout).
> >
> > 1) You could easily add additional tasks. Cycling through each can be
> > done in a 'round-robin' fashion. For example, after task A then run task
> > B, C,..., N, and back to A.
> This should be doable with N-1 bytes of context and N-1 'exchange w with
> context+X' tuples.
>
> Can't see a clean way to make it work across the address space though.
> Your stack preload idea got me to thinking I could use the stack as a
> context table for 8 tasks, i.e. 'switch' would be 'call dispatch',
> dispatch would increment the stack pointer and return. But... there's no
> way to increment the stack pointer... and anyway, subroutines are our
> friends. :) --- Rich
Yeah - spanning the address space would be difficult. The little snippet I
posted last time had a rediculous bug
movlw HIGH($+2)
retlw $+1
This doesn't work because the retlw will wipe out W's contents. So what
you'd have to do instead is added another line:
movlw HIGH($+2)
movwf context_high_temp
retlw $+1
and then in the context switcher (it's realy messy...):
code....
retlw (t1_1-table_start) ;return the index to
;the table of task branches
task1_offset1:
code....
This only adds two additional cycles to the single-code page version.
I seldom use macros, but perhaps its possible to parameterize the
retlw (tx_y-table_start)
taskx_offsety
and the accompanying:
tx_y goto taskx_offsety
This approach has an additional benefit of allowing you to select the
address at which the task will next begin exectuting. For example, you
could do this:
> Hi all,
> Anyone out there experienced with multitasking a PIC? I am trying to
> implement interrupts to perform the function of a
> multitasking a PIC with
> all sorts of trouble and was hoping there is already
> something written I
> could 'borrow' to do the same thing.
> john
>
www.geocities.com/SiliconValley/Network/3656/posit/posit.html
Quote from the page:
"Microcore for PIC16C84 based systems. It allows to create a
multitasking system simply by adding as many
tasks as you want. Each of them must be in a separate file and have 3
methods for initialisation, interrupt
management and body.
It was tested on mobile robot . And it is FREE"
Kayode.
Dr O. K. Ayandokun,
The BlackBoxCamera Company Limited,
Unit U7, Lenton Boulevard,
Nottingham, NG7 2BY,
England. spam_OUTkayode.ayandokunTakeThisOuTvirgin.net
Tel. +44 (0)700 2522526
For the latest in home security camera technology and the best ideas for
using it visit http://www.blackboxcamera.com