Forums

Really wierd thing - accessing U1IER causes processor reset...!

Started by Mike Harrison February 5, 2007
Just been doing much head-scratching over this....

Using LPC2103 with IAR Kickstart & J-link. ARM mode

This is my "put a character in the Uart1 1 TX buffer" code

void u1txbyte(Int32U d)
{
txsum+=d;
FIOSET=expsel; // debug flag
U1IER&=0xFD; // disable THRE int
FIOCLR=expsel;
u1txbuf[u1txinptr++]=d;
u1txinptr&=(u1txbufsize-1);
if (txbusy==0) U1THR=d;
txbusy=1;
U1IER |=2; // enable THRE int

}

and this is the interrupt service code for the THRE case of the UART1 a interrupt

u1txoutptr++;
u1txoutptr &=(u1txbufsize-1);
if (u1txinptr!=u1txoutptr) U1THR=u1txbuf[u1txoutptr]; else txbusy=0;

buffer size is 256 bytes, baudrate 19.2K, PCLK 16MHZ CPU clock 64MHz

Now set it off transmitting, and occasionaly, the processor resets (breakpoint at start of main()
confirms this).
Watchdog is off.
The FIOSET/FIOCLEAR instructions indicate on the scope that the FIOSET is happenning, but when it
falls over, the FIOCLEAR isn't.

It isn't an abort, as the abort vectors go to endless loops.

If I change the references to U1IER to disable all interrupts instead of just the UART one (using
the __disable_interrupt(); intrinsic) it works fine.

If I take them out altogether it also works fine ( Not thought hard enough about my int code to
figure if I really need to disable ints here...)

Now what's even stranger is that if I change it to access U0IER ( U0 is used for a completely
different function), it ALSO crashes..! If I disable UART0 in the VIC, it doesn't crash.

I've disconnected the J-link and de-selected DBGSEL - no difference.

Any clue as to what could be happenning here....?

My reading of the VIC 'missed interrupt' issues is that this should not affect access to the
peripherals' own interrupt enable bits - or are these actually 'secretly' in the VIC and subject to
similar isssues...?

An Engineer's Guide to the LPC2100 Series

--- In l..., Mike Harrison wrote:
>
> Just been doing much head-scratching over this....
>
> Using LPC2103 with IAR Kickstart & J-link. ARM mode
>
> This is my "put a character in the Uart1 1 TX buffer" code
>
> void u1txbyte(Int32U d)
> {
> txsum+=d;
> FIOSET=expsel; // debug flag
> U1IER&=0xFD; // disable THRE int
> FIOCLR=expsel;
> u1txbuf[u1txinptr++]=d;
> u1txinptr&=(u1txbufsize-1);
> if (txbusy==0) U1THR=d;
> txbusy=1;
> U1IER |=2; // enable THRE int
>
> }
>
> and this is the interrupt service code for the THRE case of the
UART1 a interrupt
>
> u1txoutptr++;
> u1txoutptr &=(u1txbufsize-1);
> if (u1txinptr!=u1txoutptr) U1THR=u1txbuf[u1txoutptr]; else
txbusy=0;
>
> buffer size is 256 bytes, baudrate 19.2K, PCLK 16MHZ CPU clock 64MHz
>
> Now set it off transmitting, and occasionaly, the processor resets
(breakpoint at start of main()
> confirms this).
> Watchdog is off.
> The FIOSET/FIOCLEAR instructions indicate on the scope that the
FIOSET is happenning, but when it
> falls over, the FIOCLEAR isn't.
>
> It isn't an abort, as the abort vectors go to endless loops.
>
> If I change the references to U1IER to disable all interrupts
instead of just the UART one (using
> the __disable_interrupt(); intrinsic) it works fine.
>
> If I take them out altogether it also works fine ( Not thought hard
enough about my int code to
> figure if I really need to disable ints here...)
>
> Now what's even stranger is that if I change it to access U0IER (
U0 is used for a completely
> different function), it ALSO crashes..! If I disable UART0 in the
VIC, it doesn't crash.
>
> I've disconnected the J-link and de-selected DBGSEL - no
difference.
>
> Any clue as to what could be happenning here....?
>
> My reading of the VIC 'missed interrupt' issues is that this should
not affect access to the
> peripherals' own interrupt enable bits - or are these
actually 'secretly' in the VIC and subject to
> similar isssues...?
>

Mike,

I don't have the time to go into it in detail, but a couple of
suggestions:

