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, IIIMessage
Re: [lpc2000] Re: Problems w/ UART
2004-10-08 by Robert Adsett
Attachments
- No local attachments were found for this message.