EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

Workaround for LPC2292 errata EXTINT.1, EXTINT.2 and VPBDIV.1

Started by bertriksikken May 8, 2007
Hi,

I'm running into a problem where the CPU seems to crash when reading
the EXTPOL and EXTMODE registers. I am aware of the errata applying
to these registers and attempted to code a work-around, but somehow
I can't make it work reliably.

The offending code is the following:

static void GetExternIntConfig(UINT32 *pulExtMode, UINT32 *pulExtPolar)
{
UINT32 ulVPBDIV;

/* get original value of VPBDIV, take into account erratum VPBDIV.1 */
ulVPBDIV = LPC_VPBDIV;
ulVPBDIV = LPC_VPBDIV;

/* read EXTMODE, take into account erratum EXTINT.1 */
LPC_VPBDIV = 0;
*pulExtMode = LPC_EXTMODE;

/* read EXTPOLAR */
LPC_VPBDIV = 0;
*pulExtPolar = LPC_EXTPOLAR;

/* restore VPBDIV */
LPC_VPBDIV = ulVPBDIV;
}

Observations:
* When I comment out the code under /* read EXTMODE ... */ the
application works. When I comment out the code under /* read EXTPOLAR
*/ the application works. When I leave them both in, the application
hangs.
* When running this code with a debugger, the debugger gets confused too.
* One application running from internal flash using this code does not
hang, another application running from external memory hangs (I did
tests on the external bus to verify that it is working properly).
* pulExtMode and pulExtPolar are valid pointers.

The LPC2292 is running at 60 MHz, with MAM fully enabled and MAMTIM=3.

Does anyone see anything wrong with my workaround code or have a
suggestion for improvement?

Kind regards,
Bertrik Sikken

An Engineer's Guide to the LPC2100 Series

bertriksikken wrote:
>
> Hi,
>
> I'm running into a problem where the CPU seems to crash when reading
> the EXTPOL and EXTMODE registers. I am aware of the errata applying
> to these registers and attempted to code a work-around, but somehow
> I can't make it work reliably.
>

I ran into some similar errata on the LPC2214 about the EXTPOL pin. I
found that I would also crash the ARM7TDMI core if I wasn't careful.
Something about the EXTPOL setting and the VPBDIV getting overwritten /
set to zero? Anyhow, this is how I finally did things, not quite the
errata suggested way of doing things, but I found the errata solution
would also give me grief!

============== begin ===============static void startExt0Interrupt (void)
{ // setup external interrupt to monitor the RXD0 BRK via EINT0.
unsigned flags_cpsr;
uint8_t vpbdivSave;
flags_cpsr = disableIRQ();
// disable UART0 service.
VICIntEnClear = VIC_BIT(VIC_UART0);
// set EINT0 pin for interrupt operation, falling edge trigger.
PINSEL0 = (PINSEL0 & ~EXT0_PINMASK0) | EXT0_INT_PINSEL0;
VICIntEnClear = VIC_BIT(VIC_EINT0);
<---------- errata stuff here ----------------->
// bug in DIE, must read VPBDIV twice.
vpbdivSave = VPBDIV; vpbdivSave = VPBDIV;
// set to level sensitive, high level.
VPBDIV = 0; EXTMODE = 0; VPBDIV = 0;
VPBDIV = 1; EXTPOLAR = 1; VPBDIV = 1;
VPBDIV = 1; EXTINT = 1; VPBDIV = 1;
VPBDIV = vpbdivSave;
<---------- errata stuff finish ----------------->
// arm the interrupt for EXT0.
ExInt0VectAddr = (uint32_t)ExternalInterrupt0Service;
VICIntSelect &= ~VIC_BIT(VIC_EINT0);
ExInt0VectCntl = VIC_ENABLE | VIC_EINT0;
VICIntEnable = VIC_BIT(VIC_EINT0);
restoreIRQ(flags_cpsr);
}
============== snip ================
Notice the replication of the written value across the VPBDIV register?
This was the ONLY WAY I could work around the problem. The suggested
work around does not work.

This has not been the only processor that I've encountered crashes with
the EXTPOL settings. IIRC, I had some rather nasty lockups with the
LPC2106 or LPC2138 (cannot recall which). At the time, I don't think
there was any errata on those CPUs. I thought that I just didn't
understand the setup of the register.

Regards,

TomW

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

like Tom I've also run into this one as well on the 2129 as well as the
2292 - sadly though I've only ever had to write this register never read it.
The Errata is correct but worded extremely poorly so that it's very easy to
misinterpret but we do similarly to Tom to do a write:

