EmbeddedRelated.com
Forums

Missing UART interrupts on 2103

Started by Chris September 9, 2008
Hello all,

Okay so ive been racking my brain over this problem for about 3-4 days
now and its driving me insane, ive searched this forum high and low
and tried lots of different solutions and i still get the same problems!

Basically what im trying to do is setup a simple interrupt driven uart
that uses a circular buffer. The method im using is as follows:

I fill the circular buffer, then just turn on the THRE interrupt,
which from what i read should then take over and pick characters from
buffer and splat them out the uart? However this isnt the case, im not
getting any uart interrupts at all

Now the other problem im having is when i try send the characters to
the micro from teraterm, i get the first character in the interrupt
fine. Then when i send another character it never goes back into the
interrupt again!!!!!!! its driving me nuts!

ive included code from what im working on.

Ive tried alot of different solutions, and none seem to work. I did
get the uart to transmit at one point, but then all my interrupts just
died after that. Which leads me to belive its a VIC problem, but from
what i can read im setting up the VIC properly so im baffled.

void uart1_int_hdlr(void) {

byte data, i, status_reg, lsr_reg;

status_reg = UART1_IIR;

switch (status_reg & 0x0E) {
case UART_RX_LINE_STATUS:
status_reg = UART1_LSR;
break;

//---- RX DATA AVIALABLE ----//
case UART_CHAR_TIMEOUT:
case UART_RX_DATA_AVAIL:
//uart has received a character in UDR
lsr_reg = UART1_LSR;
while (lsr_reg & UART1_RX_DATA_READY) {
data = UART1_RBR;
lsr_reg = UART1_LSR;
}
break;

//----TX FIFO EMPTY, RELOAD IT ----//
case UART_TX_FIFO_EMPTY:
// send byte if transmit buffer not empty

lsr_reg = UART1_LSR;

if (!(lsr_reg & UART1_TX_HOLDING_EMPTY)) break;

for (i=0; i<16; i++) {
UART1_THR = trx_buffer[tailptr++];
counter--;
if (counter) break;
}

//stop ints if nothing to send
if (!counter){
UART1_THRE_INT_OFF;
}
break;
}

VICVectAddr = 0xff;
}

//setting up the VIC//
void set_int_vecs(void) {

VICIntEnable=0x00000090; //timer0 int enabled, uart1 int enabled
VICIntSelect=0x00000000; //no interrupt setup to be FIQ yet
VICSoftInt=0x00000000;

VICVectAddr0 = (dword)uart1_int_hdlr;
VICVectCntl0 = (0x20 + 7); //enable the interrupt and set the source
to uart1

VICVectAddr1 = (dword)timer0;
VICVectCntl1 = (0x20 + 4); //enable the interrupt and set the source
to timer0

VICDefVectAddr = (dword)default_interrupt;
} //set_int_vecs()

Any help would be HUGELY appreciated!

Thanks!
Chris

An Engineer's Guide to the LPC2100 Series

> -----Original Message-----
> From: l...
> [mailto:l...]On Behalf
> Of Chris
> Sent: Monday, September 08, 2008 9:54 PM
> To: l...
> Subject: [lpc2000] Missing UART interrupts on 2103
> Hello all,
>
> Okay so ive been racking my brain over this problem for about 3-4 days
> now and its driving me insane, ive searched this forum high and low
> and tried lots of different solutions and i still get the
> same problems!
>
> Basically what im trying to do is setup a simple interrupt driven uart
> that uses a circular buffer. The method im using is as follows:
>
> I fill the circular buffer, then just turn on the THRE interrupt,
> which from what i read should then take over and pick characters from
> buffer and splat them out the uart? However this isnt the case, im not
> getting any uart interrupts at all

You need to prime the THRE interrupt by forcing a byte into the FIFO.
Unlike
many other UARTS, the LPC series does not require that the THRE interrupt
be turned off, even if there are no more characters to send. But, this
also means that no more interrupts will be generated, unless you actually
send a byte. So, you need to keep track of whether or not the FIFO is
empty, and if it is, send a byte manually, then turn on the interrupt
for the remaining bytes.

It is all a bit fiddly to get working reliably, or at least is was for
me, and I have written many interrupt driven UART handlers over the
years. This was by far the most difficult.

Mike
IFO.
> Unlike
> many other UARTS, the LPC series does not require that the THRE
interrupt
> be turned off, even if there are no more characters to send. But, this
> also means that no more interrupts will be generated, unless you
actually
> send a byte. So, you need to keep track of whether or not the FIFO is
> empty, and if it is, send a byte manually, then turn on the interrupt
> for the remaining bytes.
>

