multitasking problem

Started by gvartani June 18, 2005
Background
I have written a main program that is intended to read GPS text as a
task (140 task stack) and run an xbotx. For my bot I am using code
that came from Netmedia xbotx. The servo driver module calls a public
task within the sub "ServoTask" (25 task stack). This task is
dimensioned as private within the module.
Current problem
In my main program I directly call the GPS task and I directly call
the servo driver sub that calls the ServoTask. When I run the program
I don't get sensible results. The ServoTask doesn't complete and the
program stops. If I comment out calls to each task one at a time the
program runs successfully for that only one task given the stack size
and sleep time. However, when I call the two tasks together the
program stops. I have also added sleep time after each task call and
at the start of each task. What am I doing wrong? I think my setup
doesn't allow both tasks to run freely, but I am not sure what is
wrong. By the way, I am not using semaphores or lock task, because I
am not sharing variables between tasks. Thanks.



Don Kinzer wrote:

> --- In basicx@basi..., "gvartani" <gvartani@c...> wrote:
> > Background
> > I have written a main program that is intended to read GPS text as a
> > task (140 task stack) and run an xbotx. For my bot I am using code
> > that came from Netmedia xbotx. The servo driver module calls a
> public
> > task within the sub "ServoTask" (25 task stack). This task is
> > dimensioned as private within the module.
>
> It is difficult to perform diagnosis remotely, especially with no
> source code to inspect. Although your description does provide some
> information there is much left unsaid.
>
> Unless the servo task is not doing much, 25 bytes may be too little
> stack space. You might want to use Mike Perks' analysis program to se
> if it may be of help:
> http://home.austin.rr.com/perks/basicx/bxDism


Don is right. The smallest reasonable stack size is 45 bytes. Remember
that BasicX swallows the first 15 bytes of your stack for the task
header so this only leave 30 bytes for your task. Try out the bxDism
program and I think the results will give you some very good insights
into where you program is using RAM.

With the limited RAM available to BasicX (until chips become available
with more), you can expect to have most 2 tasks in addition to the main
task. The exception is the BX-01 that can have up to 64K RAM but you
lose virtually all the other I/O facilities.

Mike



--- In basicx@basi..., "gvartani" <gvartani@c...> wrote:
> Background
> I have written a main program that is intended to read GPS text as a
> task (140 task stack) and run an xbotx. For my bot I am using code
> that came from Netmedia xbotx. The servo driver module calls a
public
> task within the sub "ServoTask" (25 task stack). This task is
> dimensioned as private within the module.

It is difficult to perform diagnosis remotely, especially with no
source code to inspect. Although your description does provide some
information there is much left unsaid.

Unless the servo task is not doing much, 25 bytes may be too little
stack space. You might want to use Mike Perks' analysis program to se
if it may be of help:
http://home.austin.rr.com/perks/basicx/bxDism

Don


I nearly went nuts trying to resolve tasking issues on
the LCDX until I realised that the it was sharing IO
for the keyboard and LCD. Thus I suspect if the tasks
are sharing IO these need to be made thread safe just
like shared variables.

Macka

--- Mike Perks <basicx@basi...> wrote:

> Don Kinzer wrote:
>
> > --- In basicx@basi..., "gvartani"
> <gvartani@c...> wrote:
> > > Background
> > > I have written a main program that is intended
> to read GPS text as a
> > > task (140 task stack) and run an xbotx. For my
> bot I am using code
> > > that came from Netmedia xbotx. The servo driver
> module calls a
> > public
> > > task within the sub "ServoTask" (25 task stack).
> This task is
> > > dimensioned as private within the module.
> >
> > It is difficult to perform diagnosis remotely,
> especially with no
> > source code to inspect. Although your description
> does provide some
> > information there is much left unsaid.
> >
> > Unless the servo task is not doing much, 25 bytes
> may be too little
> > stack space. You might want to use Mike Perks'
> analysis program to se
> > if it may be of help:
> > http://home.austin.rr.com/perks/basicx/bxDism > Don is right. The smallest reasonable stack size is
> 45 bytes. Remember
> that BasicX swallows the first 15 bytes of your
> stack for the task
> header so this only leave 30 bytes for your task.
> Try out the bxDism
> program and I think the results will give you some
> very good insights
> into where you program is using RAM.
>
> With the limited RAM available to BasicX (until
> chips become available
> with more), you can expect to have most 2 tasks in
> addition to the main
> task. The exception is the BX-01 that can have up to
> 64K RAM but you
> lose virtually all the other I/O facilities.
>
> Mike >
> Yahoo! Groups Links > basicx-unsubscribe@basi...


