Page 1 of 2
UART is dropping bytes :(
Posted: Fri Jun 20, 2014 2:42 am
by russian
I am having more issues with UART driver - it looks like some bytes are being dropped either on read or on write

I've implemented a simple loopback thread in my firmware:
Code: Select all
while (TRUE) {
short c = (short) chSequentialStreamGet(chp);
consolePutChar((uint8_t) c);
}
I've written a tiny testing tool which sends, reads and compares bytes over serial
TwoWayTester.javaI've validated my USB-TTL devices and the testing tool by looping two USB-TTL devices - what I read is ALWAYS what I send.
I am also ALWAYS reading what I've send if I am using Chibi build-in serial-over-usb driver, so I am pretty sure the problem is around the UART driver.
I've tried increasing the buffer the way it helped the simulator -
viewtopic.php?f=2&t=1750 - but it did not help.
I am using 2.6.3 with seial_llc.c from 2.6 branch trunk to address
viewtopic.php?f=16&t=1976If needed I can improve my test code in order to figure out if the bytes are lost on read or on write. I will probably try the same test code with older releases because I kind of think some version in the past was pretty reliable in terms on UART.
Re: UART is dropping bytes :(
Posted: Fri Jun 20, 2014 4:48 am
by skute
I would suggest first checking the flags which get set on an error (overrun for example) by the serial driver. This could help narrow down the problem.
Also, the serial driver is byte by byte interrupt driven, if you know the data length that you are receiving it might be better to use the uart driver which uses DMA for the transfers.
Re: UART is dropping bytes :(
Posted: Fri Jun 20, 2014 4:56 am
by russian
Interesting, I cannot reproduce this issue with the demo projects. So, it's somehow related to my code. I see a lot of binary search in front of me

Where do I look for the flags? Somewhere within USART_TypeDef?
Re: UART is dropping bytes :(
Posted: Fri Jun 20, 2014 5:14 am
by skute
There is a similar topic which talks about the flags here:
http://forum.chibios.org/phpbb/viewtopic.php?f=2&t=810
Re: UART is dropping bytes :(
Posted: Fri Jun 20, 2014 2:02 pm
by russian
Is it appropriate to check for flags within the same loop as the 'chSequentialStreamGet'?
Like
Code: Select all
EventListener el1;
chEvtRegisterMask((EventSource *) chnGetEventSource(EFI_CONSOLE_UART_DEVICE), &el1, 1);
while (TRUE) {
short c = (short) chSequentialStreamGet(chp);
uint32_t flags;
chSysLock();
flags = chEvtGetAndClearFlagsI(&el1);
chSysUnlock();
if(flags & SD_OVERRUN_ERROR) {
firmwareError("serial overrun");
}
consolePutChar((uint8_t) c);
}
?
And yes, this check reports serial overrun if I compile with gcc. And not if I compile with IAR. Probably different amount of debug code and different performance, so it simply cannot keep up with the RX event flow?
Re: UART is dropping bytes :(
Posted: Fri Jun 20, 2014 2:30 pm
by Giovanni
Usually you get and clear the flags once after receiving an event notification.
Giovanni
Re: UART is dropping bytes :(
Posted: Fri Jun 20, 2014 7:22 pm
by skute
There is another uart echo example here:
http://forum.chibios.org/phpbb/viewtopic.php?f=4&t=1964. For my usage I had to modify the serial driver to use a circular dma buffer for rx with a timer capture/compare timeout to avoid losing characters (
http://www.st.com/st-web-ui/static/active/en/resource/technical/document/application_note/CD00256689.pdf).
Re: UART is dropping bytes :(
Posted: Sun Jun 22, 2014 2:23 am
by russian
By disabling different sections of the code and playing with serial buffer size I came to the conclusion that I am causing the issue by spending (wasting?) too much CPU - a piece of code like
Code: Select all
while(TRUE) {
chThdSleepMilliseconds(5);
}
would be enough to dramatically increase the chances of UART overrun. It looks like I was really overestimating the amount of CPU power available even in M4F.
While the ChibiOS demo application gets
Code: Select all
--- Test Case 11.4 (Benchmark, context switch)
--- Score : 2 509 608 ctxswc/S
--- Result: SUCCESS
I am currently getting only
Code: Select all
----------------------------------------------------------------------------
--- Test Case 1.4 (Benchmark, context switch)
--- Score : 471 536 ctxswc/S
--- Result: SUCCESS
I am still working on isolating which particular functionality in my code base is eating most of the performance.
An interesting observation so far is that #define CH_DBG_SYSTEM_STATE_CHECK TRUE alone drops the context switch benchmark by 40%:
default ChibiOS Demo with #define CH_DBG_SYSTEM_STATE_CHECK TRUE:
Code: Select all
--- Test Case 11.4 (Benchmark, context switch)
--- Score : 1 562 592 ctxswc/S
--- Result: SUCCESS
Which is probably related to the fact that dbg_check_enter_isr() does a full-scale lock/unlock to guard dbg_isr_cnt increment/decrement. Is it because
is not atomic on some/all compilers, or is it because we need the check and increment to be atomic in
Code: Select all
void dbg_check_enter_isr(void) {
port_lock_from_isr();
if ((dbg_isr_cnt < 0) || (dbg_lock_cnt != 0))
chDbgPanic("SV#8");
dbg_isr_cnt++;
port_unlock_from_isr();
}
?
Re: UART is dropping bytes :(
Posted: Sun Jun 22, 2014 2:50 am
by russian
I see, increment is not atomic in ARM.
How about
Code: Select all
inline void safe_increment(uint32_t *addr)
{
uint32_t new_value;
do
{
new_value = LDREXW(addr) + 1;
} while(STREXW(new_value, addr));
}
?
Re: UART is dropping bytes :(
Posted: Sun Jun 22, 2014 6:26 am
by Giovanni
The operation need to be atomic, this is why there are the lock and unlock. Note that the system checker adds a lot of code to the kernel, not just in that point, this is why the scores are lower when you enable it.
Giovanni