Yes - but note that in some systems you may well have to explicitly
turn off the tx interrupt first to reliably ascertain the exact state
of a byte/buffer queue. If you are not very careful with this, it is
possible to make the wrong decision and decide to not prime the FIFO
when it needs priming. Typically, this happens in multiThreaded apps
when the thread that is performing the send checks the queue status,
finds it not empty and is them preempted. When it runs again, it acts
on the 'not empty' status by loading its data onto the tx queue and
not priming the FIFO but, while it was not running, the tx interrupt
has emptied the tx queue of bytes and is no longer sending. This
siezes up the tx forever since the FIFO never gets primed again.

Rgds,
Martin

Ahh okay, i figured it was something simple like that. Would be nice
if that was written more clearly on the datasheet!

Onto the second problem, my receiving doesnt work?
Its definately a problem with a interrupt not clearing or something
along those lines. I can receive 1 or 2 bytes of data then the code
will never get back into the interrupt... or any interrupt for that
matter. Its the same after i transmit, seems to kill all interrupts.

Yet my 10ms timer interrupt works perfectly until the uart comes in...

Any thoughts??

Thanks,
Chris

--- In l..., "mjames_doveridge" wrote:
>
> IFO.
> > Unlike
> > many other UARTS, the LPC series does not require that the THRE
> interrupt
> > be turned off, even if there are no more characters to send. But,
this
> > also means that no more interrupts will be generated, unless you
> actually
> > send a byte. So, you need to keep track of whether or not the FIFO is
> > empty, and if it is, send a byte manually, then turn on the interrupt
> > for the remaining bytes.
> > Yes - but note that in some systems you may well have to explicitly
> turn off the tx interrupt first to reliably ascertain the exact state
> of a byte/buffer queue. If you are not very careful with this, it is
> possible to make the wrong decision and decide to not prime the FIFO
> when it needs priming. Typically, this happens in multiThreaded apps
> when the thread that is performing the send checks the queue status,
> finds it not empty and is them preempted. When it runs again, it acts
> on the 'not empty' status by loading its data onto the tx queue and
> not priming the FIFO but, while it was not running, the tx interrupt
> has emptied the tx queue of bytes and is no longer sending. This
> siezes up the tx forever since the FIFO never gets primed again.
>
> Rgds,
> Martin
>

Okay so ive gotten the transmitting to work reliably, priming UART
worked good. However the receiving still doesnt work, whenever i send
it a character it never goes back into any interrupts. Its like the
global interrupt enable flag is being cleared.
But i cant find a global interrupt enable flag anywhere in the data?
However imagecraft seems to have a way of disabling/enabling interrupts?

Is there something im screwing up in my interrupt code?
Also to get the transmitting to work i had to do a sort of "fix", i
have to put the enable_interrupt macro that imagecraft came with at
the end of it. This doesnt seem right.

What am i doing wrong?
--- In l..., "Chris" wrote:
>
> Hello all,
>
> Okay so ive been racking my brain over this problem for about 3-4 days
> now and its driving me insane, ive searched this forum high and low
> and tried lots of different solutions and i still get the same problems!
>
> Basically what im trying to do is setup a simple interrupt driven uart
> that uses a circular buffer. The method im using is as follows:
>
> I fill the circular buffer, then just turn on the THRE interrupt,
> which from what i read should then take over and pick characters from
> buffer and splat them out the uart? However this isnt the case, im not
> getting any uart interrupts at all
>
> Now the other problem im having is when i try send the characters to
> the micro from teraterm, i get the first character in the interrupt
> fine. Then when i send another character it never goes back into the
> interrupt again!!!!!!! its driving me nuts!
>
> ive included code from what im working on.
>
> Ive tried alot of different solutions, and none seem to work. I did
> get the uart to transmit at one point, but then all my interrupts just
> died after that. Which leads me to belive its a VIC problem, but from
> what i can read im setting up the VIC properly so im baffled.
>
> void uart1_int_hdlr(void) {
>
> byte data, i, status_reg, lsr_reg;
>
> status_reg = UART1_IIR;
>
> switch (status_reg & 0x0E) {
> case UART_RX_LINE_STATUS:
> status_reg = UART1_LSR;
> break;
>
> //---- RX DATA AVIALABLE ----//
> case UART_CHAR_TIMEOUT:
> case UART_RX_DATA_AVAIL:
> //uart has received a character in UDR
> lsr_reg = UART1_LSR;
> while (lsr_reg & UART1_RX_DATA_READY) {
> data = UART1_RBR;
> lsr_reg = UART1_LSR;
> }
> break;
>
> //----TX FIFO EMPTY, RELOAD IT ----//
> case UART_TX_FIFO_EMPTY:
> // send byte if transmit buffer not empty
>
> lsr_reg = UART1_LSR;
>
> if (!(lsr_reg & UART1_TX_HOLDING_EMPTY)) break;
>
> for (i=0; i<16; i++) {
> UART1_THR = trx_buffer[tailptr++];
> counter--;
> if (counter) break;
> }
>
> //stop ints if nothing to send
> if (!counter){
> UART1_THRE_INT_OFF;
> }
> break;
> }
>
> VICVectAddr = 0xff;
> }
>
> //setting up the VIC//
> void set_int_vecs(void) {
>
> VICIntEnable=0x00000090; //timer0 int enabled, uart1 int enabled
> VICIntSelect=0x00000000; //no interrupt setup to be FIQ yet
> VICSoftInt=0x00000000;
>
> VICVectAddr0 = (dword)uart1_int_hdlr;
> VICVectCntl0 = (0x20 + 7); //enable the interrupt and set the source
> to uart1
>
> VICVectAddr1 = (dword)timer0;
> VICVectCntl1 = (0x20 + 4); //enable the interrupt and set the source
> to timer0
>
> VICDefVectAddr = (dword)default_interrupt;
> } //set_int_vecs()
>
> Any help would be HUGELY appreciated!
>
> Thanks!
> Chris
>