Send instant messages to your online friends http://au.messenger.yahoo.com



I have run these tasks individually, and they seem to be fine when
run individually with their respective stack size. Also, the servo
task is from a program Netmedia ships with their xbotx (good
credibility there). This is what happens, my servo task has two "if
statements" to check the enabled state of the motors (true or false)
if true then it calls pulse out as follows...

Private Sub ServoTask()
' This produces a pulse rate of about 50 Hz.
Const DeadTime As Integer = 10

Do
If (LEnabled) Then
Call PulseOut(LeftServoPin, LPosition + LTrimCount, 1)
End If
If (REnabled) Then
Call PulseOut(RightServoPin, RPosition - RTrimCount, 1)
End If
Call Sleep(DeadTime)
Loop

End Sub

The problem occurs when LEnabled and REnabled are true and the GPS
is sending data at the same time. If I am not reading GPS data all
is fine, but if I am reading GPS data and the above mentioned
parameters are true, my GPS data (read from another task) gets
completely clobbered. Is there anyway a call to PulseOut sent via
pins 5 and 6 can affect GPS input data, which is read at pin 20?
Thanks, Gerald
--- In basicx@basi..., Rod McKenzie <mrrmckenzie@y...> wrote:
> I nearly went nuts trying to resolve tasking issues on
> the LCDX until I realised that the it was sharing IO
> for the keyboard and LCD. Thus I suspect if the tasks
> are sharing IO these need to be made thread safe just
> like shared variables.
>
> Macka
>
> --- Mike Perks <basicx@a...> wrote:
>
> > Don Kinzer wrote:
> >
> > > --- In basicx@basi..., "gvartani"
> > <gvartani@c...> wrote:
> > > > Background
> > > > I have written a main program that is intended
> > to read GPS text as a
> > > > task (140 task stack) and run an xbotx. For my
> > bot I am using code
> > > > that came from Netmedia xbotx. The servo driver
> > module calls a
> > > public
> > > > task within the sub "ServoTask" (25 task stack).
> > This task is
> > > > dimensioned as private within the module.
> > >
> > > It is difficult to perform diagnosis remotely,
> > especially with no
> > > source code to inspect. Although your description
> > does provide some
> > > information there is much left unsaid.
> > >
> > > Unless the servo task is not doing much, 25 bytes
> > may be too little
> > > stack space. You might want to use Mike Perks'
> > analysis program to se
> > > if it may be of help:
> > > http://home.austin.rr.com/perks/basicx/bxDism
> >
> >
> > Don is right. The smallest reasonable stack size is
> > 45 bytes. Remember
> > that BasicX swallows the first 15 bytes of your
> > stack for the task
> > header so this only leave 30 bytes for your task.
> > Try out the bxDism
> > program and I think the results will give you some
> > very good insights
> > into where you program is using RAM.
> >
> > With the limited RAM available to BasicX (until
> > chips become available
> > with more), you can expect to have most 2 tasks in
> > addition to the main
> > task. The exception is the BX-01 that can have up to
> > 64K RAM but you
> > lose virtually all the other I/O facilities.
> >
> > Mike
> >
> >
> >
> > Yahoo! Groups Links
> >
> >
> > basicx-unsubscribe@basi...
> >
> >
> >
> >
> > Send instant messages to your online friends
http://au.messenger.yahoo.com