1. I suspect the code may have a race condition, for example when you
update U1IER you use a read/modify/write. What's happenening with RX
interrupts at the same time? are they disabled? Also, can the TX byte
function be called from an interrupt (it's clearly not re-entrant)?
I doubt either of these is your specific problem, but the code
doesn't look right somehow.

2. If the processor is doing a reset rather than an abort, it's
probably just jumping to zero. This could be stack corruption or the
VIC loading a zero address. No harm in programming the VIC default
address handler with something that just lights a LED or whatever, so
you can see is it being called.

3. I'd be inclined to (a) never to disable the UART interrupts (b)
separate out the code that plays with the UART registers from the
buffering code and (c) generally simplify things, to make it easier
to prove correct. That's more a matter of style, though.

Brendan
> -----Original Message-----
> From: l...
> [mailto:l...]On Behalf
> Of Mike Harrison
> Sent: Monday, February 05, 2007 3:15 PM
> To: l...
> Subject: [lpc2000] Really wierd thing - accessing U1IER
> causes processor
> reset...!
> Just been doing much head-scratching over this....
>
> Using LPC2103 with IAR Kickstart & J-link. ARM mode
>
> This is my "put a character in the Uart1 1 TX buffer" code
>
> void u1txbyte(Int32U d)
> {
> txsum+=d;
> FIOSET=expsel; // debug flag
> U1IER&=0xFD; // disable THRE int
> FIOCLR=expsel;
> u1txbuf[u1txinptr++]=d;
> u1txinptr&=(u1txbufsize-1);
> if (txbusy==0) U1THR=d;
> txbusy=1;
> U1IER |=2; // enable THRE int
>
> }
>
> and this is the interrupt service code for the THRE case of
> the UART1 a interrupt
>
> u1txoutptr++;
> u1txoutptr &=(u1txbufsize-1);
> if (u1txinptr!=u1txoutptr) U1THR=u1txbuf[u1txoutptr];
> else txbusy=0;
>
> buffer size is 256 bytes, baudrate 19.2K, PCLK 16MHZ CPU clock 64MHz
>
> Now set it off transmitting, and occasionaly, the processor
> resets (breakpoint at start of main()
> confirms this).
> Watchdog is off.
> The FIOSET/FIOCLEAR instructions indicate on the scope that
> the FIOSET is happenning, but when it
> falls over, the FIOCLEAR isn't.
>
> It isn't an abort, as the abort vectors go to endless loops.
>
> If I change the references to U1IER to disable all interrupts
> instead of just the UART one (using
> the __disable_interrupt(); intrinsic) it works fine.
>
> If I take them out altogether it also works fine ( Not
> thought hard enough about my int code to
> figure if I really need to disable ints here...)
>
> Now what's even stranger is that if I change it to access
> U0IER ( U0 is used for a completely
> different function), it ALSO crashes..! If I disable UART0 in
> the VIC, it doesn't crash.
>
> I've disconnected the J-link and de-selected DBGSEL - no difference.
>
> Any clue as to what could be happenning here....?
>
> My reading of the VIC 'missed interrupt' issues is that this
> should not affect access to the
> peripherals' own interrupt enable bits - or are these
> actually 'secretly' in the VIC and subject to
> similar isssues...?

When I did my UART code this way, I got many spurious interrupts.
Using the global disable/enable stopped the spurious interrupts.

Do you have a default vector set up to catch spurious interrupts?

Mike
--- In l..., "Michael Anton" wrote:
>
> > -----Original Message-----
> > From: l...
> > [mailto:l...]On Behalf
> > Of Mike Harrison
> > Sent: Monday, February 05, 2007 3:15 PM
> > To: l...
> > Subject: [lpc2000] Really wierd thing - accessing U1IER
> > causes processor
> > reset...!
> >
> >
> > Just been doing much head-scratching over this....
> >
> > Using LPC2103 with IAR Kickstart & J-link. ARM mode
> >
> > This is my "put a character in the Uart1 1 TX buffer" code
> >
> > void u1txbyte(Int32U d)
> > {
> > txsum+=d;
> > FIOSET=expsel; // debug flag
> > U1IER&=0xFD; // disable THRE int
> > FIOCLR=expsel;
> > u1txbuf[u1txinptr++]=d;
> > u1txinptr&=(u1txbufsize-1);
> > if (txbusy==0) U1THR=d;
> > txbusy=1;
> > U1IER |=2; // enable THRE int
> >
> > }
> >
> > and this is the interrupt service code for the THRE case of
> > the UART1 a interrupt
> >
> > u1txoutptr++;
> > u1txoutptr &=(u1txbufsize-1);
> > if (u1txinptr!=u1txoutptr) U1THR=u1txbuf[u1txoutptr];
> > else txbusy=0;
> >
> > buffer size is 256 bytes, baudrate 19.2K, PCLK 16MHZ CPU clock
>> 64MHz
> >
> > Now set it off transmitting, and occasionaly, the processor
> > resets (breakpoint at start of main()
> > confirms this).
> > Watchdog is off.
> > The FIOSET/FIOCLEAR instructions indicate on the scope that
> > the FIOSET is happenning, but when it
> > falls over, the FIOCLEAR isn't.
> >
> > It isn't an abort, as the abort vectors go to endless loops.
> >
> > If I change the references to U1IER to disable all interrupts
> > instead of just the UART one (using
> > the __disable_interrupt(); intrinsic) it works fine.
> >
> > If I take them out altogether it also works fine ( Not
> > thought hard enough about my int code to
> > figure if I really need to disable ints here...)
> >
> > Now what's even stranger is that if I change it to access
> > U0IER ( U0 is used for a completely
> > different function), it ALSO crashes..! If I disable UART0 in
> > the VIC, it doesn't crash.
> >
> > I've disconnected the J-link and de-selected DBGSEL - no
>> difference.
> >
> > Any clue as to what could be happenning here....?
> >
> > My reading of the VIC 'missed interrupt' issues is that this
> > should not affect access to the
> > peripherals' own interrupt enable bits - or are these
> > actually 'secretly' in the VIC and subject to
> > similar isssues...?
> >
> > When I did my UART code this way, I got many spurious interrupts.
> Using the global disable/enable stopped the spurious interrupts.
>
> Do you have a default vector set up to catch spurious interrupts?
>
> Mike
>

Hi,
I cannot get my LPC2103 to run at 70Mhz with core powered at
1.8V. From LPC2103 errata sheet, you need to power VCore at
1.95V when running at high speed. It might be this type of
weird problems instead of a real bug in the UART... :)
Regards
>1. I suspect the code may have a race condition, for example when you
>update U1IER you use a read/modify/write.

