public inbox for ecos-bugs@sourceware.org
help / color / mirror / Atom feed
From: bugzilla-daemon@bugs.ecos.sourceware.org
To: unassigned@bugs.ecos.sourceware.org
Subject: [Bug 1001392] New: Generic 16x5x driver misses Rx timeout condition on LPC1765
Date: Thu, 24 Nov 2011 14:41:00 -0000	[thread overview]
Message-ID: <bug-1001392-777@http.bugs.ecos.sourceware.org/> (raw)

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 the assignee for the bug.


             reply	other threads:[~2011-11-24 14:41 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-11-24 14:41 bugzilla-daemon [this message]
2012-02-07 10:18 ` [Bug 1001392] " bugzilla-daemon
2011-11-24 14:41 [Bug 1001392] New: " bugzilla-daemon

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=bug-1001392-777@http.bugs.ecos.sourceware.org/ \
    --to=bugzilla-daemon@bugs.ecos.sourceware.org \
    --cc=unassigned@bugs.ecos.sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).