--- In basicx@basi..., "gvartani" <gvartani@c...> wrote:
> Is there anyway a call to PulseOut sent via pins 5 and 6
> can affect GPS input data, which is read at pin 20?

What routine are you using to read the GPS data on pin 20?

Don



Don,

I am using the routine provided by Basicx folks at the following
website: http://www.basicx.com/Products/BX-24/bx-24appnotes.htm
It is called GPS_Text_Decoder.zip

I have modified a few lines for it to run as a task with a task stack
of 100 and am not reading or printing all the data the code provides.
I only read Lon and Lat. I have created two public variables Lon and
Lat that I write data to. That way my main program can read them.
This
runs just fine until I enable my servos and have PulseOut active.

--- In basicx@basi..., "Don Kinzer" <dkinzer@e...> wrote:
> --- In basicx@basi..., "gvartani" <gvartani@c...> wrote:
> > Is there anyway a call to PulseOut sent via pins 5 and 6
> > can affect GPS input data, which is read at pin 20?
>
> What routine are you using to read the GPS data on pin 20?
>
> Don


gvartani wrote:

> I have run these tasks individually, and they seem to be fine when
> run individually with their respective stack size. Also, the servo
> task is from a program Netmedia ships with their xbotx (good
> credibility there). This is what happens, my servo task has two "if
> statements" to check the enabled state of the motors (true or false)
> if true then it calls pulse out as follows...
>
> Private Sub ServoTask()
> ' This produces a pulse rate of about 50 Hz.
> Const DeadTime As Integer = 10
>
> Do
> If (LEnabled) Then
> Call PulseOut(LeftServoPin, LPosition + LTrimCount, 1)
> End If
> If (REnabled) Then
> Call PulseOut(RightServoPin, RPosition - RTrimCount, 1)
> End If
> Call Sleep(DeadTime)
> Loop
>
> End Sub
>
> The problem occurs when LEnabled and REnabled are true and the GPS
> is sending data at the same time. If I am not reading GPS data all
> is fine, but if I am reading GPS data and the above mentioned
> parameters are true, my GPS data (read from another task) gets
> completely clobbered. Is there anyway a call to PulseOut sent via
> pins 5 and 6 can affect GPS input data, which is read at pin 20?
> Thanks, Gerald

I think Don is on the right track. Your problem is either a clash of
resources or a clash of resources ;)

What resources you may ask. There are 3 cases:

