This is the mail archive of the
ecos-bugs@sourceware.org
mailing list for the eCos project.
[Bug 1001392] New: Generic 16x5x driver misses Rx timeout conditionon LPC1765
- From: bugzilla-daemon at bugs dot ecos dot sourceware dot org
- To: ecos-bugs at ecos dot sourceware dot org
- Date: Thu, 24 Nov 2011 14:40:47 +0000
- Subject: [Bug 1001392] New: Generic 16x5x driver misses Rx timeout conditionon LPC1765
- Auto-submitted: auto-generated
Please do not reply to this email. Use the web interface provided at:
http://bugs.ecos.sourceware.org/show_bug.cgi?id=1001392
Summary: Generic 16x5x driver misses Rx timeout condition on
LPC1765
Product: eCos
Version: 3.0
Platform: All
OS/Version: Other
Status: UNCONFIRMED
Severity: enhancement
Priority: low
Component: Serial
AssignedTo: unassigned@bugs.ecos.sourceware.org
ReportedBy: bernard.fouche@kuantic.com
CC: ecos-bugs@ecos.sourceware.org
Class: Advice Request
Hello.
I've found an issue with the generic 16x5x serial driver while working
with a NXP LPC1765. The situation is the following: I'm doing the
usual program/flash/debug cycle. I work with eCos from CVS.
In some circumstances, I halt the target while there are pending
bytes in the Rx FIFO of a channel of the serial controller.
Then I 'soft reset' (using OpenOCD) the target to rerun the software
(of after reflashing code). At that point the serial driver may fall
in a never ending loop there (from
devs/serial/generic/16x5x/current/src/ser_16x5x.c):
SER_16X5X_READ_ISR(base, _isr);
while ((_isr & ISR_nIP) == 0) {
switch (_isr&0xE) {
case ISR_Rx:
case ISR_RxTO:
{
cyg_uint8 _lsr;
unsigned char c;
HAL_READ_UINT8(base+REG_lsr, _lsr);
while(_lsr & LSR_RSR) {
HAL_READ_UINT8(base+REG_rhr, c);
(chan->callbacks->rcv_char)(chan, c);
HAL_READ_UINT8(base+REG_lsr, _lsr);
}
break;
}
... more code ...
The code above assumes that the timeout condition (case ISR_RxTO) implies that
(_lsr & LSR_RSR) is also true, while with the LPC1765, I'm able to get a
timeout but ( _lsr & LSR_RSR) is false.
Here is _isr (aka IIR: Interrupt Indication Register) (on LPC1765
there are 4 bytes between each register, hence the x4 multiplier):
#define REG_isr SER_REG(2) // Interrupt status register
#define REG_lsr SER_REG(5) // Line status register
(gdb) printf "0x%08X=%X\n",base+(4*2),*(base+(4*2))
0x4009C008=CC
The lower byte (0x0C) shows:
- interrupt flag set (bit 0 value is 0)
- Character Time-out Indicator (bits 1-3: 110)
Here is _lsr:
(gdb) printf "0x%08X=%X\n",base+(4*5),*(base+(4*5))
0x4009C014=60
Bit 0 is zero: no character is ready for reading...
However emptying the Rx FIFO will reset the timeout condition.
If I manually read the data register...
(gdb) printf "0x%08X=%X\n",base+(4*0),*(base+(4*0))
0x4009C000=0
then the timeout condition is removed:
(gdb) printf "0x%08X=%X\n",base+(4*2),*(base+(4*2))
0x4009C008=C1
There are many different chips based on the 16550 design, with many
different bugs. It's difficult to know if this is a MCU bug or a
'feature' since I found no datasheet, whatever the manufacturer, explicitely
stating that a rx timeout condition must also raise bit 0 of LSR.
The proposed fix is very simple, just change de while() loop to a
do()while loop, to always read at least a byte from the FIFO :
while ((_isr & ISR_nIP) == 0) {
switch (_isr&0xE) {
case ISR_Rx:
case ISR_RxTO:
{
cyg_uint8 _lsr;
unsigned char c;
do{
HAL_READ_UINT8(base+REG_rhr, c);
(chan->callbacks->rcv_char)(chan, c);
HAL_READ_UINT8(base+REG_lsr, _lsr);
}
while(_lsr & LSR_RSR);
break;
}
It's even a bit quicker if a single byte is in the FIFO because _lsr is updated
only once.
--
Configure bugmail: http://bugs.ecos.sourceware.org/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are on the CC list for the bug.