Chris wrote:
>
> Okay so ive gotten the transmitting to work reliably, priming UART
> worked good. However the receiving still doesnt work, whenever i send
> it a character it never goes back into any interrupts. Its like the
> global interrupt enable flag is being cleared.
> But i cant find a global interrupt enable flag anywhere in the data?
> However imagecraft seems to have a way of disabling/enabling interrupts?
>
> Is there something im screwing up in my interrupt code?
> Also to get the transmitting to work i had to do a sort of "fix", i
> have to put the enable_interrupt macro that imagecraft came with at
> the end of it. This doesnt seem right.
>
> What am i doing wrong?
>

From what it sounds like, you are not using any type of JTAG debugging???

I did have some trouble with the UARTs on the LPC2000 family, but
quickly resolved my issues by being able to use Insight + a JTAG debug
module to view the status register values of the UART. Single stepping
code is a wonderful thing!

My main issue turned out to be a multitude of little problems, for
example, the modem control line interrupt would trigger my ISR and I was
not responding to it (clearing the condition), thus locking up the
UART. Dumb stuff like that...
TomW

--
Tom Walsh - WN3L - Embedded Systems Consultant
http://openhardware.net http://cyberiansoftware.com http://openzipit.org
"Windows? No thanks, I have work to do..."
----------------

--- In l..., Tom Walsh wrote:
>
> Chris wrote:
> >
> > Okay so ive gotten the transmitting to work reliably, priming UART
> > worked good. However the receiving still doesnt work, whenever i send
> > it a character it never goes back into any interrupts. Its like the
> > global interrupt enable flag is being cleared.
> > But i cant find a global interrupt enable flag anywhere in the data?
> > However imagecraft seems to have a way of disabling/enabling
interrupts?
> >
> > Is there something im screwing up in my interrupt code?
> > Also to get the transmitting to work i had to do a sort of "fix", i
> > have to put the enable_interrupt macro that imagecraft came with at
> > the end of it. This doesnt seem right.
> >
> > What am i doing wrong?
> > From what it sounds like, you are not using any type of JTAG
debugging???
>
> I did have some trouble with the UARTs on the LPC2000 family, but
> quickly resolved my issues by being able to use Insight + a JTAG debug
> module to view the status register values of the UART. Single stepping
> code is a wonderful thing!
>
> My main issue turned out to be a multitude of little problems, for
> example, the modem control line interrupt would trigger my ISR and I
was
> not responding to it (clearing the condition), thus locking up the
> UART. Dumb stuff like that...
> TomW
>
> --
> Tom Walsh - WN3L - Embedded Systems Consultant
> http://openhardware.net http://cyberiansoftware.com http://openzipit.org
> "Windows? No thanks, I have work to do..."
> ----------------
>
Im using Imagecraft, with NOICE debugging enviro. Im using a SEGGER
J-LINK device for jtag.

Its funny, the code ive got seems to work perfectly on a lpc2131 but
on the 2103 it doesnt work. lol explain that?