Really stupid serial IO question about interrupts

Go To Last Post
11 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi All, I'm sorry to post this here, but I can't find another forum and I have had no luck reaching anyone at NXP...

 

I am writing serial drivers for an NXP SC16IS752, which is a dual UART I have interfaced to an ATMEGA 1284P via I2C. The UART has big 64 byte FIFOs with programmable interrupt threshold. So when the receive threshold is crossed it signals and I come and fetch the data from the FIFOs. Pretty basic.

 

The problem I am having, at least the problem I'm having on the receiving side, is that if just a small amount of data comes in, the interrupt never fires and the data is never retrieved. I can set the trigger level as low as 4 bytes, but if I do that I lose much of the benefit of the big FIFO.

 

I'm sure I'm not the first person to run across this problem. What's the typical solution?

 

Any help would be greatly appreciated!

 

Thanks...

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Have you tried http://www.lpcware.com/forum ?

 

skyjumper wrote:
What's the typical solution?

One way is to have a timeout - so that, if you don't get an interrupt within the timeout period, you go and "manually" check what's in the FIFO...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Can this be considered as treason? smiley

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Can this be considered as treason? smiley 

 

Nah, it's just a UART, not a microcontroller...

 

In particular, this uart seems to generate a "time-out interrupt" 4 character times after the last byte has been received.  I'd prefer that to be configurable, but ... it's not bad.

I don't see any separate "enable" for the time-out interrupt (or for FIFO threshold interrupts.)  I'll chalk that up to bad documentation, and assume they're lumped into the rx/tx interrupts, though with a separate value in the "IIR" register...

 

7.7 When the UART receives a number of characters and these data are not enough to set off the receive interrupt (because they do not reach the receive trigger level), the UART will generate a time-out interrupt instead, 4 character times after the last character is received. The time-out counter will be reset at the center of each stop bit received or each time the receive FIFO is read.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:

Have you tried http://www.lpcware.com/forum ?

 

 

No I didn't find that one, I'll check it out thank you.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

westfw wrote:
In particular, this uart seems to generate a "time-out interrupt" 4 character times after the last byte has been received.  I'd prefer that to be configurable, but ... it's not bad.

I don't see any separate "enable" for the time-out interrupt (or for FIFO threshold interrupts.)  I'll chalk that up to bad documentation, and assume they're lumped into the rx/tx interrupts, though with a separate value in the "IIR" register...

 

 

Thanks! I see that listed on page 24 of the data sheet, but where is it explained? I guess I missed it, and still don't see it.

 

UPDATE: Oh, I found it, sec 7.7. Thanks!

 

 

Last Edited: Sun. Mar 15, 2015 - 03:23 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So after looking at my code and the data sheet I see that and time IIR[2] is set there is a receiver issue, either a timeout, a RHR or a Receive Line Status Error. My code was checking for that bit, but not then checking to see if the interrupt was due to an error. So i added that check. currently I'm ignoring the error but not attempting to read the FIFO.

 

What exactly does a status error mean? I searched the data sheet with no luck. I think it means there was some issue that prevented data from being read and so no new data was added to the FIFO, but in that event I'm not sure what action I should take. It does not seem reasonable to clear the FIFO. What do you guys suggest?

 

Thanks again...

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It said that the FIFO queues error status with the received bytes beginning of section 7:

Both the receiver and transmitter FIFOs can store up to 64 characters (including three additional bits of error status per character for the receiver FIFO)

But it also says you'll get an error interrupt whenever there are error bits ANYWHERE IN THE FIFO.   I can't tell what order...  (Heh.  But perhaps I can send your performance to hell by sending you a steam of buggy bits!)

I think you ALWAYS want to read all the characters from the FIFO.  (It's not clear what happens if you don't: will you get more timeout interrupts after the next character?  After the next 4 character-time idle?  Grr.)  What you do with the bytes that have errors attached is ... questionable.  Most async drivers these days seem to ignore most errors, assuming that either a human or higher-level protocol will notice the problem.

 

Dealing with the need for both buffering (for performance reasons) and responsiveness (to maintain interactivity) is a complex issue on uart receivers.  I gets worse when DMA is involved (you want a DMA controller that has SW-abortable transfers, or innate knowledge of uart timeouts, or something.)

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

westfw wrote:

It said that the FIFO queues error status with the received bytes beginning of section 7:

Both the receiver and transmitter FIFOs can store up to 64 characters (including three additional bits of error status per character for the receiver FIFO)

But it also says you'll get an error interrupt whenever there are error bits ANYWHERE IN THE FIFO.   I can't tell what order...  (Heh.  But perhaps I can send your performance to hell by sending you a steam of buggy bits!)

I think you ALWAYS want to read all the characters from the FIFO.  (It's not clear what happens if you don't: will you get more timeout interrupts after the next character?  After the next 4 character-time idle?  Grr.)  What you do with the bytes that have errors attached is ... questionable.  Most async drivers these days seem to ignore most errors, assuming that either a human or higher-level protocol will notice the problem.

 

Dealing with the need for both buffering (for performance reasons) and responsiveness (to maintain interactivity) is a complex issue on uart receivers.  I gets worse when DMA is involved (you want a DMA controller that has SW-abortable transfers, or innate knowledge of uart timeouts, or something.)

 

 

Thanks again. I don't check for errors in the driver. The driver just takes the data and adds it to the ring buffer. When i extract the data from the ring buffer I'm validating it then. The reason was because I wanted to do as little in the driver as possible, so I would spend less time in the ISR. Attacking it with a logic analyzer, it seems everything is working as it should.

 

On a related note, and this is probably an equally stupid question, once I put data in my data structure to be sent, how do I trigger the UART to generate an interrupt so the ISR is called? I know other UARTs will allow me to do that but this one does not seem to have that ability. It also does not have (that I can find) anything like a transmit buffer time out, which I guess makes sense. I'm currently manually disabling interrupts, calling the ISR routine like any other function, then enabling interrupts. Is this the best (or the only) course of action?

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

how do I trigger the UART to generate an interrupt so the ISR is called?

I've seen two common behaviors:

1) The TX interrupt means "transmitter has room" - a "level" state.  On an otherwise idle system, you'll get the first interrupt immediately after enabling both the interrupt and the transmitter (more common.)  The user-level "putc" function will need to enable the transmitter if it was not already running, and the tx service function will need to disable the transmitter when there is no more data.  This seems to be the more common style of UART these days.

2) The TX interrupt means "a byte has finished transmission" (or "a fifo threshold has been crossed) - a sort of "edge" trigger.  In this case, putc has to put the first character into the uart transmitter (IFF the uart isn't already transmitting), but when you run out of characters you can just stop.

 

I can't really tell from the datasheet which is going on with this chip.  The description:

THR  :  transmit FIFO empty (FIFO disable) or TX FIFO passes above trigger level (FIFO enable)

almost makes it sound as though its like (1) when not using the FIFO, and (2) when you are using the FIFO.   I'd guess (1), but you may need to experiment.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Okay thanks again. I thought it was 2, and I had not thought of 1. So I'll see if my trusty logic analyzer and I can get to the bottom of it. If it is 2 I guess I can use the FCR to re-enable the transmitter, and see if that kicks off the initial interrupt.