EXTMODE = 0xF; // set EINT0, EINT1, EINT2 and EINT3 to edge detection
VPBDIV = 0xF; // Errata requirement to get the above register setting to
work
VPBDIV = 0;
EXTPOLAR = 0x0; // set EINT0, EINT1, EINT2 and EINT3 to falling edge
detection
VPBDIV = 0x0; // Errata requirement to get the above register setting to
work
VPBDIV = 0;

That said I've not had to read this register as you are trying to do - so
when you do work out the sequence could you pop it into a message on here so
we can all see how to read the register as well as write it.

Cheers.

Andy

-----Original Message-----
From: l... [mailto:l...]On Behalf Of
Tom Walsh
Sent: 08 May 2007 20:20
To: l...
Subject: Re: [lpc2000] Workaround for LPC2292 errata EXTINT.1, EXTINT.2
and VPBDIV.1
bertriksikken wrote:
>
> Hi,
>
> I'm running into a problem where the CPU seems to crash when reading
> the EXTPOL and EXTMODE registers. I am aware of the errata applying
> to these registers and attempted to code a work-around, but somehow
> I can't make it work reliably.
>

I ran into some similar errata on the LPC2214 about the EXTPOL pin. I
found that I would also crash the ARM7TDMI core if I wasn't careful.
Something about the EXTPOL setting and the VPBDIV getting overwritten /
set to zero? Anyhow, this is how I finally did things, not quite the
errata suggested way of doing things, but I found the errata solution
would also give me grief!

============== begin =============== static void startExt0Interrupt (void)
{ // setup external interrupt to monitor the RXD0 BRK via EINT0.
unsigned flags_cpsr;
uint8_t vpbdivSave;
flags_cpsr = disableIRQ();
// disable UART0 service.
VICIntEnClear = VIC_BIT(VIC_UART0);
// set EINT0 pin for interrupt operation, falling edge trigger.
PINSEL0 = (PINSEL0 & ~EXT0_PINMASK0) | EXT0_INT_PINSEL0;
VICIntEnClear = VIC_BIT(VIC_EINT0);
<---------- errata stuff here ----------------->
// bug in DIE, must read VPBDIV twice.
vpbdivSave = VPBDIV; vpbdivSave = VPBDIV;
// set to level sensitive, high level.
VPBDIV = 0; EXTMODE = 0; VPBDIV = 0;
VPBDIV = 1; EXTPOLAR = 1; VPBDIV = 1;
VPBDIV = 1; EXTINT = 1; VPBDIV = 1;
VPBDIV = vpbdivSave;
<---------- errata stuff finish ----------------->
// arm the interrupt for EXT0.
ExInt0VectAddr = (uint32_t)ExternalInterrupt0Service;
VICIntSelect &= ~VIC_BIT(VIC_EINT0);
ExInt0VectCntl = VIC_ENABLE | VIC_EINT0;
VICIntEnable = VIC_BIT(VIC_EINT0);
restoreIRQ(flags_cpsr);
}
============== snip ================
Notice the replication of the written value across the VPBDIV register?
This was the ONLY WAY I could work around the problem. The suggested
work around does not work.

This has not been the only processor that I've encountered crashes with
the EXTPOL settings. IIRC, I had some rather nasty lockups with the
LPC2106 or LPC2138 (cannot recall which). At the time, I don't think
there was any errata on those CPUs. I thought that I just didn't
understand the setup of the register.

Regards,

TomW

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

Thanks for your replies.

I've given up on reading EXTMODE and EXTPOLAR and just try to write
them now (any modifications on these registers are cached in static
variables).

I added code that lights up some LEDs in the various steps of setting
the EXTMODE register:

static void SetExternIntConfig(UINT32 ulExtMod, UINT32 ulExtPol)
{
UINT32 ulVPBDIV;

LPC_IO0CLR = (1<<10);

/* get original value of VPBDIV, take into account erratum VPBDIV.1 */
ulVPBDIV = LPC_VPBDIV;
ulVPBDIV = LPC_VPBDIV;

LPC_IO0CLR = (1<<11);

/* write EXTMODE, take into account erratum EXTINT.1 and EXTINT.2 */
LPC_VPBDIV = 0;
LPC_EXTMODE = ulExtMod;
LPC_VPBDIV = ulExtMod;

LPC_IO0CLR = (1<<12);

/* write EXTPOLAR */
// LPC_VPBDIV = 0;
// LPC_EXTPOLAR = ulExtPol;
// LPC_VPBDIV = ulExtPol;

/* restore VPBDIV */
LPC_VPBDIV = ulVPBDIV;

LPC_IO0CLR = (1<<13);
}

