Serial port questions: queues

Started by arhodes19044 August 7, 2005
I have a project interfacing a hand-held GPS unit and displaying data
at higher numerical resolution than the GPS unit itself displays, and
then doing post-processing on the data.

I use Com1 to get data from the GPS unit. I do not need to send ANY
data to the unit. Com3 is used exclusively for output to an LCD
serial display.

I am running out of stack space when I reserve fairly large queues
(50-80 bytes)in an attempt to avoid losing data from the GPS, and
avoid having to wait to send data to the LCD.

1) If I never need to use a queue (input or output) for a particular
port, is it possible to avoid creating that queue? It seems that the
communications functions REQUIRE both queues, but maybe a dummy
variable could be given for the unused queue?

2) Can serial ports simultaneously send and recieve, I.e. Full
duplex? I think they can. Therefore it is possible to have
separate devices on the input and output lines. Of course they must
be running at the same baud rate. In my case, the LCD is 9600 and
the GPS is 4800 in the particular mode I am using (NMEA). So I must
use separate ports, and therefore I really need the answers to
question #1.

-Tony


arhodes19044 wrote:

> I am running out of stack space when I reserve fairly large queues
> (50-80 bytes)in an attempt to avoid losing data from the GPS, and
> avoid having to wait to send data to the LCD.
>
> 1) If I never need to use a queue (input or output) for a particular
> port, is it possible to avoid creating that queue? It seems that the
> communications functions REQUIRE both queues, but maybe a dummy
> variable could be given for the unused queue?

Yes you can for COM3. Simply define the port with a pin number of zero -
see DefineCom3().

>
> 2) Can serial ports simultaneously send and recieve, I.e. Full
> duplex? I think they can.

COM1 is implemented in hardware and so can be full duplex. COM3 is
implemented in software and so cannot be full duplex.

Mike



I had seen that I could assign a zero (null) for an input or output
pin. Having done that, can I set the "inputqueue" value to zero as
well? Can I set a queue on com1 to zero as well? I'd suspect that
for Com3, if the a input or output pin is zero, then the software
will not proceed further with checking or using the queue.

I would suppose that in the case of Com1, where we can not specifiy a
null pin for input or output, then we can not deactivate queue
access, so a valid queue would be necessary..... -Tony

--- In basicx@basi..., Mike Perks <basicx@a...> wrote:
> arhodes19044 wrote:
>
> > I am running out of stack space when I reserve fairly large queues
> > (50-80 bytes)in an attempt to avoid losing data from the GPS, and
> > avoid having to wait to send data to the LCD.
> >
> > 1) If I never need to use a queue (input or output) for a
particular
> > port, is it possible to avoid creating that queue? It seems that
the
> > communications functions REQUIRE both queues, but maybe a dummy
> > variable could be given for the unused queue?
>
> Yes you can for COM3. Simply define the port with a pin number of
zero -
> see DefineCom3().
>
> >
> > 2) Can serial ports simultaneously send and recieve, I.e. Full
> > duplex? I think they can.
>
> COM1 is implemented in hardware and so can be full duplex. COM3 is
> implemented in software and so cannot be full duplex.
>
> Mike


--- In basicx@basi..., Mike Perks <basicx@a...> wrote:
> > > 2) Can serial ports simultaneously send and recieve, I.e.
Full
> > duplex? I think they can.
>
> COM1 is implemented in hardware and so can be full duplex. COM3 is
> implemented in software and so cannot be full duplex.

I believe that this assertion is incorrect. If it were, there would
be frequent problem with missing incoming characters if one happened
to be sent from the remote while the BX-24 was in the midst of
transmitting a character. I believe that the Com3 "software UART"
is, in fact, full duplex and is interrupt driven. On each
interrupt, the BX-24 system firmware would look to see if a if
character reception is underway and, if so, if it is time to sample
the input line for the next bit to be received. If character
reception is not under way, the input line would be sampled to see
if start bit is present. Possibly during the same interrupt cycle,
the firmware would look to see if character transmission is underway
and, if so, if it is time to set the output line state for the next
bit to be transmitted. If no character is currently being sent it
would check the output queue to see if there is a character waiting
to be sent.

