[#5063] serial uart bfin_5xx.c stops receiving when RX buf wraps (patch included)
Submitted By: Tomasz Motylewski
Open Date
2009-04-09 04:26:14 Close Date
2010-06-11 04:43:21
Priority:
Medium High Assignee:
Sonic Zhang
Status:
Closed Fixed In Release:
N/A
Found In Release:
2008R1.5-RC3 Release:
head, branch-2008R1
Category:
Drivers Board:
STAMP
Processor:
ALL Silicon Revision:
0.2
Is this bug repeatable?:
Yes Resolution:
Fixed
Uboot version or rev.:
Toolchain version or rev.:
08r1.5-14 gcc 4.1.2
App binary format:
N/A
Summary: serial uart bfin_5xx.c stops receiving when RX buf wraps (patch included)
Details:
The patch blackfin.uclinux.org/git/?p=readonly-mirrors/linux-kernel.git;a=commitdiff;h=03869d610feefa6f531c24dc1e4c076d31151f25 fixes bugs [#4455] and [#4436] but a new bug appears:
when receiving small packets of characters sometimes data is not read until next character comes. This happens when the most recent character is exactly at the beginning of the RX buffer. In my case this stops the whole communication - application does not respond, so client does not send anymore till timeout.
What follows is the output of /sys/kernel/debug/blackfin/DMA Controller/DMA8_ ...
CURR_ADDR CURR_X_COUNT CURR_Y_COUNT
0x03f00200 0x0000 0x0000 system start, no chars received
0x03f00001 0x01ff 0x0008 1 character received
0x03f00202 0x01fe 0x0008 next character
0x03f001ff 0x0001 0x0008 next 509 chars
0x03f00200 0x0200 0x0007 next char
0x03f003ff 0x0001 0x0007 next 511 chars
0x03f00400 0x0200 0x0006 next char
0x03f00c00 0x0200 0x0002 next 2048 chars
0x03f00e00 0x0200 0x0001 next 512 chars
0x03f00e01 0x01ff 0x0001 next char
0x03f00fff 0x0001 0x0001 next 510 chars
0x03f01000 0x0000 0x0001 next char SUPRISE, SUPRISE, driver will not receive, expected 0x0200 0x0008
0x03f00001 0x01ff 0x0008 next char, back to normal
This behaviour is documented in BF537_HRM_whole_book_3.0.pdf page 5-15 and others.
To get above data I have enabled debugfs and set 115200 baud. I have sent data from by PC by:
dd if=big-file.txt of=/dev/ttyUSB0 bs=1 count=1 (here comes count in decimal)
I guess DMA8 is just my setup, you will have to find out which is used on your blackfin CPU.
My guess is that cause of [#4455] and [#4436] was not only race condition but also "0x03f01000 0x0000 0x0001" condition which is 100% reproducible when sending characters 1 by 1.
I have fixed and tested it using CURR_X, CURR_Y (see attached patch).
But I would like to suggest considering
if(CURR_Y_COUNT == 0)
return; // ... skip processing, no bytes till now
USE (CURR_ADDR-buffer_start)%buffer_size and delete whole CURR_*_COUNT insanity.
Best regards
Tomasz Motylewski
Wolf & Woelfel GmbH
www.wolf-woelfel.de/
Follow-ups
--- Tomasz Motylewski 2009-04-09 06:15:31
I would like to use this opportunity to request shortening poll time in the
driver. Current 20 ms latency is too long. See attached bfin_5xx.c-lowlat.diff
I have tested 2 patches I have attached together.
All was tested in 2008R1.5-RC3 with bfin_5xx.c (2008R1 + patch) and
linux-2.6.x/include/asm-blackfin/mach-bf*/bfin_serial_5xx.h copied from 2008R1
head. I am also attaching the whole patched bfin_5xx.c as is.
Release 0.3 BF537 works the same way.
--- Mike Frysinger 2009-04-09 06:37:01
doesnt the timeout occur only in the error case ? if that's true, you dont want
the timeout function firing when it shouldnt be and so it should stay at 50ms.
--- Tomasz Motylewski 2009-04-09 11:47:29
My understanding is that DMA interrupt only occurs when switching DMA
"lines". You may do test I have describen above checking
/proc/interrupts.
After receiving over 4 KB (often single characters) I have:
# cat /proc/interrupts
6: 24524759 BFIN Timer Tick
18: 8 BFIN_UART_RX
19: 291 BFIN_UART_TX
24: 3135 EMAC_RX
Err: 0
That means without "timeout" IRQ happens only every 512 bytes. Good
for throuput but not latency. Even at 115200 baud full load IRQs will only
happen about every 44 ms, while other function polls every 20 ms.
P.S. And please consider removing uart->rx_dma_nrows
--- Tomasz Motylewski 2009-04-09 11:57:26
clarification: in case "0x03f01000 0x0000 0x0001" the characters in
the buffer are NEVER received. "timeout" function simply ignores them
every time it is called. Only when (and if) next character comes, driver copies
the waiting + fresh character.
--- Sonic Zhang 2009-04-23 05:47:31
As Tomasz Motylewski mentioned, this bug is caused by irregular behavior of DMA
register CURR_X_COUNT and CURR_Y_COUNT when an auto restart uart rx DMA run to
last byte in DMA buffer, trigger the interrupt and stay at this possiton. The
status of current x and y is 0:7 instead of 512:8 or 0:8. The driver doesn't
take care of this case when calculating the position.
Fixed.
In addition, the poll interval is set based on normal keyboard input response
time. If you think it is too slow, you need to give a reasonable explanation.
--- Robin Getz 2009-04-23 09:48:02
Can you better define what you mean by "irregular behavior":
- not expected, but described properly in the HRM
- not expected, and not documented in the HRM
From what I can tell - this is the expected behavior per the HRM, and should
not be described as irregular.
-Robin
--- Sonic Zhang 2009-04-23 23:07:58
Yes, it is described in the DMA part of the HRM. Irregular here means the x and
y status at the last line is different from that of lines in the middle of a 2D
dma.
Files
Changes
Commits
Dependencies
Duplicates
Associations
Tags
File Name File Type File Size Posted By
bfin_5xx.c-dmafix.diff text/plain 4721 Tomasz Motylewski
bfin_5xx.c text/x-csrc 34897 Tomasz Motylewski
bfin_5xx.c-lowlat.diff text/plain 712 Tomasz Motylewski