> From: Andy Kunz <spam_OUTmontanaTakeThisOuTFAST.NET>
> To: .....PICLISTKILLspam@spam@MITVMA.MIT.EDU
> Subject: Re: SoNoboby knows
> Date: Sunday, 1 June 1997 00:09
>
> >Arrgh! I knew this was going to degenerate into an os/machines war!
You
> >could MT on a high-end PIC if you didn't want GUI. It's the GUI that
needs
> >the PC size box, not the MT.
>
> You can cooperatively multi-task on a 12C508 if you know what you're
doing.
I don't regard cooperative MT as useful, in the embedded world.
> >True. So why is it still a 16 bit app? 3.11 was buried 2 years ago.
> >MPLAB's latest release is since then. It doesn't take that long to port
> >from one to the other.
>
> It can very well. Many names were changed, and many parameters. It
ain't
> a simple "recompile with a 32-bit bit compiler" deal.
True, if you code with the 'raw' Windows API's. If you do this you deserve
a hard porting job. Using a higher level such as MFC, you *can* port
easily. (this probably applies to Delphi/Owl and others, as well.
The upgrade from 3.11 to 95 is trivial in cost, and trivial in cost of
support hardware needed. Why wait? I suppose some ppl are still using
XT's or less, but that hasn't stopped MPLAB from running on a system that
requires a 386 as a minimum (Win3.11)(realistically)
>
> Besides, MicroChip would have to pay for the upgrade to Delphi 2 :-).
>
Perhaps they've dumped it and gone to c++
----------
> From: Clyde Smith-Stubbs <@spam@clydeKILLspamHTSOFT.COM>
> To: KILLspamPICLISTKILLspamMITVMA.MIT.EDU
> Subject: Re: SoNoboby knows
> Date: Sunday, 1 June 1997 06:48
>
> Thus spake Scott Newell (RemoveMEnewellTakeThisOuTCEI.NET):
>
> > Speaking of Delphi, I got the simulator to run about 20 times faster by
> > writting a little Delphi app to simply 'pound' the MPLAB IDE with mouse
> > messages. (A more elegant solution might be to raise the MPLAB
thread's
> > priority. Oh well.)
>
> Nope, raising the MPLAB task priority (it has no threads) will do nothing
To PIC a nit, it must have one thread, which belongs to the process. (If
you use MFC, CWinApp - which is the main app object, is actually derived
from CWinThread)
> since it is DELIBERATELY waiting for messages, and until one arrives,
will
> do nothing, irrespective of its priority. This behaviour is not unique to
> running under Win32, BTW. It does exactly the same thing under Win3.1.
That's why it would be better coded as a Win32 app (and have a decent
threading model enabled)
>
> Any conspiracy theorists out there?
>
Nobody but us coders! (anyone who uses compilers and os's API's become
paranoid over time, anyway.)
>I don't regard cooperative MT as useful, in the embedded world.
Too bad. It makes "impossible" things easy.
>True, if you code with the 'raw' Windows API's. If you do this you deserve
>a hard porting job. Using a higher level such as MFC, you *can* port
>easily. (this probably applies to Delphi/Owl and others, as well.
They changed many names in MFC as well. They couldn't even keep them the
same from one _release_ to the next!
Andy
==================================================================
Andy Kunz - Montana Design - 409 S 6th St - Phillipsburg, NJ 08865
Hardware & Software for Industry & R/C Hobbies
"Go fast, turn right, and keep the wet side down!"
==================================================================
At 04:37 PM 6/1/97 -0400, you wrote:
>>I don't regard cooperative MT as useful, in the embedded world.
>
>Too bad. It makes "impossible" things easy.-snip-
Andy Kunz
-snip-
When you say cooperative multitasking, are you
meaning MT where the code moves between any and
all possible combinations of output states, waiting
and testing at each one for conditions that say to
go to a new output state and wait again?
Or, are you meaning MT where an OS handles checking
conditions and some output actions and sequences are
coded as a thread with no consideration of the others
except knowing that the OS is being used simultaneously
by them too?
At 07:45 PM 6/1/97 -0500, you wrote:
>When you say cooperative multitasking, are you
>meaning MT where the code moves between any and
>all possible combinations of output states, waiting
>and testing at each one for conditions that say to
>go to a new output state and wait again?
Yes.
Oh, yes, and that the multiple tasks communicate with one another, forcing
them to idle or act upon a stimulus.
Interrupts are not required - not pre-emptive.
Also very easy to understand, as it is very deterministic. Therefore
rather easy to debug, document, etc.
And efficient in both code and time.
>Or, are you meaning MT where an OS handles checking
>conditions and some output actions and sequences are
>coded as a thread with no consideration of the others
>except knowing that the OS is being used simultaneously
>by them too?
Well, since there is no generic OS for these chips (as yet), obviously I
could not mean this in the Unix- or Amiga-like terms.
Andy
==================================================================
Andy Kunz - Montana Design - 409 S 6th St - Phillipsburg, NJ 08865
Hardware & Software for Industry & R/C Hobbies
"Go fast, turn right, and keep the wet side down!"
==================================================================
On Sun, Jun 01, 1997 at 07:45:23PM -0500, John Griessen wrote:
> When you say cooperative multitasking, are you
> meaning MT where the code moves between any and
> all possible combinations of output states, waiting
> and testing at each one for conditions that say to
> go to a new output state and wait again?
>
> Or, are you meaning MT where an OS handles checking
> conditions and some output actions and sequences are
> coded as a thread with no consideration of the others
> except knowing that the OS is being used simultaneously
> by them too?
I'm not sure I understand exactly what you are describing in
the first paragraph, but the second describes what is usually
called "preemptive" multitasking.
Cooperative multitasking is multitasking where a context switch
occurs only when the current task or thread decides it is prepared
to relinquish the CPU. This is usually done by calling an OS
function, e.g. Yield(), which will either return immediately if
no other task is ready to run, or perform a context switch if there
is another task ready.
Preemptive multitasking allows context switches to be triggered
by interrupts and other asynchronous events. Win32 is preemptive,
Win16 is cooperative. That's why Win3.1 gets stupid whenever a
program does something busy, like saving a file. Cooperative
multitasking is often well suited to embedded applications, because you
have complete control over every task, and can ensure that each task
is well-behaved.
Preemptive multitasking is more complex to implement, and more prone
to unexpected behaviour, but essential for a hosted OS that must be able
to run programs that may not be well behaved.
--
Clyde Smith-Stubbs | HI-TECH Software, | Voice: +61 7 3354 2411 TakeThisOuTclydeEraseMEspam_OUThtsoft.com | P.O. Box 103, Alderley, | Fax: +61 7 3354 2422 http://www.htsoft.com | QLD, 4051, AUSTRALIA. |
---------------------------------------------------------------------------
Download a FREE beta version of our new ANSI C compiler for the PIC
microcontroller! Point your WWW browser at http://www.htsoft.com/
>Oh, yes, and that the multiple tasks communicate with one another, forcing
>them to idle or act upon a stimulus.
>
>Interrupts are not required - not pre-emptive.
>
>Also very easy to understand, as it is very deterministic. Therefore
>rather easy to debug, document, etc.
>
>And efficient in both code and time.
>
The New Micros company has formalized that approach and called it
isostructure programming. They're claiming to ship
a chip with the language they call ISOMAX burned in
soon, plus they'll offer c code generators for translating
to other than the controllers they do, for a price.
I'm planning to copy their/your style for my foundry
control project, since they are 68hc11 products mostly.
The cooperative MT/ISOMAX method skips having a
complicated, memory consuming RTOS to buy and pay
royalties on. I like that.
At 11:20 AM 6/2/97 +1000, you wrote:
I'm not sure I understand exactly what you are describing in
the first paragraph, but the second describes what is usually
called "preemptive" multitasking.
Cooperative multitasking is multitasking where a context switch
occurs only when the current task or thread decides it is prepared
to relinquish the CPU. This is usually done by calling an OS
function, e.g. Yield(), which will either return immediately if
no other task is ready to run, or perform a context switch if there
is another task ready.
-snip-
--
Clyde Smith-Stubbs
++++++++++++++++++++++
I meant to describe in the first paragraph programming
like I do state machine design for chips, where you DO
know all the possible states of your program,(it may
be a big set), or
if you can't define all the states in a problem, you
separate that problem and use another processor to
handle it so that you CAN define all the states in
the program at hand. Then you dont need a preemptive
RTOS.
> > When you say cooperative multitasking, are you
> > meaning MT where the code moves between any and
> > all possible combinations of output states, waiting
> > and testing at each one for conditions that say to
> > go to a new output state and wait again?
> Cooperative multitasking is multitasking where a context switch
> occurs only when the current task or thread decides it is prepared
> to relinquish the CPU. This is usually done by calling an OS
> function, e.g. Yield(), which will either return immediately if
> no other task is ready to run, or perform a context switch if there
> is another task ready.
Unfortunately, no PIC (not even the 17Cxx) can at present handle the
general case of cooperative multi-tasking, where either/any process may
execute a yield() from within nested procedures. The normal method for
handling such task switching is to split the stack area into two or more
pieces; on the 8x51, a task switch (assuming two tasks) would then be
performed as:
Yield:
mov a,other_sp
xch a,sp
mov other_sp,a
ret
Calling Yield() will place the address following the call onto the stack,
save the stack pointer and point it to the other stack, and then work on
the other task. When that task calls Yield() the stack pointer will be
restored with its old value, so RETurning will resume execution of the
former task. Simple and very efficient.
The best a PIC can do is have one task with arbitrary procedure nesting
(up to the total stack limit) and have the other task(s) only yield at the
"top" level [not within a routine]. For a two-way task manager, I think
the following is probably the best approach (assuming the secondary task
fits into 256 bytes):
[general]
There needs to be a byte variable called "Task2PC", and PCLATH should
'always' [any time there's a task switch] be pointed at the page
containing task two.
[for task 1]
Yield should be a macro that reads as follows:
call DoYield
movwf Task2PC
The DoYield label should point to the code:
movf Task2PC,w
movwf PC
[for task 2]
Yield2 takes an argument, which is an address to go to once task 1
yields again. The Yield2 macro [if you want to use a macro] is simply:
retlw [address]
[example]
Task 1 is a general purpose who-knows what. Task 2 is a serial-port
receive routine. For this particular application, assume the DoYield
"routine" contains code to wait until the end of the current 1/3-bit-time
clock. Task2 might then look like the following [written to maximize
speed]:
[I think the overall code size would end up being around 50-60
instructions for the receive routine. Using a loop would save code space,
but would make the logic more complex.]
Pseudo-cooperative multitasking like the above can be very useful, and can
work quite effectively on a PIC (the total time to switch to and from the
second task is eight cycles). Unfortunately, for applications where both
tasks are complex, the requirement that the second task always be at
top-level whenever yielding control can make clear and efficient coding
difficult. Such jobs are perhaps better suited to other processors (alas)
such as the 8x51 or 68HCxx. For most tasks, however, the PIC is a
wonderful little chip.
>Unfortunately, no PIC (not even the 17Cxx) can at present handle the
>general case of cooperative multi-tasking, where either/any process may
>execute a yield() from within nested procedures. The normal method for
However, if one is wise, he will write his procedures such that the process
in question is safely completed, and he may with a state machine pick up
where he left off.
This is how I do it, anyway.
Andy
==================================================================
Andy Kunz - Montana Design - 409 S 6th St - Phillipsburg, NJ 08865
Hardware & Software for Industry & R/C Hobbies
"Go fast, turn right, and keep the wet side down!"
==================================================================
> >Unfortunately, no PIC (not even the 17Cxx) can at present handle the
> >general case of cooperative multi-tasking, where either/any process may
> >execute a yield() from within nested procedures. The normal method for
>
> However, if one is wise, he will write his procedures such that the process
> in question is safely completed, and he may with a state machine pick up
> where he left off.
>
> This is how I do it, anyway.
Right; sometimes that works well. On the other hand, which is easier to
read [compressed to save vertical space]:
void yield(void) /* Called by other procedure */
{
curr_function();
}
While this particular instance of Example Two could have been done
somewhat more nicely (taking advantage of the simplicity of 'test', adding
more functions to test (e.g. wait until character is input) would make the
Example Two method significantly more complicated while requiring only
simple additions to the code in Example One.
On machines that support it, cooperative multitasking via stack-switching
can be an efficient way to produce complex systems with reasonable,
readable code. The biggest wrinkle often comes with 'smart' compilers:
rather than using stack frames, many compilers use one of several
algorithms to allocate variables statically. Unfortunately, if such a
compiler isn't made aware that two routines may indirectly call each
other, it may overlay those routines' variables. Such errors can cause
many types of bizarre failures and can be hard to track down. Nonetheless,
when used as part of a sound design, cooperative multitasking on CPU's
that support it is often a good way to make systems both efficient and
maintainable.
Andy, I agree with John Payson's comments about trying to MT on a PIC. I
also agree with your comments below and that's pretty much how I do things.
This 16C74-based weather station I've been working has really become a
`test-bed' to see what I could do with the chip. What started out as an
efficient, interrupt-driven, state machine has `bloated' into a `patchwork'
of interrupts and polling... I'm about to `overhaul' the code for the new
16C77 and I've been taking fresh look at MT and the extra data and program
banks of the 77. I want to take a hard look at the limited stack and as well
as the 77's common 16 Bytes of RAM wich are aliased in all four banks. This
could provide a common message area for something like a MT `executive'
controller. I've been use to UNIX, an amazing Forth-based MT kernel running
on a 6809, and have been an Amiga Developer for 10yrs. I don't think the PIC
is suitable to that level of MT but I do think there are some good ideas to
out there. The 77 is a `new animal' as far as the aliased registers and I'm
looking forward to see what can be done.
>>Unfortunately, no PIC (not even the 17Cxx) can at present handle the
>>general case of cooperative multi-tasking, where either/any process may
>>execute a yield() from within nested procedures. The normal method for
>
>However, if one is wise, he will write his procedures such that the process
>in question is safely completed, and he may with a state machine pick up
>where he left off.
>
>This is how I do it, anyway.
>
>Andy
>
>==================================================================
>Andy Kunz - Montana Design - 409 S 6th St - Phillipsburg, NJ 08865
> Hardware & Software for Industry & R/C Hobbies
> "Go fast, turn right, and keep the wet side down!"
>==================================================================
>
>
> Andy, I agree with John Payson's comments about trying to MT on a PIC. I
>also agree with your comments below and that's pretty much how I do things.
Thanks for the feedback. I agree that if one chooses the hard way, it will
be hard. Done right, it's rather simple. SOunds like all three of us (and
others) are approaching a concensus.
Can we move on...?
Andy
==================================================================
Andy Kunz - Montana Design - 409 S 6th St - Phillipsburg, NJ 08865
Hardware & Software for Industry & R/C Hobbies
"Go fast, turn right, and keep the wet side down!"
==================================================================
No, we cant move on quite yet :). There is a article about this type of
thing in Embedded Systems Programing (a mag, June 97 issue). I was
wondering if this the exact type of thing you guys were discussing. The MT
system is a bunch of "machines" The machines are called like this
Main() //Main routine calls different state machines
{MachineOne();
MachineTwo();
MachineThree();
}
MachineOne() //Example machine
{
switchState(state)
{
case state1
{Do stuff here
state = state3
return to main
}
case state2
{Do stuff here
state = state1
return to main
}
case state3
{
Do stuff here
state = state1
return to main
}
}
}
and each machine is a state machine. The state machines each get a state
variable. The machine is called. It does whatever for that state. Then it
changes its state variable if necessary and returns to Main(). You can use
globel variables to leave notes about things for the next machine. Is this
the idea????
Anybody know of a good book on this stuff ??
JV
----------
> From: Andy Kunz <RemoveMEmontanaTakeThisOuTFAST.NET>
> To: PICLISTEraseME.....MITVMA.MIT.EDU
> Subject: Re: os/wars - a compilation - was Re: SoNoboby knows
> Date: Tuesday, June 03, 1997 6:21 AM
>
> > Andy, I agree with John Payson's comments about trying to MT on a
PIC. I
> >also agree with your comments below and that's pretty much how I do
things.
>
> Thanks for the feedback. I agree that if one chooses the hard way, it
will
> be hard. Done right, it's rather simple. SOunds like all three of us
(and {Quote hidden}
> others) are approaching a concensus.
>
> Can we move on...?
>
> Andy
>
> ==================================================================
> Andy Kunz - Montana Design - 409 S 6th St - Phillipsburg, NJ 08865
> Hardware & Software for Industry & R/C Hobbies
> "Go fast, turn right, and keep the wet side down!"
> ==================================================================
At 07:21 AM 6/3/97 -0400, you wrote:
>Thanks for the feedback. I agree that if one chooses the hard way, it will
>be hard. Done right, it's rather simple. SOunds like all three of us (and
>others) are approaching a concensus.
>
>Can we move on...?
Sure - does that mean we now consider multiple PICs on a single board
to process a wide word token stream, interleave a few FPGAs and a
few hundred FIFO's ?
Seriously guys (and gals) - I've used an ATMEL 2051 and HC11 as a
reasonable dual processer combo for some comms/display apps.
In my old days I had one design that used dual Z80B.
Anyone considered their solution would employ more than one PIC, and
as a result have any observations to offer ?
----------
> Nr: John Verberkmoes <EraseMEjohnvINXPRESS.NET>
> Jnls: RemoveMEPICLISTEraseMEEraseMEMITVMA.MIT.EDU
> Rel`: Re: os/wars - a compilation - was Re: SoNoboby knows
> D`r`: 4 h~m 1997 c. 1:25
>
> No, we cant move on quite yet :). There is a article about this type of
> thing in Embedded Systems Programing (a mag, June 97 issue). I was
> wondering if this the exact type of thing you guys were discussing. The
MT {Quote hidden}
> system is a bunch of "machines" The machines are called like this
>
> Main() //Main routine calls different state machines
> {MachineOne();
> MachineTwo();
> MachineThree();
> }
>
> MachineOne() //Example machine
> {
> switchState(state)
> {
> case state1
> {Do stuff here
> state = state3
> return to main
> }
> case state2
> {Do stuff here
> state = state1
> return to main
> }
> case state3
> {
> Do stuff here
> state = state1
> return to main
> }
> }
>
> }
>
>
> and each machine is a state machine. The state machines each get a state
> variable. The machine is called. It does whatever for that state. Then it
> changes its state variable if necessary and returns to Main(). You can
use
> globel variables to leave notes about things for the next machine. Is
this
> the idea????
Of couse :-) For the PIC16LC74 I do like this, without "call" , because
stack is only 8 :
MainLoop:
if(! event1) goto Next1
if(eventReady()) event1 = 0;
//Your sample of state mashine here (not on every event)
...
event2 = 1; //if needed
Next1: if(! event2) goto Next2;
...
Next2
goto MainLoop
Interrupt routune has the same structure, and I can start the events as
needed.
At 03:54 PM 6/3/97 -0400, you wrote:
>Sure - does that mean we now consider multiple PICs on a single board
>to process a wide word token stream, interleave a few FPGAs and a
>few hundred FIFO's ?
Actually, that's a very good point to bring up.
A good rule of thumb is, "If you ain't making tons of these, it's probably
cheaper to implement with multiple PICs each doing something small, than to
have one PIC do it all."
Andy
==================================================================
Andy Kunz - Montana Design - 409 S 6th St - Phillipsburg, NJ 08865
Hardware & Software for Industry & R/C Hobbies
"Go fast, turn right, and keep the wet side down!"
==================================================================
I considered it in a recent project, but ended up with a single PIC.
The application would have needed some transfer of data between the
2 PICs. It soon became apparent that they were going to spend more time
handing the data transfer than they were on their primary task.
So instead of 2 C84s, I went for a single C73.
Synergy does not apply to multi-processor systems. You always end up
with less than the sum of the parts because of the overhead of sharing
data.
On the subject of multi-processor systems, Mike Watson wrote:
>Synergy does not apply to multi-processor systems. You always end up
>with less than the sum of the parts because of the overhead of sharing
>data.
True, but don't knock multi-processor systems too hard. I was the chief
software / firmware architect on a professional computer-based system with
a HUGE User Interface that uses up to 16 synchronous 8MHz Z80s (and an
asynchronous 16MHz Z180, which came later, to handle very-high-speed comms)
all running in parallel and sharing data via a tightly-coupled
shared-memory scheme. 10 years later, one can hardly believe that such a
simple $2 processor is behind 350+ $100,000+ such systems currently in use
around the world today ...
I think a major factor in the continued success and continual development
of that product was the common shared-memory interface and the flexibility
thereof -- it can handle large or small data transfers with aplomb,
inter-Z80 communications are a piece of cake, and additions to the
systems's functionality are usually trivial (except for the
ever-diminishing amount of free codespace available ;-) ).
Of course this flexibility required a lot of coding and code space, which
speaks against all but those PICS with the ability to execute from external
memory.
___________________________________________
| Andrew E. Kalman, Ph.D. RemoveMEaekKILLspamnetcom.com |
| standard disclaimers apply |
|___________________________________________|