U32 pmuRegVal; // Configure wakeup sources before going into sleep/deep-sleep. // By default, pin 0.1 is configured as wakeup source (falling edge) pmuInit(); // Put peripherals into sleep mode (leave WDTOSC enabled) pmuRegVal = SCB_PDSLEEPCFG_IRCOUT_PD | SCB_PDSLEEPCFG_IRC_PD | SCB_PDSLEEPCFG_FLASH_PD | SCB_PDSLEEPCFG_BOD_PD | SCB_PDSLEEPCFG_ADC_PD | SCB_PDSLEEPCFG_SYSPLL_PD; // Enter deep sleep mode (wakeup after 5 seconds) pmuDeepSleep(pmuRegVal, 5); |
/**************************************************************************/ /*! \brief Initialises the power management unit Initialise the power management unit, and configure pin 0.1 to act as a wakeup source from sleep or deep-sleep mode. For sleep and deep-sleep modes, entered via pmuSleep(), P0.0..11 and P1.0 can be used as a wakeup source. For deep power-down mode, entered via pmuPowerDown(), only a low level on pin 1.4 (WAKEUP) can wake the device up. */ /**************************************************************************/ void pmuInit( void ) { /* Enable all clocks, even those turned off at power up. */ SCB_PDRUNCFG &= ~(SCB_PDRUNCFG_WDTOSC_MASK | SCB_PDRUNCFG_SYSOSC_MASK | SCB_PDRUNCFG_ADC_MASK); /* Enable wakeup interrupts (P0.1..11 and P1.0 can be used) */ NVIC_EnableIRQ(WAKEUP1_IRQn); // P0.1 /* Configure pin 0.1 as wakeup source (MAT2 on 32-bit Timer 0) */ IOCON_PIO0_1 &= ~IOCON_PIO0_1_FUNC_MASK; IOCON_PIO0_1 |= (IOCON_PIO0_1_FUNC_GPIO | IOCON_PIO0_1_HYS_ENABLE); /* Set pins to input for wakeup */ gpioSetDir( 0, 1, gpioDirection_Input ); /* Only edge trigger. activation polarity on P0.1 is FALLING EDGE. */ SCB_STARTAPRP0 = ~SCB_STARTAPRP0_MASK; // ~0xFFFFFFFF; /* Clear all wakeup source */ SCB_STARTRSRP0CLR = SCB_STARTRSRP0CLR_MASK; /* Enable Port 0.1 as wakeup source. */ SCB_STARTERP0 |= SCB_STARTERP0_ERPIO0_1; return; } /**************************************************************************/ /*! Setup the clock for the watchdog timer. The default setting is 10kHz. */ /**************************************************************************/ static void pmuWDTClockInit (void) { /* Configure watchdog clock */ /* Freq. = 0.5MHz, div = 50: WDT_OSC = 10kHz */ SCB_WDTOSCCTRL = SCB_WDTOSCCTRL_FREQSEL_0_5MHZ | SCB_WDTOSCCTRL_DIVSEL_DIV50; /* Set clock source (use external crystal) */ SCB_WDTCLKSEL = SCB_WDTCLKSEL_SOURCE_INPUTCLOCK; SCB_WDTCLKUEN = SCB_WDTCLKUEN_UPDATE; SCB_WDTCLKUEN = SCB_WDTCLKUEN_DISABLE; SCB_WDTCLKUEN = SCB_WDTCLKUEN_UPDATE; /* Wait until updated */ while (!(SCB_WDTCLKUEN & SCB_WDTCLKUEN_UPDATE)); /* Set divider */ SCB_WDTCLKDIV = SCB_WDTCLKDIV_DIV1; /* Enable WDT clock */ SCB_PDRUNCFG &= ~(SCB_PDRUNCFG_WDTOSC); // Switch main clock to WDT output SCB_MAINCLKSEL = SCB_MAINCLKSEL_SOURCE_WDTOSC; SCB_MAINCLKUEN = SCB_MAINCLKUEN_UPDATE; // Update clock source SCB_MAINCLKUEN = SCB_MAINCLKUEN_DISABLE; // Toggle update register once SCB_MAINCLKUEN = SCB_MAINCLKUEN_UPDATE; // Wait until the clock is updated while (!(SCB_MAINCLKUEN & SCB_MAINCLKUEN_UPDATE)); } /**************************************************************************/ /*! \brief Turns off select peripherals and puts the device in deep-sleep mode. This function will put the device into deep-sleep mode. Most gpio pins can be used to wake the device up, but the pins must first be configured for this in pmuInit. By default, only pin 0.1 (ISP) is configured as a wakeup source. The device can be configured to wakeup from deep-sleep mode after a specified delay with the wakeupSeconds parameter. This will configure 32-bit timer 0 to set a match on pin 0.1 (ISP), which will wakeup the device up. The timer will be configured to run off the WDT OSC while in deep-sleep mode, meaning that WDTOSC should not be powered off (using the sleepCtrl parameter) when a wakeup delay is specified. The sleepCtrl parameter is used to indicate which peripherals should be put in sleep mode (see the SCB_PDSLEEPCFG register for details). @param[in] sleepCtrl The bits to set in the SCB_PDSLEEPCFG register. This controls which peripherals will be put in sleep mode. @param[in] wakeupSeconds The number of seconds to wait until the device will wakeup. If you do not wish to wakeup after a specific delay, enter a value of 0. */ /**************************************************************************/ void pmuDeepSleep(U32 sleepCtrl, U32 wakeupSeconds) { SCB_PDAWAKECFG = SCB_PDRUNCFG; sleepCtrl &= ~(1 << 9); // MAIN_REGUL_PD sleepCtrl |= (1 << 11) | (1 << 12); // LP_REGUL_PD SCB_PDSLEEPCFG = sleepCtrl; SCB_SCR |= SCB_SCR_SLEEPDEEP; /* Configure system to run from WDT and set TMR32B0 for wakeup */ if (wakeupSeconds > 0) { // Make sure WDTOSC isn't disabled in PDSLEEPCFG SCB_PDSLEEPCFG &= ~(SCB_PDSLEEPCFG_WDTOSC_PD); // Disable 32-bit timer 0 if currently in use timer32Disable(0); // Reconfigure clock to run from WDTOSC pmuWDTClockInit(); /* Enable the clock for CT32B0 */ SCB_SYSAHBCLKCTRL |= (SCB_SYSAHBCLKCTRL_CT32B0); /* Configure PIO0.1 as Timer0_32 MAT2 */ IOCON_PIO0_1 &= ~IOCON_PIO0_1_FUNC_MASK; IOCON_PIO0_1 |= IOCON_PIO0_1_FUNC_CT32B0_MAT2; /* Set appropriate timer delay */ TMR_TMR32B0MR0 = PMU_WDTCLOCKSPEED_HZ * wakeupSeconds; /* Configure match control register to raise an interrupt and reset on MR0 */ TMR_TMR32B0MCR = (TMR_TMR32B0MCR_MR0_INT_ENABLED | TMR_TMR32B0MCR_MR0_RESET_ENABLED); /* Configure external match register */ TMR_TMR32B0EMR &= ~(0xFF<<4); // Clear EMR config bits TMR_TMR32B0EMR |= TMR_TMR32B0EMR_EMC2_TOGGLE; // MR2 (GPIO0.1) Toggle /* Enable the TIMER0 interrupt */ NVIC_EnableIRQ(TIMER_32_0_IRQn); /* Start the timer */ TMR_TMR32B0TCR = TMR_TMR32B0TCR_COUNTERENABLE_ENABLED; } // Send Wait For Interrupt command __asm volatile ("WFI"); return; } |
drvpins(0, 0, 0, 0, 0, 0, 0, 0); drvpins(0xFFF, 0xFFF, 0xFFF, 0xFFF, 0xFFF, 0xFFF, 0x3F, 0x3F); |
Content originally posted in LPCWare by johnhe on Mon Apr 19 09:05:49 MST 2010
[FONT=Helvetica, Arial, sans-serif]My guess is that there is no interest in presenting code that can be easily and independently run to settle issues.
So I did it on my own.
I have done some simple tests with an LPC1343 LPCXpresso board.
These are my conclusions.
There is good evidence that there is a silicon fault in the LPC1343 that will allow a timer peripheral to run during deep sleep (and output a match result) if the system oscillator has been changed to the watchdog oscillator and the watchdog oscillator is not shut down in deep sleep. About 5uA is added to the normal deep sleep current of the LPC1343 of 30uA.
No one should rely on this fault remaining in future batches to build software with, such as using the fault to wake up from deep sleep by using a timer output match to trigger start logic.
I have attached my test software along with a hex file of the code that demonstrates the fault. Both are in the attached zip file
John Heenan
[/FONT]