Just for clarification on the UART Block Diagram (see UM)... 1. Do U0TSR & U0RSR actually representthe Tx & Rx FIFO buffers? I only see U0TSR & U0RSR illustrated here and I can't find any other documentation for it. Now concerning U0THR & U0RBR (data registers)... 2. Why do they both share the same memory address? I'd really like to know the purpose of this. 3. What will happen if the lpc receives a character while I'm writing to the transmit register? I ask this because currently, I'm having trouble running the serial port both ways (with interrupts) while sending replies and receiving command packets from the PC. Sometimes the protocol I'm using works. However, while debugging I always notice the lpc losing receiver bytes whenever communication goes wrong. I only observe this happening if the lpc's replying to a command packet and another command packet's coming in the same time. best regards, Leighton |
|
Questions on the UART Interface
Started by ●November 17, 2004
Reply by ●November 17, 20042004-11-17
At 08:55 PM 11/17/04 +0000, you wrote: >Now concerning U0THR & U0RBR (data registers)... >2. Why do they both share the same memory address? I'd really like >to know the purpose of this. Consider the R/W line an extra address bit if it helps. They don't share the same physical memory. The idea (from the 8250 on) is that since you never read the transmit register and never write the receive register that they can be distinguished simply by the state of the read line and save all that extra address space and decoding logic (also explains why the divisor latch is a banked register). These would be from the same school of chip designers that believe you never actually need to read setup registers. >3. What will happen if the lpc receives a character while I'm >writing to the transmit register? It's supposed to act just fine. >I ask this because currently, I'm having trouble running the serial >port both ways (with interrupts) while sending replies and receiving >command packets from the PC. Sometimes the protocol I'm using works. >However, while debugging I always notice the lpc losing receiver >bytes whenever communication goes wrong. I only observe this >happening if the lpc's replying to a command packet and another >command packet's coming in the same time. Are you sure it's not the other way around? I have seen a similar problem but I keep losing THRE interrupts. It appears they 'disappear' if the LPC receives a byte while the interrupt identification register was being read. I have a work-around that appears to at least reduce the problem (I've not had it reappear) that only reads the IIR once per interrupt. It behaves similarly to the documented race conditions on the LPC (particularly the timers) but I've not seen anybody report duplicating it yet. Needless to say, I'd like to know for sure what's going on with it and you seem to have come closest to duplicating the conditions I see it under (both interrupts active, transmit and receive happening simultaneously). Robert " 'Freedom' has no meaning of itself. There are always restrictions, be they legal, genetic, or physical. If you don't believe me, try to chew a radio signal. " Kelvin Throop, III |
Reply by ●November 17, 20042004-11-17
--- In , "Leighton Rowe" <leightonsrowe@y...> wrote: > > Just for clarification on the UART Block Diagram (see UM)... > 1. Do U0TSR & U0RSR actually representthe Tx & Rx FIFO buffers? I > only see U0TSR & U0RSR illustrated here and I can't find any other > documentation for it. No, they are the actual shift registers. U0TSR can be checked with U0LSR bit 6, TEMT. TEMT=0 => U0TSR is shifting out a byte, TEMT=1 => U0TSR is idle. The 16-byte FIFOs aren't shown in the figure, but would rather correspond to U0THR and U0RBR. For better documentation, Google for 16C550. > Now concerning U0THR & U0RBR (data registers)... > 2. Why do they both share the same memory address? I'd really like > to know the purpose of this. Writing to the address means writing to U0THR, and reading from the address means reading from U0RBR. They occupy the same address because Philips chose to be software compatible with the 16C550, which was designed to be hardware and software compatible with the 8250, which was designed at a time when I/O addresses apparently were very precious. For an even worse example of this mindset, see the Intel 8259 interrupt controller which occupies two(!) I/O addresses. > 3. What will happen if the lpc receives a character while I'm > writing to the transmit register? Nothing special, the receiver and transmitter work independently. But make sure that you don't miss any of them in your interrupt handler. > I ask this because currently, I'm having trouble running the serial > port both ways (with interrupts) while sending replies and receiving > command packets from the PC. Sometimes the protocol I'm using works. > However, while debugging I always notice the lpc losing receiver > bytes whenever communication goes wrong. I only observe this > happening if the lpc's replying to a command packet and another > command packet's coming in the same time. When you enable more than one interrupt in U0IER (such as both receive and transmit interrupt), you should in your interrupt handler check U0IIR to see what caused the interrupt. More than one interrupt can occur at a time, and the highest priority one is indicated in U0IIR. Pay close attention to the "Interrupt Reset" column in the UART0 Interrupt Handling table. When you have seen in U0IIR what caused the interrupt, you should handle it, and then do the action in the "Interrupt Reset" column to tell the UART that you have handled it. For a receive interrupt, the Interrupt Reset action is to read U0RBR, so it is a quite normal part of handling a receive interrupt. For a transmit interrupt, the reset action is simply reading U0IIR, which you have already done since you know it is a transmit interrupt. If you don't do the Interrupt Reset action in your interrupt handler for a pending interrupt, the UART will immediately interrupt again. So you can write your interrupt handler in two ways: a. Check U0IIR, handle the highest-priority pending interrupt, thereby doing the Interrupt Reset action, and return. If more than one interrupt was pending, the UART will immediately interrupt again, and then present the next-highest priority interrupt in U0IIR, and so on. This way is the easiest, and the best one if multiple simultaneous interrupts are rare. b. Check U0IIR, handle the highest-priority pending interrupt, thereby doing the Interrupt Reset action. Re-check U0IIR, and loop around if another interrupt is pending. When no more interrupts are pending, return. This way is better if multiple simultaneous interrupts are so likely that it pays off to save the multiple interrupt entry/exit code. Regards, Karl Olsen |
|
Reply by ●November 18, 20042004-11-18
At 10:07 PM 11/17/04 +0000, you wrote: >b. Check U0IIR, handle the highest-priority pending interrupt, >thereby doing the Interrupt Reset action. Re-check U0IIR, and loop >around if another interrupt is pending. When no more interrupts are >pending, return. This way is better if multiple simultaneous >interrupts are so likely that it pays off to save the multiple >interrupt entry/exit code. That's certainly the way it's supposed to work (and the way I have done it on 'real' 16550s) but when I do this on an LPC2106 with both transmit and receive interrupts I occasionally miss THRE interrupts (they just never occur). This only happens when receive is occurring at the same time as transmit (I used a simple echo test) and it only occurs infrequently (several 100K up to a megabyte or more of transmitted bytes before it would halt). The only explanation I have is an undocumented race condition in updating the IIR as it is being read but as I said in an earlier post I haven't seen any duplication. Changing to the less conventional one IIR read per interrupt seems to eliminate the problem but maybe all it does is reduce the probability. Leighton's symptoms appear to be similar to (but not the same as) what I've seen so I'm wondering if he hasn't run across the same underlying problem I have. The THRE interrupts are the only serial interrupts that do not re-assert if they are not serviced so they are particularly vulnerable. Robert " 'Freedom' has no meaning of itself. There are always restrictions, be they legal, genetic, or physical. If you don't believe me, try to chew a radio signal. " Kelvin Throop, III |
|
Reply by ●November 18, 20042004-11-18
Sorry for the delay guys, Point taken for the answers to 1,2, and 3. Thanks Karl & Robert. > Leighton's symptoms appear to be similar to (but not the same as) what I've > seen so I'm wondering if he hasn't run across the same underlying problem I > have. > > The THRE interrupts are the only serial interrupts that do not re- assert if > they are not serviced so they are particularly vulnerable. > Robert, I haven't yet seen the problem you described that's interestingly the opposite to what I'm getting. Debugging through the JTAG and using a serial port data logger I see all the receiver bytes coming in from the PC. I usually send up to 16 bytes per THRE & for the most part the lpc sends the reply packet correctly. But only in that special case I see the lpc not respond to the last command packet. It came across the receive line ok (logger) so the PC's ok. However on the lpc side I debug and see the packet looking truncated. Like some bytes got lost while receiving, which looks kinda wierd. I haven't yet seen the opposite happen b4. > a. Check U0IIR, handle the highest-priority pending interrupt, > thereby doing the Interrupt Reset action, and return. If more than > one interrupt was pending, the UART will immediately interrupt again, > and then present the next-highest priority interrupt in U0IIR, and so > on. This way is the easiest, and the best one if multiple > simultaneous interrupts are rare. > > b. Check U0IIR, handle the highest-priority pending interrupt, > thereby doing the Interrupt Reset action. Re-check U0IIR, and loop > around if another interrupt is pending. When no more interrupts are > pending, return. This way is better if multiple simultaneous > interrupts are so likely that it pays off to save the multiple > interrupt entry/exit code. Interesting stuff Karl. I wasn't really paying attention to the IIR table. So, I'll have to review my code just incase I did a bit too much for RDA & THRE. Basically, the code I'm using is following Plan B. Bill Knight's code follows the same concept too. I'll give Plan A a try though, since my PC <-> lpc communication is on a small scale, and Robert's having more success with it. |
|
Reply by ●November 18, 20042004-11-18
At 02:15 PM 11/18/04 +0000, you wrote: > > Leighton's symptoms appear to be similar to (but not the same as) >what I've > > seen so I'm wondering if he hasn't run across the same underlying >problem I > > have. > > > > The THRE interrupts are the only serial interrupts that do not re- >assert if > > they are not serviced so they are particularly vulnerable. > > > >Robert, I haven't yet seen the problem you described that's >interestingly the opposite to what I'm getting. Debugging through >the JTAG and using a serial port data logger I see all the receiver >bytes coming in from the PC. I usually send up to 16 bytes per THRE >& for the most part the lpc sends the reply packet correctly. But >only in that special case I see the lpc not respond to the last >command packet. It came across the receive line ok (logger) so the >PC's ok. However on the lpc side I debug and see the packet looking >truncated. Like some bytes got lost while receiving, which looks >kinda wierd. I haven't yet seen the opposite happen b4. I had a thought. If my speculation about a race condition in IIR is correct it may well explain both our problems. In my case I lose the THRE interrupt and thus stop transmitting. In your case you lose a receive interrupt and drop a character. My test wouldn't catch a dropped character since I wasn't running any sort of check or comparison so all I would see is if the echo stopped cold (if a receive interrupt was missed it would just pick up the next one). Do you know (and can you tell) if the packet is truncated or maybe just missing characters from its body? If it always just characters at the end I'm less optimistic about the race condition. If it is a race in the IIR then a single read per interrupt might help (or it might not) depending on the details of the race and the timing (ICK). In any case let us know how changing to a single IIR read per interrupt affects the problem. Robert " 'Freedom' has no meaning of itself. There are always restrictions, be they legal, genetic, or physical. If you don't believe me, try to chew a radio signal. " Kelvin Throop, III |
|
Reply by ●November 18, 20042004-11-18
> Do you know (and can you tell) if the packet is truncated or maybe just > missing characters from its body? If it always just characters at the end > I'm less optimistic about the race condition. Well after double checking & changing my code to the single IIR read concept, things remained the same. The affected packet I receive always get's somewhat truncated in the middle, with the last bytes showing up a few bytes earlier than expected. I however notice LSR interrupt occuring at the point where the problem occurs but I don't see any signs of any LSR errors. Just a crazy question though...can the UART ISR interrupt itself? (eg. while processing a THRE an RDA interrupt comes in) Should I enable the FIFOs (write 1 to U0FCR) before running the interrupts? I seem to be getting by without this up until this point. Thanks again, Leighton |
|
Reply by ●November 18, 20042004-11-18
At 07:00 PM 11/18/04 +0000, you wrote: > > Do you know (and can you tell) if the packet is truncated or maybe >just > > missing characters from its body? If it always just characters at >the end > > I'm less optimistic about the race condition. > >Well after double checking & changing my code to the single IIR read >concept, things remained the same. The affected packet I receive >always get's somewhat truncated in the middle, with the last bytes >showing up a few bytes earlier than expected. Well that fits with the speculation of an IIR race condition. Doesn't prove it but it does fit. You may have duplicated what I've been seeing. >I however notice LSR interrupt occuring at the point where the >problem occurs but I don't see any signs of any LSR errors. Hmmm... Doesn't make much sense to me either. Maybe instead of a simple race the source is being miss-classified? My own test would not have seen a difference between that and the interrupt simply dissappearing. >Just a crazy question though...can the UART ISR interrupt itself? >(eg. while processing a THRE an RDA interrupt comes in) At the very least that would require that you re-enable the associated interrupt (IRQ or FIQ) and if vectored through the VIC you would also have to acknowledge the vectored interrupt with the appropriate write to the VIC first as well. If you've done that, try it again w/o re-enabling the interrupts. >Should I enable the FIFOs (write 1 to U0FCR) before running the >interrupts? I seem to be getting by without this up until this point. I don't see why that would eliminate the problem. Worse it might hide it so that it showed up later under less benign conditions. Curiouser and curiouser Robert " 'Freedom' has no meaning of itself. There are always restrictions, be they legal, genetic, or physical. If you don't believe me, try to chew a radio signal. " Kelvin Throop, III |
|
Reply by ●November 18, 20042004-11-18
> >Should I enable the FIFOs (write 1 to U0FCR) before running the > >interrupts? I seem to be getting by without this up until this point. > > I don't see why that would eliminate the problem. Worse it might hide it > so that it showed up later under less benign conditions. > Good news...I got communication running alot better after enabling FIFOs (U0FCR = 1) at startup. So far, no Rx & Tx glitches yet. Try doing the same to see what happens. For now the LSR mystery is worth forgetting. Leighton |
|
Reply by ●November 18, 20042004-11-18
At 08:02 PM 11/18/04 +0000, you wrote: > > >Should I enable the FIFOs (write 1 to U0FCR) before running the > > >interrupts? I seem to be getting by without this up until this >point. > > > > I don't see why that would eliminate the problem. Worse it might >hide it > > so that it showed up later under less benign conditions. > > > >Good news...I got communication running alot better after enabling >FIFOs (U0FCR = 1) at startup. So far, no Rx & Tx glitches yet. Try >doing the same to see what happens. That rather worries me. I will give it try and see what it does on my code though (I've got a few other items to take care of first). I place it in the same category as my read-IIR-only-once-per-interrupt 'fix' though. I strongly suspect it's only masking temporarily whatever the underlying cause is. I suspect there is something similar going on here as happens with the SPI and the timers. We've now got two independent reports of missing interrupts on the UART with no clear source of the problem. Robert " 'Freedom' has no meaning of itself. There are always restrictions, be they legal, genetic, or physical. If you don't believe me, try to chew a radio signal. " Kelvin Throop, III |