Discussion:
UART looses Bytes
(too old to reply)
Toennies Kai
2004-11-24 16:51:14 UTC
Permalink
Hi!

I try to receive data at 1MBaud on the UART using the receive interrupt.
I changed the oszillator, it is now 16MHz.
I do not use the Nut-OS routines for UART communication.
It all works fine, but sometimes(too often) I loose one or more bytes.
Something from the Nut-OS delays the uart receive interrupt.
This I could see on the oscilloscope.
The thing is, now I send byte after byte with no delay.
Later I will have 20?s between the startbits of two following bytes.
Will that be enough?
My receive interrupt routine takes no more than 5?s.

I would like to know, what is interfering me and how long it will take.
And if it might be disabled, for a period of time(complete telegramm).

Thanks in advance,
Kai T?nnies
Ole Reinhardt
2004-11-24 17:46:51 UTC
Permalink
Hi,
Post by Toennies Kai
I would like to know, what is interfering me and how long it will take.
And if it might be disabled, for a period of time(complete telegramm).
You could disable all interrupts after receiving the first byte and than
receive your data by polling. After receiving the last byte simply
reenable the interrupts...

If you does not use any NutOS code in your receiving routine Nothing
worse should happen... But perhaps you will loose other interrupts...
Anyway it is always a good idea return from an interrupt routine or from
a mutex section as fast as possible.


Regards,

Ole Reinhardt
--
kernel concepts Tel: +49-271-771091-14
Dreisbachstr. 24 Fax: +49-271-771091-19
D-57250 Netphen E+ : +49-177-7420433
--
Harald Kipp
2004-11-24 18:16:50 UTC
Permalink
Hello Kai,

Gosh, good question. That very much depends on what's going
on else in the system. For example, timer processing disables
interrupts and the duration depends on the number of times
to process.

20us is a lot of time and the UART hardware can buffer 2 bytes.
But still...roughly calculated, context switching takes about
7us on a 16 MHz ATmega with interrupts disabled almost all
the time.

You are receiving limited length telegrams, right? Wouldn't
it be better then to receive the full telegram in a single
interrupt call? This will block all other interrupts,
which is usually acceptable for Ethernet and Timer processing.

But I agree that this may not solve the problem for the
first two bytes of the telegram.

We had similar problems MP3 streaming and solved it by
explicitly disabling the MP3 interrupt and re-enabling
the global interrupt within the MP3 interrupt routine,
which takes quite long to process. This allows nesting
interrupts, which were required to continuously receive
PPP characters from the serial port. In this case you
should make sure, that the separate interrupt stack feature
is disabled.

One last idea: If you're using Ethernut 1 (with RTL8019),
then the interrupt routine in the driver can become
quite slow during overflow processing:

#if !defined(__AVR_ATmega128__) && !defined(__AVR_ATmega103__)
cbi(EIMSK, RTL_SIGNAL_IRQ);
sei();
#endif
NicOverflow();
#if !defined(__AVR_ATmega128__) && !defined(__AVR_ATmega103__)
cli();
sbi(EIMSK, RTL_SIGNAL_IRQ);
#endif

The part for allowing nested interrupts had been disabled
for AVR, because when this was done, Oliver's code didn't
allow interrupt nesting to that time. Try to remove the
#ifs.

Any other Nut/OS drivers you're using in your app?

Harald
Post by Toennies Kai
Hi!
I try to receive data at 1MBaud on the UART using the receive interrupt.
I changed the oszillator, it is now 16MHz.
I do not use the Nut-OS routines for UART communication.
It all works fine, but sometimes(too often) I loose one or more bytes.
Something from the Nut-OS delays the uart receive interrupt.
This I could see on the oscilloscope.
The thing is, now I send byte after byte with no delay.
Later I will have 20?s between the startbits of two following bytes.
Will that be enough?
My receive interrupt routine takes no more than 5?s.
I would like to know, what is interfering me and how long it will take.
And if it might be disabled, for a period of time(complete telegramm).
Thanks in advance,
Kai T?nnies
Matthias Ringwald
2004-11-25 10:26:09 UTC
Permalink
hi

short hint: as noted recently on this list:
if the rx irq is triggered up to 3 bytes are ready to read out, so
after reading the first
byte in the handler, just check the rxcomplete bit to see if there are
more bytes buffered.
this does give you a little relaxation, as if your irq is late, you're
saving let's say 4 IRQ
context switches while catching up.

despite that, I'm having trouble using 115200 on a 7.328 Mhz using the
nut driver.
Calculating the time of one byte there, I have roughly 300 uS
and still miss a byte in a while. (or 2000 instructions..)

