Yahoo Groups archive

Lpc2000

Index last updated: 2026-04-28 23:31 UTC

Message

Re: [lpc2000] Re: Problems w/ UART

2004-10-08 by Robert Adsett

At 08:44 PM 10/8/04 +0000, you wrote:
> > OK, but where in the interrupt?
>The first line of code that should always be executed.
This may seem obtuse, but first line of C or asm?  A good optimizer on the 
ARM may change the order of execution in non-obvious ways.


> > > > This is potentially a problem.  I haven't looked at in detail but
> > >you are
> > > > using the same buffer routine here as you are in the non-interrupt
> > > > code.  The ground is very unstable here.
> > >I removed the vectored irq setup, still doesn't work.
> >
> > This is not a matter of vectored or not.
>
>If I removed the vectored setup, then there is only one interrupt left
>  to call the isr, so there should not be a problem.

It doesn't matter if it is 1 interrupt or 10 the potential for a problem 
still exists, you are calling the same buffer for both the interrupt and 
mainline code.



>I gave up on that and started over, and this is what I think I am
>doing.  I start by disabling all interrupts globally and for the uart.
>  Then I enable only the RBR interrupt, then the uart vic.  In the main
>I print out 123 by using a for loop as a delay.  I setup the rbr isr
>to print out '!' if it receives a character.  Now the problem is when
>I send 2 characters the processor resets.  Is there something wrong w/
>my code?

Resetting may actually be a good thing here ;)  At least it suggests to me 
that you might actually be getting your interrupt this time.


>#include <stdio.h>
>#include "../ArmCommon/types.h"
>#include "../ArmCommon/LPC22xx.h"
>#include "../ArmCommon/LPC2294.h"
>
>#define TX_BUFFER_LENGTH 64
>
>static Uint16 txBytes = 0;
>static Uint16 txRdPos = 0;
>static Uint16 txWrPos = 0;
>static Uint16 txBuffer[TX_BUFFER_LENGTH];
>
>void uart0_config (void);
>void uart0_isr (void);
>void uart0_sendByte (Uint8);
>int putchar(int);
>int main (void);
>Uint32 irqBackup;
>
>void disableInterrupts (void);
>void enableInterrupts (void);
>
>void disableInterrupts (void) {
>         irqBackup = VICIntEnable;
>         VICIntEnable = 0;
>}
>void enableInterrupts (void) {
>         VICIntEnable = irqBackup;
>}

I'd feel a lot better about these if you were really disabling and 
restoring interrupts at the CPU level rather than just the VIC flags, but I 
don't think that's your problem source.


>void uart0_config (void) {
>         volatile Uint8 x;
>         // Setup UART 0
>         U0LCR = 0x80; // Enable DLAB
>         U0DLL = 0x36; // Setup BGR
>         U0DLM = 0x00; // ~57.6 kbps @ 50 Mhz
>         U0LCR = 0x03; // Enable UART 0, 8 bits, no parity, 1 stop bit
>
>         // Reset the FIFOs
>         U0FCR = 0xC7; // RX FIFO trigger level 8 chars, reset tx and rx fifo,
>enable fifos
>
>         // Clear any old irqs
>         x = U0LSR;
>         x = U0RBR;
>         x = U0IIR;
>
>         // Setup Interrupts for UART0
>         U0IER = 0x1; // Only RBR IRQ on
>         VICIntEnable |= (0x1 << 6); // Enable Uart0 Interrupt
>         VICVectAddr6 = (Uint32) uart0_isr;
>         VICVectCntl6 = 0x20 | 6;
>}
>
>void uart0_isr (void) __irq {
>         volatile Uint8 x;
>         uart0_sendByte('!');

There are problems here.  First you never empty the buffer so the buffer 
becomes blocked very quickly.  Now watch what happens when you send a 
string of bytes through that will fill the buffer up.

- First byte gets written at point A--
- Second byte comes along right behind it and also gets written at point 
A-- since the first byte has moved into the shift register.
- The rest of the buffer gets filled up via the else clause (Point B--) and 
then
- the next call sits in the infinite loop at point C--
- Shortly after the UART finally catches up and finishes sending the first 
character and moves the second character into the shift register while 
flagging an interrupt.
- The interrupt fires and the first thing that occurs is a call to 
uart0_sendByte which goes into an infinite loop at point C-- since the 
buffer is full.

You get two characters out, one interrupt fires and you never exit the 
interrupt routine.  Unless you have a watchdog enabled I would expect this 
to hang, not reset.

Unless the interrupt stack isn't setup correctly.  I'm not familiar with 
the startup code for your compiler so someone else might be better suited 
to suggest if that is an issue.


>         // Clear IRQ
>         x = U0LSR;
>         x = U0IIR;
>         x = U0RBR;
>         VICVectAddr = 0;
>}
>
>void uart0_sendByte(Uint8 a) {
>         // Wait until there is room in the buffer

C--

>         while(txBytes == TX_BUFFER_LENGTH);

A---

>         if(U0LSR&0x20) { // If the chip buffer is empty, put it there
>                 U0THR = a;
>         }

B--

>         else { // Put in software buffer
>                 disableInterrupts();
>                 txBuffer[txWrPos] = a;
>                 txWrPos++;
>                 txWrPos = (txWrPos == TX_BUFFER_LENGTH)?0:txWrPos;
>                 txBytes++;
>                 enableInterrupts();
>         }
>}
>
>int putchar(int a) {
>         uart0_sendByte((int)a);
>         return 0;
>}
>
>int main (void) {
>         Uint16 x;
>         PINSEL0 = PINSEL0_00_TxD | PINSEL0_01_RxD;
>         VPBDIV = 0x1;
>         VICIntSelect = 0;       // Only IRQs, no FIQs
>         VICIntEnClr = 0xFFFFFFFF; // Disable all irqs
>         uart0_config();
>         // Proof that it can send more than one character
>         printf("1");
>         for(x = 0; x < 1000; x++);
>         printf("2");
>         for(x = 0; x < 1000; x++);
>         printf("3");
>
>         while(1);
>}

Remember there are three places to disable/enable interrupts from the UART

- the uart itself
- the VIC peripheral
- the CPU

To avoid subtle phase problems (especially when first starting to work with 
interrupts) it makes sense as a simple precaution to disable interrupts at 
the CPU level when enabling or disabling them at the other levels.

Again I'd suggest looking at other UART code for this processor (take a 
look at the pointers from an earlier post).


" '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

Attachments

Move to quarantaine

This moves the raw source file on disk only. The archive index is not changed automatically, so you still need to run a manual refresh afterward.