This is all conjecture, of course, so I could be dead wrong. One
way to test the theory is to simply jumper the output pin to the
input pin and send a stream of characters. If the received
characters match those sent then it is full duplex.

Don



--- In basicx@basi..., "arhodes19044" <spamiam@c...> wrote:
> Having done that, can I set the "inputqueue" value to zero as
> well? Can I set a queue on com1 to zero as well? I'd suspect
> that for Com3, if the a input or output pin is zero, then the
> software will not proceed further with checking or using the queue.
>
> I would suppose that in the case of Com1, where we can not
> specifiy a null pin for input or output, then we can not
> deactivate queue access, so a valid queue would be necessary.....

I believe that you must always provide a valid queue for both the
input queue and the output queue on the OpenCom() call. When you
won't be using one of them you can define a minimally sized queue
(10 bytes - 9 overhead, 1 data) for that purpose. At one time I
thought that you might be able to pass the same value for both the
input queue and the output queue but I don't believe this works
because I've seen evidence that BasicX sets certain bits in
a "flags" byte in the queue structure to indicate that the queue is
being used in certain ways. I'm almost certain that this is the
case for queues used with Com1 and it may be true for Com3 as well.

Don


Don Kinzer wrote:

> --- In basicx@basi..., Mike Perks <basicx@a...> wrote:
> > > > 2) Can serial ports simultaneously send and recieve, I.e.
> Full
> > > duplex? I think they can.
> >
> > COM1 is implemented in hardware and so can be full duplex. COM3 is
> > implemented in software and so cannot be full duplex.
>
> I believe that this assertion is incorrect. If it were, there would
> be frequent problem with missing incoming characters if one happened
> to be sent from the remote while the BX-24 was in the midst of
> transmitting a character.

I don't think I expressed this very well. What I meant was that COM1 is
handled in hardware by the chip UART so by its nature it can do both
send and receive simultaneously. COM3 is handled in software and so
BasicX gives the semblance of duplex using multitasking and interrupts.

Mike



I was afraid that the queues would get manipulated even if the S/W
ports have one of the IO pins defined as Null. If I were writing
the compiler, I might be tempted to test if the pin is null before
tesating or manipulating the queue data. For Com1, I could see that
one must have both IO queues enabled because both IO directions are
automatically enabled (I guess) I suppose it might be possible to
tell the compiler to avoid the use of one of the directions and
therefore never check the corresponding queue.

-Tony

--- In basicx@basi..., "Don Kinzer" <dkinzer@e...> wrote:
> --- In basicx@basi..., "arhodes19044" <spamiam@c...> wrote:
> > Having done that, can I set the "inputqueue" value to zero as
> > well? Can I set a queue on com1 to zero as well? I'd suspect
> > that for Com3, if the a input or output pin is zero, then the
> > software will not proceed further with checking or using the
queue.
> >
> > I would suppose that in the case of Com1, where we can not
> > specifiy a null pin for input or output, then we can not
> > deactivate queue access, so a valid queue would be necessary.....
>
> I believe that you must always provide a valid queue for both the
> input queue and the output queue on the OpenCom() call. When you
> won't be using one of them you can define a minimally sized queue
> (10 bytes - 9 overhead, 1 data) for that purpose. At one time I
> thought that you might be able to pass the same value for both the
> input queue and the output queue but I don't believe this works
> because I've seen evidence that BasicX sets certain bits in
> a "flags" byte in the queue structure to indicate that the queue
is
> being used in certain ways. I'm almost certain that this is the
> case for queues used with Com1 and it may be true for Com3 as well.
>
> Don