(adding: I'm using two uarts and might also send and receive on both.
but I'm already


I still don't know what exactly is causing me pain.

As I'm not happy counting instructions, I will sooner or later have to
hook up an Oszi
and measure several routines. Candidates: NutThreadSwitch,
NutEventPostAsync, NutEventPost, NutTimerIRQ

I'm currently very suspicious about the NutEventPostAsync call and I'm
wondering
if replacing this function with another one, that justs enters the
specific queue
in a linked list (in O(1)).. this is similar to the re-use of timers in
the nut timer irq.

I did something like that in the unix_devs.c driver for other reasons.

read my other posting: usartavr.c rx complete irq improvementsuggestion

good luck
matthias
Post by Toennies Kai
Hi!
I try to receive data at 1MBaud on the UART using the receive
interrupt.
I changed the oszillator, it is now 16MHz.
I do not use the Nut-OS routines for UART communication.
It all works fine, but sometimes(too often) I loose one or more bytes.
Something from the Nut-OS delays the uart receive interrupt.
This I could see on the oscilloscope.
Toennies Kai
2004-11-24 16:51:14 UTC
Permalink
Hi!

I try to receive data at 1MBaud on the UART using the receive interrupt.
I changed the oszillator, it is now 16MHz.
I do not use the Nut-OS routines for UART communication.
It all works fine, but sometimes(too often) I loose one or more bytes.
Something from the Nut-OS delays the uart receive interrupt.
This I could see on the oscilloscope.
The thing is, now I send byte after byte with no delay.
Later I will have 20?s between the startbits of two following bytes.
Will that be enough?
My receive interrupt routine takes no more than 5?s.

I would like to know, what is interfering me and how long it will take.
And if it might be disabled, for a period of time(complete telegramm).

Thanks in advance,
Kai T?nnies
Ole Reinhardt
2004-11-24 17:46:51 UTC
Permalink
Hi,
Post by Toennies Kai
I would like to know, what is interfering me and how long it will take.
And if it might be disabled, for a period of time(complete telegramm).
You could disable all interrupts after receiving the first byte and than
receive your data by polling. After receiving the last byte simply
reenable the interrupts...

If you does not use any NutOS code in your receiving routine Nothing
worse should happen... But perhaps you will loose other interrupts...
Anyway it is always a good idea return from an interrupt routine or from
a mutex section as fast as possible.


Regards,

Ole Reinhardt
--
kernel concepts Tel: +49-271-771091-14
Dreisbachstr. 24 Fax: +49-271-771091-19
D-57250 Netphen E+ : +49-177-7420433
--
Harald Kipp
2004-11-24 18:16:50 UTC
Permalink
Hello Kai,

Gosh, good question. That very much depends on what's going
on else in the system. For example, timer processing disables
interrupts and the duration depends on the number of times
to process.

20us is a lot of time and the UART hardware can buffer 2 bytes.
But still...roughly calculated, context switching takes about
7us on a 16 MHz ATmega with interrupts disabled almost all
the time.

You are receiving limited length telegrams, right? Wouldn't
it be better then to receive the full telegram in a single
interrupt call? This will block all other interrupts,
which is usually acceptable for Ethernet and Timer processing.

But I agree that this may not solve the problem for the
first two bytes of the telegram.

We had similar problems MP3 streaming and solved it by
explicitly disabling the MP3 interrupt and re-enabling
the global interrupt within the MP3 interrupt routine,
which takes quite long to process. This allows nesting
interrupts, which were required to continuously receive
PPP characters from the serial port. In this case you
should make sure, that the separate interrupt stack feature
is disabled.

One last idea: If you're using Ethernut 1 (with RTL8019),
then the interrupt routine in the driver can become
quite slow during overflow processing:

#if !defined(__AVR_ATmega128__) && !defined(__AVR_ATmega103__)
cbi(EIMSK, RTL_SIGNAL_IRQ);
sei();
#endif
NicOverflow();
#if !defined(__AVR_ATmega128__) && !defined(__AVR_ATmega103__)
cli();
sbi(EIMSK, RTL_SIGNAL_IRQ);
#endif

The part for allowing nested interrupts had been disabled
for AVR, because when this was done, Oliver's code didn't
allow interrupt nesting to that time. Try to remove the
#ifs.

Any other Nut/OS drivers you're using in your app?

Harald
Post by Toennies Kai
Hi!
I try to receive data at 1MBaud on the UART using the receive interrupt.
I changed the oszillator, it is now 16MHz.
I do not use the Nut-OS routines for UART communication.
It all works fine, but sometimes(too often) I loose one or more bytes.
Something from the Nut-OS delays the uart receive interrupt.
This I could see on the oscilloscope.
The thing is, now I send byte after byte with no delay.
Later I will have 20?s between the startbits of two following bytes.
Will that be enough?
My receive interrupt routine takes no more than 5?s.
I would like to know, what is interfering me and how long it will take.
And if it might be disabled, for a period of time(complete telegramm).
Thanks in advance,
Kai T?nnies
Matthias Ringwald
2004-11-25 10:26:09 UTC
Permalink
hi

short hint: as noted recently on this list:
if the rx irq is triggered up to 3 bytes are ready to read out, so
after reading the first
byte in the handler, just check the rxcomplete bit to see if there are
more bytes buffered.
this does give you a little relaxation, as if your irq is late, you're
saving let's say 4 IRQ
context switches while catching up.

despite that, I'm having trouble using 115200 on a 7.328 Mhz using the
nut driver.
Calculating the time of one byte there, I have roughly 300 uS
and still miss a byte in a while. (or 2000 instructions..)

(adding: I'm using two uarts and might also send and receive on both.
but I'm already


I still don't know what exactly is causing me pain.

As I'm not happy counting instructions, I will sooner or later have to
hook up an Oszi
and measure several routines. Candidates: NutThreadSwitch,
NutEventPostAsync, NutEventPost, NutTimerIRQ

I'm currently very suspicious about the NutEventPostAsync call and I'm
wondering
if replacing this function with another one, that justs enters the
specific queue
in a linked list (in O(1)).. this is similar to the re-use of timers in
the nut timer irq.

I did something like that in the unix_devs.c driver for other reasons.

read my other posting: usartavr.c rx complete irq improvementsuggestion

good luck
matthias
Post by Toennies Kai
Hi!
I try to receive data at 1MBaud on the UART using the receive
interrupt.
I changed the oszillator, it is now 16MHz.
I do not use the Nut-OS routines for UART communication.
It all works fine, but sometimes(too often) I loose one or more bytes.
Something from the Nut-OS delays the uart receive interrupt.
This I could see on the oscilloscope.
Continue reading on narkive:
Loading...