Bug: Chip_RGU_TriggerReset starts M0 core

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Bug: Chip_RGU_TriggerReset starts M0 core

478 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by dstahlke on Mon Oct 05 22:26:54 MST 2015
I was experiencing an odd crash which, after a half day of debugging, I traced to the Chip_RGU_TriggerReset function.  I'm linking against an older version of LPCOpen, but it looks like 2.16 would have the same issue.  The function itself is quite simple, at least in 2.16:

STATIC INLINE void Chip_RGU_TriggerReset(CHIP_RGU_RST_T ResetNumber)
{
LPC_RGU->RESET_CTRL[ResetNumber >> 5] = 1 << (ResetNumber & 31);
/* Reset will auto clear after 1 clock cycle */
}

Herein lies an insidious bug.  Writing zero to bit 24 of LPC_RGU->RESET_CTRL[1] will start the M0 core.  If you're not expecting that, and haven't set things up properly, M0 will start running random code, leading to unpredictable consequences.

There is a simple workaround:

if((ResetNumber >> 5) == 1) {
LPC_RGU->RESET_CTRL[1] = (1 << (ResetNumber & 31)) | (1 << 24);
} else {
LPC_RGU->RESET_CTRL[ResetNumber >> 5] = 1 << (ResetNumber & 31);
}

... but this assumes you don't want M0 running.  In general, I suppose you could set only bit (ResetNumber & 31) by using the bit-band memory.

It should be noted (if only for the benefit of people debugging via Google) that Chip_RGU_TriggerReset is called by Chip_HSADC_Init and Chip_ENET_Init, so those functions could also lead to a crash.
Labels (1)
0 Kudos
4 Replies

398 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by starblue on Wed Oct 07 02:00:54 MST 2015

Quote: dstahlke
I'm using LPC4370.


Note that the same reset behavior applies for M0SUB, not only M0APP.

For a general solution you should probably read RESET_ACTIVE_STATUSn first and make sure to preserve the reset status for the M0s when writing to RESET_CTRLn.

Note to NXP: The paragraph preceding the tables for RESET_CTRLn should IMHO also mention M0SUB.
0 Kudos

398 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by dstahlke on Tue Oct 06 21:14:19 MST 2015
In order to set a bit in RESET_CTRL without clearing the M0 related bits, I tried writing to the bit band region.  Didn't work, causes a hard fault.  I've heard bit band described as atomic read-modify-write, so maybe the issue is that RESET_CTRL is write-only so bit band can't be used.

static inline volatile uint32_t *bitband_peri(volatile void *p, int bit) {
    uint32_t base = 0x42000000;
    uint32_t ref  = 0x40000000;
    return (uint32_t *)(base + (uint32_t(p)-ref)*32 + bit*4);
}

static inline void my_reset(int bit) {
    *bitband_peri(LPC_RGU->RESET_CTRL, bit) = 1;
}

int main() {
    ....
    my_reset(RGU_TIMER2_RST);
    ....
}
0 Kudos

398 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by dstahlke on Tue Oct 06 19:17:45 MST 2015
I'm using LPC4370.  The errata sheet says MASTER_RST, M4_RST, and PERIPH_RST are non-functional.

The problem I was having was caused not by a hardware problem, but by LPCOpen.  I was calling Chip_RGU_TriggerReset(RGU_TIMER2_RST), which should (and does) set the corresponding bit in RESET_CTRL.  Problem is it also clears the M0_SUB_RST or M0APP_RST bit, depending on whether RESET_CTRL[0] or RESET_CTRL[1] is being altered.  This takes the M0 core out of reset or something (I don't really know much about the M0).

Note: when I wrote the above workaround, I didn't realize that RESET_CTRL[0] also has an M0 related bit.  So when RESET_CTRL[0] is written, make sure not to clear bit 12.
0 Kudos

398 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by briching on Tue Oct 06 08:51:14 MST 2015
What part are you using?  On some parts, the reset functionality doesn't work as designed (or could even be undefined)

LPC4357 errata sheet - see the sections on RESET.1 and RESET.2
0 Kudos