Tony, not sure if this is of any help but you can directly access the
Atmel's USART registers. I did this in my 9-Bit RS-TH9 multiprocessor
protocol. My routines provided no buffering but worked well for the
application and eliminated the queues...
Of course, this only works for COM1.

- Tom

--- In basicx@basi..., "arhodes19044" <spamiam@c...> wrote:
> I had seen that I could assign a zero (null) for an input or output
> pin. Having done that, can I set the "inputqueue" value to zero as
> well? Can I set a queue on com1 to zero as well? I'd suspect that
> for Com3, if the a input or output pin is zero, then the software
> will not proceed further with checking or using the queue.
>
> I would suppose that in the case of Com1, where we can not specifiy a
> null pin for input or output, then we can not deactivate queue
> access, so a valid queue would be necessary..... > -Tony



I actually NEED the queues since for output, I want to dump as many
charasters as fast as possible so I have less chance of missing GPS
input. And for input, I do not want to miss characters,
particularly not in the middle of a sentence, so a big queue is
really important. My post processing could be quite time-consuming,
especially if I add heavy duty math on position/speed calculations.

This is why I crashed the BX. I enlarged the queues too much and
ran out of stack space. It was not obvious when it happened at my
desk, because it would get thru a couple of display cycles before
crashing. And since I was not moving, I could not see immediately
that the display was not updating.

By judiciously improving on the built-in string conversion routines
to fit my customized needs, and more efficient (but less
maintainable) usage of string buffers, I was able to get quite a bit
of extra space. I probably have room to enlarge the queues more.
However I will not do so because I have not started dropping data
(yet).

Oddly, I was not able to improve meaningfully on CStr(). I did use
slightly less stack by a couple of bytes, but my code was longer
eventhough my function was very limited and customized and had no
error checking. So, I went back to the original function.

I did make significant improvements on the built-in functions of
cstringfloat() and cstringlong() by extensively limiting what it
does and no error checking. Very customized. Actually my
cstringlong() is really cstringint() because I will not be using
long integers.

-Tony

--- In basicx@basi..., "tombhandley" <gr13tbs@c...> wrote:
> Tony, not sure if this is of any help but you can directly access
the
> Atmel's USART registers. I did this in my 9-Bit RS-TH9
multiprocessor
> protocol. My routines provided no buffering but worked well for
the
> application and eliminated the queues...
> Of course, this only works for COM1.
>
> - Tom
>
> --- In basicx@basi..., "arhodes19044" <spamiam@c...> wrote:
> > I had seen that I could assign a zero (null) for an input or
output
> > pin. Having done that, can I set the "inputqueue" value to zero
as
> > well? Can I set a queue on com1 to zero as well? I'd suspect
that
> > for Com3, if the a input or output pin is zero, then the
software
> > will not proceed further with checking or using the queue.
> >
> > I would suppose that in the case of Com1, where we can not
specifiy a
> > null pin for input or output, then we can not deactivate queue
> > access, so a valid queue would be necessary.....
> >
> >
> > -Tony


arhodes19044 wrote:

> Oddly, I was not able to improve meaningfully on CStr(). I did use
> slightly less stack by a couple of bytes, but my code was longer
> eventhough my function was very limited and customized and had no
> error checking. So, I went back to the original function.

I am confused. CStr() is a polymorphic function that takes a variety of
numerical formats and converts them to a string. Under the covers there
are only actually four functions that do the work, CStringBoolean for
booleans, CStringFloat for single, CStringUnsignedLong for unsignedlong
and CStringLong for everything else. All the byte and integer types are
converted to a long before CStringLong is called.

>
> I did make significant improvements on the built-in functions of
> cstringfloat() and cstringlong() by extensively limiting what it
> does and no error checking. Very customized. Actually my
> cstringlong() is really cstringint() because I will not be using
> long integers.
>
Perhaps you can share your results for other people to use.

Mike