No - I also tried writing the register without first reading it - same behaviour

>What's happenening with RX
>interrupts at the same time?

No RX ints will be coming from this UART at the time.

>are they disabled? Also, can the TX byte
>function be called from an interrupt (it's clearly not re-entrant)?

No.

>2. If the processor is doing a reset rather than an abort, it's
>probably just jumping to zero. This could be stack corruption or the
>VIC loading a zero address. No harm in programming the VIC default
>address handler with something that just lights a LED or whatever, so
>you can see is it being called.

Will try this when I get time.
>Hi,
>I cannot get my LPC2103 to run at 70Mhz with core powered at
>1.8V. From LPC2103 errata sheet, you need to power VCore at
>1.95V when running at high speed. It might be this type of
>weird problems instead of a real bug in the UART... :)
>Regards

Doubt it's this as PCLK is only at 16MHz - I've had this same hardware running with PCLK-64MHz with
no apparent problems.
--- In l..., Mike Harrison wrote:
> >1. I suspect the code may have a race condition, for example when
you
> >update U1IER you use a read/modify/write.
>
> No - I also tried writing the register without first reading it -
same behaviour
>
> >What's happenening with RX
> >interrupts at the same time?
>
> No RX ints will be coming from this UART at the time.
>
> >are they disabled? Also, can the TX byte
> >function be called from an interrupt (it's clearly not re-entrant)?
>
> No.
>
> >2. If the processor is doing a reset rather than an abort, it's
> >probably just jumping to zero. This could be stack corruption or
the
> >VIC loading a zero address. No harm in programming the VIC default
> >address handler with something that just lights a LED or whatever,
so
> >you can see is it being called.
>
> Will try this when I get time.
>

Mike, my comments on race conditions etc. were based on a quick scan
of the code: I'm sure it's fine, just that you have to be very
careful: even if the code works now, it might be problematic later
(e.g. calling your TX function from an interrupt handler).

My guess is that you're getting spurious calls to the default
interrupt vector in the VIC, which will explain the reset if you
haven't set one up - see the User Guide for details. All you need to
do is set up an empty function for the default handler address that
just resets the VIC and returns. If the interrupt is valid it will
recur on the correct vector. However, you should try and minimise
these: hence my comment on disabling the UART interrupt.

If you like I can post an alternative approach to handling UART
interrupts that might help.

Brendan
On Tue, 06 Feb 2007 10:43:29 -0000, you wrote:

>--- In l..., Mike Harrison wrote:
>> >1. I suspect the code may have a race condition, for example when
>you
>> >update U1IER you use a read/modify/write.
>>
>> No - I also tried writing the register without first reading it -
>same behaviour
>>
>> >What's happenening with RX
>> >interrupts at the same time?
>>
>> No RX ints will be coming from this UART at the time.
>>
>> >are they disabled? Also, can the TX byte
>> >function be called from an interrupt (it's clearly not re-entrant)?
>>
>> No.
>>
>> >2. If the processor is doing a reset rather than an abort, it's
>> >probably just jumping to zero. This could be stack corruption or
>the
>> >VIC loading a zero address. No harm in programming the VIC default
>> >address handler with something that just lights a LED or whatever,
>so
>> >you can see is it being called.
>>
>> Will try this when I get time.
>>Mike, my comments on race conditions etc. were based on a quick scan
>of the code: I'm sure it's fine, just that you have to be very
>careful: even if the code works now, it might be problematic later
>(e.g. calling your TX function from an interrupt handler).
>
>My guess is that you're getting spurious calls to the default
>interrupt vector in the VIC, which will explain the reset if you
>haven't set one up - see the User Guide for details. All you need to
>do is set up an empty function for the default handler address that
>just resets the VIC and returns. If the interrupt is valid it will
>recur on the correct vector. However, you should try and minimise
>these: hence my comment on disabling the UART interrupt.
>
>If you like I can post an alternative approach to handling UART
>interrupts that might help.

It's not an immediate problem as I have a fix by disabling global ints, however I am curious as to
how accessing this register can cause a spurious int.