When running this, my application hangs and only LEDs on P0.10 and
P0.11 (active low) light up, the LEDs on P0.12 and P0.13 do not
light up.

My conclusion so far is that the documented work-around simply does
not work.

Using the sequence
LPC_VPBDIV = ulExtMod; // instead of 0
LPC_EXTMODE = ulExtMod;
LPC_VPBDIV = ulExtMod;
as suggested by Tom gives the same result.

I'm having problems when running from an external 32-bit memory on
CS0. When the same code runs from internal flash, it seems to work
fine: external interrupts work as expected as the specified type
(edge/level) and polarity.

Regards,
Bertrik

--- In l..., "Andy Berney" wrote:
>
> Hi guys,
>
> like Tom I've also run into this one as well on the 2129 as well as the
> 2292 - sadly though I've only ever had to write this register never
read it.
> The Errata is correct but worded extremely poorly so that it's very
easy to
> misinterpret but we do similarly to Tom to do a write:
>
> EXTMODE = 0xF; // set EINT0, EINT1, EINT2 and EINT3 to edge detection
> VPBDIV = 0xF; // Errata requirement to get the above register
setting to
> work
> VPBDIV = 0;
> EXTPOLAR = 0x0; // set EINT0, EINT1, EINT2 and EINT3 to falling edge
> detection
> VPBDIV = 0x0; // Errata requirement to get the above register
setting to
> work
> VPBDIV = 0;
>
> That said I've not had to read this register as you are trying to do
- so
> when you do work out the sequence could you pop it into a message on
here so
> we can all see how to read the register as well as write it.
>
> Cheers.
>
> Andy
>
> -----Original Message-----
> From: l... [mailto:l...]On
Behalf Of
> Tom Walsh
> Sent: 08 May 2007 20:20
> To: l...
> Subject: Re: [lpc2000] Workaround for LPC2292 errata EXTINT.1,
EXTINT.2
> and VPBDIV.1
> bertriksikken wrote:
> >
> > Hi,
> >
> > I'm running into a problem where the CPU seems to crash when reading
> > the EXTPOL and EXTMODE registers. I am aware of the errata applying
> > to these registers and attempted to code a work-around, but somehow
> > I can't make it work reliably.
> > I ran into some similar errata on the LPC2214 about the EXTPOL pin. I
> found that I would also crash the ARM7TDMI core if I wasn't careful.
> Something about the EXTPOL setting and the VPBDIV getting
overwritten /
> set to zero? Anyhow, this is how I finally did things, not quite the
> errata suggested way of doing things, but I found the errata solution
> would also give me grief!
>
> ============== begin ===============> static void startExt0Interrupt (void)
> { // setup external interrupt to monitor the RXD0 BRK via EINT0.
> unsigned flags_cpsr;
> uint8_t vpbdivSave;
> flags_cpsr = disableIRQ();
> // disable UART0 service.
> VICIntEnClear = VIC_BIT(VIC_UART0);
> // set EINT0 pin for interrupt operation, falling edge trigger.
> PINSEL0 = (PINSEL0 & ~EXT0_PINMASK0) | EXT0_INT_PINSEL0;
> VICIntEnClear = VIC_BIT(VIC_EINT0);
> <---------- errata stuff here ----------------->
> // bug in DIE, must read VPBDIV twice.
> vpbdivSave = VPBDIV; vpbdivSave = VPBDIV;
> // set to level sensitive, high level.
> VPBDIV = 0; EXTMODE = 0; VPBDIV = 0;
> VPBDIV = 1; EXTPOLAR = 1; VPBDIV = 1;
> VPBDIV = 1; EXTINT = 1; VPBDIV = 1;
> VPBDIV = vpbdivSave;
> <---------- errata stuff finish ----------------->
> // arm the interrupt for EXT0.
> ExInt0VectAddr = (uint32_t)ExternalInterrupt0Service;
> VICIntSelect &= ~VIC_BIT(VIC_EINT0);
> ExInt0VectCntl = VIC_ENABLE | VIC_EINT0;
> VICIntEnable = VIC_BIT(VIC_EINT0);
> restoreIRQ(flags_cpsr);
> }
> ============== snip ================>
> Notice the replication of the written value across the VPBDIV
register?
> This was the ONLY WAY I could work around the problem. The suggested
> work around does not work.
>
> This has not been the only processor that I've encountered crashes
with
> the EXTPOL settings. IIRC, I had some rather nasty lockups with the
> LPC2106 or LPC2138 (cannot recall which). At the time, I don't think
> there was any errata on those CPUs. I thought that I just didn't
> understand the setup of the register.
>
> Regards,
>
> TomW
All
Sorry about jumping in so late on this thread. I used external
interrupts on a project a couple of years ago and while it was a pain to
get running, it did. The processor was the LPC2138 not the 2292, but
this MIGHT help.