1. Clash of AVR chip resources e.g. both trying to use Timer1 (this is
behind Don's question).

2.. Clash of Memory resources e.g. the tasks are exhausting their
respective task stacks and overwriting memory. There is no checking in
the BasicX runtime for this so a task can merrily overwrite any portion
of memory and "clobber" other memory. Again did you try running bxDism
to get a handle on memory usage? Three tasks (main, servo and GPS)
starts to stretch the BX-24 memory resources.

3. Clash of shared memory e.g. the tasks have shared memory like a flag
and one is overwriting while the other is reading. The solution is to
setup a queue or a semaphore to protect this shared resource.

Mike


Mike,

Thanks for elaborating on the issue.
1. As far as AVR chip resources, how do I avoid a clash?
2. I haven't run bxDism yet; I will have to run it tonight.
3. I will setup semaphores tonight and test the program, before I
run bxDism. I have used semaphores in the past a couple of times
only when I was using the same variable to read and write data.
That's why I didn't even think of the memory usage aspect of it in
terms of other tasks writing to the same memory location regardless
of the name of the variable.

I won't have updates till late this evening but will definitely
share what I find out.

Thanks again,
Gerald

--- In basicx@basi..., Mike Perks <basicx@a...> wrote:
> gvartani wrote:
>
> > I have run these tasks individually, and they seem to be fine
when
> > run individually with their respective stack size. Also, the
servo
> > task is from a program Netmedia ships with their xbotx (good
> > credibility there). This is what happens, my servo task has
two "if
> > statements" to check the enabled state of the motors (true or
false)
> > if true then it calls pulse out as follows...
> >
> > Private Sub ServoTask()
> > ' This produces a pulse rate of about 50 Hz.
> > Const DeadTime As Integer = 10
> >
> > Do
> > If (LEnabled) Then
> > Call PulseOut(LeftServoPin, LPosition + LTrimCount, 1)
> > End If
> > If (REnabled) Then
> > Call PulseOut(RightServoPin, RPosition - RTrimCount,
1)
> > End If
> > Call Sleep(DeadTime)
> > Loop
> >
> > End Sub
> >
> > The problem occurs when LEnabled and REnabled are true and the
GPS
> > is sending data at the same time. If I am not reading GPS data
all
> > is fine, but if I am reading GPS data and the above mentioned
> > parameters are true, my GPS data (read from another task) gets
> > completely clobbered. Is there anyway a call to PulseOut sent via
> > pins 5 and 6 can affect GPS input data, which is read at pin 20?
> > Thanks, Gerald
>
> I think Don is on the right track. Your problem is either a clash
of
> resources or a clash of resources ;)
>
> What resources you may ask. There are 3 cases:
>
> 1. Clash of AVR chip resources e.g. both trying to use Timer1
(this is
> behind Don's question).
>
> 2.. Clash of Memory resources e.g. the tasks are exhausting their
> respective task stacks and overwriting memory. There is no
checking in
> the BasicX runtime for this so a task can merrily overwrite any
portion
> of memory and "clobber" other memory. Again did you try running
bxDism
> to get a handle on memory usage? Three tasks (main, servo and GPS)
> starts to stretch the BX-24 memory resources.
>
> 3. Clash of shared memory e.g. the tasks have shared memory like a
flag
> and one is overwriting while the other is reading. The solution is
to
> setup a queue or a semaphore to protect this shared resource.
>
> Mike


--- In basicx@basi..., "gvartani" <gvartani@c...> wrote:
> I am using the routine provided by Basicx folks at the following
> website: http://www.basicx.com/Products/BX-24/bx-24appnotes.htm
> It is called GPS_Text_Decoder.zip

Unfortunately, that is a problem.

The referenced code uses Com3 which uses a "software UART" (as
opposed to Com1 which uses a hardware UART). All UARTs rely on
precise timing in order to properly transmit and receive
characters. Software UARTs, in particular, require that the
processor be allowed to service interrupts regularly so that the
software can sample the input line and change the output line at the
right times. Consequently, when you're using Com3 you can't perform
any other operations that disable interrupts for more than about 25%
of the bit time. Many of the BasicX I/O routines that implement
precise timing (e.g. PulseIn(), PulseOut(), etc.) disable interrupts
in order to obtain the required precision.

If you're running the port at 19,200 baud, one bit time is about
52uS. That means that you can't, for example, call PulseOut() to
generate a pulse longer than about 12uS or you risk garbling the
serial data coming or going. If you can do so, it would help to
reduce the speed of COM3. At 1200 baud, for example, a bit time is
about 830uS. At that speed you could tolerate periods of 200uS or
so with interrupts disabled.

Depending on what else you're trying to do, you may be able to
switch to Com1. Using the hardware UART still requires interrupts
to be serviced but the processor only needs to service the hardware
UART for incoming characters every 10 bit times. Outgoing
characters from a hardware UART will never be affected by having
interrupts disabled.

An alternate strategy is to off-load the pulse generation to
external hardware. This can be done using a "one shot" like the
74HC123 or even the ubiquitous 555 timer. Depending on how precise
the timing and width of your pulses must be and the minimum duration
you may also be able to generate the required pulses in software
using PutPin().

Don