Regards
-Bill Knight
R O SoftWare

void extIntInit(void)
{
uint8_t vpbDiv, extPolar, extMode;



// External Int Signal is on EINT0 (P0.16) of the LPC2138-SBC
VICIntEnClear = VIC_BIT(VIC_EINT0); // Make sure EINT0 is disabled
PINSEL1 = (PINSEL1 & ~3) | 1; // Configure pin as EINT0
// Pin set as INPUT elsewhere
VICIntSelect &= ~VIC_BIT(VIC_EINT0); // Set EINT0 as IRQ
VICVectCtlArray[11] = VIC_ENABLE | VIC_EINT0; // Use slot 11
VICVectAdrArray[11] = (uint32_t)extIntISR; // Set vector address

EXTINT = 1; // Clear any pending interrupts

// See LPC errata concerning access to EXTMODE & EXTPOLAR
// DO NOT SINGLE STEP OR BREAKPOINT UNTIL THE VALUE IN VPBDIV
// IS RESTORED!!!!!
vpbDiv = VPBDIV; // Get current VPBDIV setting
vpbDiv = VPBDIV; // Philips Apps says read it twice
VPBDIV = 0; // Set to 0 to avoid corruption
extPolar = (EXTPOLAR & ~1) & 0x0F; // Set Polarity to active LOW
EXTPOLAR = extPolar;
VPBDIV = extPolar;

VPBDIV = 0; // Set to 0 to avoid corruption
#if 0 // LEVEL_SENSITIVE
extMode = (EXTMODE & ~1) & 0x0F; // Set Mode to Level Sensitive
#else // EDGE_SENSITIVE
extMode = (EXTMODE | 1) & 0x0F; // Set Mode to Edge Sensitive
#endif
EXTMODE = extMode;
VPBDIV = extMode;
VPBDIV = (vpbDiv & 0x33); // Restore VPBDIV setting

VICIntEnable = VIC_BIT(VIC_EINT0); // Enable the interrupt
}
bertriksikken wrote:
> Hi Tom, Andy,
>
> Thanks for your replies.
>
> I've given up on reading EXTMODE and EXTPOLAR and just try to write
> them now (any modifications on these registers are cached in static
> variables).
>
> I added code that lights up some LEDs in the various steps of setting
> the EXTMODE register:
>
> static void SetExternIntConfig(UINT32 ulExtMod, UINT32 ulExtPol)
> {
> UINT32 ulVPBDIV;
>
> LPC_IO0CLR = (1<<10);
>
> /* get original value of VPBDIV, take into account erratum VPBDIV.1 */
> ulVPBDIV = LPC_VPBDIV;
> ulVPBDIV = LPC_VPBDIV;
>
> LPC_IO0CLR = (1<<11);
>
> /* write EXTMODE, take into account erratum EXTINT.1 and EXTINT.2 */
> LPC_VPBDIV = 0;
> LPC_EXTMODE = ulExtMod;
> LPC_VPBDIV = ulExtMod;
>
> LPC_IO0CLR = (1<<12);
>
> /* write EXTPOLAR */
> // LPC_VPBDIV = 0;
> // LPC_EXTPOLAR = ulExtPol;
> // LPC_VPBDIV = ulExtPol;
>
> /* restore VPBDIV */
> LPC_VPBDIV = ulVPBDIV;
>
> LPC_IO0CLR = (1<<13);
> }
>
> When running this, my application hangs and only LEDs on P0.10 and
> P0.11 (active low) light up, the LEDs on P0.12 and P0.13 do not
> light up.
>
> My conclusion so far is that the documented work-around simply does
> not work.
>
> Using the sequence
> LPC_VPBDIV = ulExtMod; // instead of 0
> LPC_EXTMODE = ulExtMod;
> LPC_VPBDIV = ulExtMod;
> as suggested by Tom gives the same result.
>
> I'm having problems when running from an external 32-bit memory on
> CS0. When the same code runs from internal flash, it seems to work
> fine: external interrupts work as expected as the specified type
> (edge/level) and polarity.
>
> Regards,
> Bertrik
>
> --- In l..., "Andy Berney" wrote:
>> Hi guys,
>>
>> like Tom I've also run into this one as well on the 2129 as well as the
>> 2292 - sadly though I've only ever had to write this register never
> read it.
>> The Errata is correct but worded extremely poorly so that it's very
> easy to
>> misinterpret but we do similarly to Tom to do a write:
>>
>> EXTMODE = 0xF; // set EINT0, EINT1, EINT2 and EINT3 to edge detection
>> VPBDIV = 0xF; // Errata requirement to get the above register
> setting to
>> work
>> VPBDIV = 0;
>> EXTPOLAR = 0x0; // set EINT0, EINT1, EINT2 and EINT3 to falling edge
>> detection
>> VPBDIV = 0x0; // Errata requirement to get the above register
> setting to
>> work
>> VPBDIV = 0;
>>
>> That said I've not had to read this register as you are trying to do
> - so
>> when you do work out the sequence could you pop it into a message on
> here so
>> we can all see how to read the register as well as write it.
>>
>> Cheers.
>>
>> Andy
>>
>> -----Original Message-----
>> From: l... [mailto:l...]On
> Behalf Of
>> Tom Walsh
>> Sent: 08 May 2007 20:20
>> To: l...
>> Subject: Re: [lpc2000] Workaround for LPC2292 errata EXTINT.1,
> EXTINT.2
>> and VPBDIV.1
>> bertriksikken wrote:
>> >
>> > Hi,
>> >
>> > I'm running into a problem where the CPU seems to crash when reading
>> > the EXTPOL and EXTMODE registers. I am aware of the errata applying
>> > to these registers and attempted to code a work-around, but somehow
>> > I can't make it work reliably.
>> >
>>
>> I ran into some similar errata on the LPC2214 about the EXTPOL pin. I
>> found that I would also crash the ARM7TDMI core if I wasn't careful.
>> Something about the EXTPOL setting and the VPBDIV getting
> overwritten /
>> set to zero? Anyhow, this is how I finally did things, not quite the
>> errata suggested way of doing things, but I found the errata solution
>> would also give me grief!
>>
>> ============== begin ===============>> static void startExt0Interrupt (void)
>> { // setup external interrupt to monitor the RXD0 BRK via EINT0.
>> unsigned flags_cpsr;
>> uint8_t vpbdivSave;
>> flags_cpsr = disableIRQ();
>> // disable UART0 service.
>> VICIntEnClear = VIC_BIT(VIC_UART0);
>> // set EINT0 pin for interrupt operation, falling edge trigger.
>> PINSEL0 = (PINSEL0 & ~EXT0_PINMASK0) | EXT0_INT_PINSEL0;
>> VICIntEnClear = VIC_BIT(VIC_EINT0);
>> <---------- errata stuff here ----------------->
>> // bug in DIE, must read VPBDIV twice.
>> vpbdivSave = VPBDIV; vpbdivSave = VPBDIV;
>> // set to level sensitive, high level.
>> VPBDIV = 0; EXTMODE = 0; VPBDIV = 0;
>> VPBDIV = 1; EXTPOLAR = 1; VPBDIV = 1;
>> VPBDIV = 1; EXTINT = 1; VPBDIV = 1;
>> VPBDIV = vpbdivSave;
>> <---------- errata stuff finish ----------------->
>> // arm the interrupt for EXT0.
>> ExInt0VectAddr = (uint32_t)ExternalInterrupt0Service;
>> VICIntSelect &= ~VIC_BIT(VIC_EINT0);
>> ExInt0VectCntl = VIC_ENABLE | VIC_EINT0;
>> VICIntEnable = VIC_BIT(VIC_EINT0);
>> restoreIRQ(flags_cpsr);
>> }
>> ============== snip ================>>
>> Notice the replication of the written value across the VPBDIV
> register?
>> This was the ONLY WAY I could work around the problem. The suggested
>> work around does not work.
>>
>> This has not been the only processor that I've encountered crashes
> with
>> the EXTPOL settings. IIRC, I had some rather nasty lockups with the
>> LPC2106 or LPC2138 (cannot recall which). At the time, I don't think
>> there was any errata on those CPUs. I thought that I just didn't
>> understand the setup of the register.
>>
>> Regards,
>>
>> TomW

The 2024 Embedded Online Conference