Self Wakeup Timer (WKT) on LPC8XX not waking!

cancel
Showing results for 
Search instead for 
Did you mean: 

Self Wakeup Timer (WKT) on LPC8XX not waking!

335 Views
leo838
Contributor II

Hello all,

I'm trying to get the self wakeup timer to restart an LPC810 (standalone, no board) after a deep power down. The application is to simulate a 'lighthouse' type effect with an LED, power down & after approx 8 secs reset & repeat.

The code:

/*
===============================================================================
 Name        : lighthouseD.c
 Author      : $(OFO)
 Version     : v.01
 Copyright   : $(OFO)
 Description : Create lighthouse type effect with LED
                : Final project for release onto stand alone chip!!
                : NOTE: If board becomes 'bricked' connect pins 7 & 8 of port J7 together
                : i.e. PIO0_1 Pin 5
                : then connect USB cable (places into ISP mode)
===============================================================================
 */

#if defined (__USE_LPCOPEN)
#if defined(NO_BOARD_LIB)
#include "chip.h"
#else
#include "board.h"
#endif
#endif

#include <cr_section_macros.h>

#define LED1_GPIO_PORT_NUM    0
#define LED1_GPIO_BIT_NUM    0
#define RAMP_TIME 2 // How many seconds to go from off to full bright & vice-versa

volatile uint32_t millis = 0;    //millisecond counter

void SysTick_Handler(void) {
    //our systick interrupt handler
    millis++;
}

void delay_ms(uint32_t ms) {
    //delay (ms)
    uint32_t now = millis;
    while ((millis - now) < ms);
}

void WKT_IRQHandler(void){
    /* Clear self wakeup timer (WKT) interrupt request */
    Chip_WKT_ClearIntStatus(LPC_WKT);
}

void deep_power_down (uint32_t secs){
    // Function to put micro into deep power down (most power saving mode)
    // Woken by self wake-up timer
    // Full reset on wake-up
// Disable wakeup pin
    Chip_PMU_SetPowerDownControl(LPC_PMU, PMU_DPDCTRL_WAKEPAD);

    /* Alarm/wake timer as chip wakeup source */
    Chip_SYSCTL_EnablePeriphWakeup(SYSCTL_WAKEUP_WKTINT);

    /* Enable and reset WKT clock */
    Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_WKT);
    Chip_SYSCTL_PeriphReset(RESET_WKT);

    /* 10KHz clock source */
    Chip_WKT_SetClockSource(LPC_WKT, WKT_CLKSRC_10KHZ);

    /* Setup for wakeup in 5s */
    Chip_WKT_LoadCount(LPC_WKT, Chip_WKT_GetClockRate(LPC_WKT) * 8);

    // Enable deep power down mode
    // Will restart with full reset
    // Note: This function includes a __WFI !!
    Chip_PMU_DeepPowerDownState(LPC_PMU);

/*
    Chip_PMU_SetPowerDownControl(LPC_PMU, PMU_DPDCTRL_LPOSCEN | PMU_DPDCTRL_LPOSCDPDEN | PMU_DPDCTRL_WAKEPAD);

    // Ensure deep power down not inhibited (PCON, bit 3)
    // Can only be cleared by chip reset

    // Setup for wakeup in X s
    Chip_WKT_LoadCount(LPC_WKT, Chip_WKT_GetClockRate(LPC_WKT) * secs);

    // Enable deep power down mode
    // Will restart with full reset
    // Note: This function includes a __WFI !!
    Chip_PMU_DeepPowerDownState(LPC_PMU);
*/

}

int main(void) {
    volatile static int c;
    int time_per = 0;    // Percentage time for LED to be on
    int ms_old = 0;

#if defined (__USE_LPCOPEN)
    // Read clock settings and update SystemCoreClock variable
    SystemCoreClockUpdate();
#if !defined(NO_BOARD_LIB)
    // Set up and initialize all required blocks and
    // functions related to the board hardware
    Board_Init();
    // Set the LED to the state of "On"
    //Board_LED_Set(0, true);
#endif
#endif


    // Setup systick clock interrupt @1ms
    // This function is in core_cm0plus.h in lpc_chip_8xx project
    SysTick_Config(Chip_Clock_GetSystemClockRate()/1000);

    // Setup LED port pin
    Chip_GPIO_SetPinDIROutput(LPC_GPIO_PORT, LED1_GPIO_PORT_NUM, LED1_GPIO_BIT_NUM);
    Chip_GPIO_SetPinState(LPC_GPIO_PORT, LED1_GPIO_PORT_NUM, LED1_GPIO_BIT_NUM, true);
    Chip_GPIO_SetPinState(LPC_GPIO_PORT, LED1_GPIO_PORT_NUM, LED1_GPIO_BIT_NUM, false);    // Ensure off

    // Check did we restart from deep power down?
    if ((Chip_PMU_GetSleepFlags(LPC_PMU) & PMU_PCON_DPDFLAG) == TRUE){
        // We woke from deep power down, must clear
        Chip_PMU_ClearSleepFlags(LPC_PMU, PMU_PCON_DPDFLAG);

        // Flash LED
        Chip_GPIO_SetPinState(LPC_GPIO_PORT, LED1_GPIO_PORT_NUM, LED1_GPIO_BIT_NUM, TRUE);
        delay_ms(1000);
        Chip_GPIO_SetPinState(LPC_GPIO_PORT, LED1_GPIO_PORT_NUM, LED1_GPIO_BIT_NUM, FALSE);

    }


    while (1){
        // Get brighter over RAMP_TIME
        ms_old = millis; // Record time

        for  (time_per = 1; time_per < 100;){

            Chip_GPIO_SetPinState(LPC_GPIO_PORT, LED1_GPIO_PORT_NUM, LED1_GPIO_BIT_NUM, TRUE);

            // Wait
            for (c = 0; c < time_per; c++);

            Chip_GPIO_SetPinState(LPC_GPIO_PORT, LED1_GPIO_PORT_NUM, LED1_GPIO_BIT_NUM, FALSE);

            // Wait
            for (c = 0; c < (100 -time_per); c++);

            if ((millis - ms_old) >  (RAMP_TIME * 10)){
                // Increase brightness
                time_per++;
                ms_old = millis;
            }

        }

        // Dwell
        Chip_GPIO_SetPinState(LPC_GPIO_PORT, LED1_GPIO_PORT_NUM, LED1_GPIO_BIT_NUM, TRUE);
        //delay_ms(1000);
        //deep_sleep(1);

        // Get dimmer over RAMP_TIME
        ms_old = millis; // Record time

        for  (time_per = 100; time_per > 1;){

            Chip_GPIO_SetPinState(LPC_GPIO_PORT, LED1_GPIO_PORT_NUM, LED1_GPIO_BIT_NUM, TRUE);

            // Wait
            for (c = 0; c < time_per; c++);

            Chip_GPIO_SetPinState(LPC_GPIO_PORT, LED1_GPIO_PORT_NUM, LED1_GPIO_BIT_NUM, FALSE);

            // Wait
            for (c = 0; c < (100 -time_per); c++);

            if ((millis - ms_old) >  (RAMP_TIME * 10)){
                // decrease brightness
                time_per--;
                ms_old = millis;
            }

        }

        // Switch off & wait
        Chip_GPIO_SetPinState(LPC_GPIO_PORT, LED1_GPIO_PORT_NUM, LED1_GPIO_BIT_NUM, FALSE);
        //delay_ms (8000);
        deep_power_down(8);

    }

    return 0 ;
}

The chip appears to successfully enter a power down state but fails to restart.

Can anyone help?

PS. I notice that there are similar functions in syscon_8xx.h & pmu_8xx.h. Which should be used? A little confusing.

Thanks,

Leo

Labels (1)
0 Kudos
2 Replies

128 Views
leo838
Contributor II

Well I think I found the issue, it seems that an additional line is required before loading the count into the SWT register, see below. I'm not quite sure but it seems like the inline function:

STATIC INLINE WKT_CLKSRC_T Chip_WKT_GetClockSource(LPC_WKT_T *pWKT)
{
    return (WKT_CLKSRC_T) (pWKT->CTRL & WKT_CTRL_CLKSEL);
}

Was not returning the correct clock source. Still haven't discovered the reason..

As an aside it seems like there's some misnaming of the files in lpc_chip_8xx library I'm using. For example the WKT functions are contained in a file called wwdt_8xx.c & the WWDT functions in the wkt_8xx.c. A little confusing!!

Regards,

Leo

/*
===============================================================================
 Name        : lighthouseD.c
 Author      : $(OFO)
 Version     : v.01
 Copyright   : $(OFO)
 Description : Create lighthouse type effect with LED
                : Final project for release onto stand alone chip!!
                : NOTE: If board becomes 'bricked' connect pins 7 & 8 of port J7 together
                : i.e. PIO0_1 Pin 5
                : then connect USB cable (places into ISP mode)
===============================================================================
 */

#if defined (__USE_LPCOPEN)
#if defined(NO_BOARD_LIB)
#include "chip.h"
#else
#include "board.h"
#endif
#endif

#include <cr_section_macros.h>

#define LED1_GPIO_PORT_NUM    0
#define LED1_GPIO_BIT_NUM    0
#define RAMP_TIME 2 // How many seconds to go from off to full bright & vice-versa

volatile uint32_t millis = 0;    //millisecond counter

void SysTick_Handler(void) {
    //our systick interrupt handler
    millis++;
}

void delay_ms(uint32_t ms) {
    //delay (ms)
    uint32_t now = millis;
    while ((millis - now) < ms);
}

void WKT_IRQHandler(void){
    /* Clear self wakeup timer (WKT) interrupt request */
    Chip_WKT_ClearIntStatus(LPC_WKT);
}

void deep_power_down (uint32_t secs){

    // Disable wakeup pin
    Chip_PMU_SetPowerDownControl(LPC_PMU, PMU_DPDCTRL_LPOSCEN | PMU_DPDCTRL_LPOSCDPDEN | PMU_DPDCTRL_WAKEPAD);

    // Needed?
    NVIC_ClearPendingIRQ(WKT_IRQn);
    NVIC_DisableIRQ(WKT_IRQn);

    // Init self wakeup timer (WKT)

    /* Enable clock for WKT */
    LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 9);

    /* Reset WKT */
    LPC_SYSCON->PRESETCTRL &= ~(1 << 9);
    LPC_SYSCON->PRESETCTRL |=  (1 << 9);

    /* set LPOSCDPDEN and LPOSCEN to 1 */
    LPC_PMU->DPDCTRL |= (3 << 2);

    /* Enable Interrupt for WKT in NVIC */
    NVIC_EnableIRQ(WKT_IRQn);

    /* Config WKT */
    LPC_WKT->CTRL  = (1 << 2);

    Chip_WKT_SetClockSource(LPC_WKT, WKT_CLKSRC_10KHZ);                  // <<--------------LINE REQUIRED!
    Chip_WKT_LoadCount(LPC_WKT, Chip_WKT_GetClockRate(LPC_WKT) * secs);
    LPC_WKT->CTRL = 1;

    /* WKT can wake up */
    LPC_SYSCON->STARTERP1 = (1 << 15);

    /* Go to deep power down mode */
    LPC_PMU->PCON = 0x3;
    Chip_PMU_DeepPowerDownState(LPC_PMU);    // Includes __WFI();
    //__WFI();

}

int main(void) {
    volatile static int c;
    int time_per = 0;    // Percentage time for LED to be on
    int ms_old = 0;

#if defined (__USE_LPCOPEN)
    // Read clock settings and update SystemCoreClock variable
    SystemCoreClockUpdate();
#if !defined(NO_BOARD_LIB)
    // Set up and initialize all required blocks and
    // functions related to the board hardware
    Board_Init();
    // Set the LED to the state of "On"
    //Board_LED_Set(0, true);
#endif
#endif


    // Setup systick clock interrupt @1ms
    // This function is in core_cm0plus.h in lpc_chip_8xx project
    SysTick_Config(Chip_Clock_GetSystemClockRate()/1000);

    // Setup LED port pin
    Chip_GPIO_SetPinDIROutput(LPC_GPIO_PORT, LED1_GPIO_PORT_NUM, LED1_GPIO_BIT_NUM);
    Chip_GPIO_SetPinState(LPC_GPIO_PORT, LED1_GPIO_PORT_NUM, LED1_GPIO_BIT_NUM, TRUE);
    Chip_GPIO_SetPinState(LPC_GPIO_PORT, LED1_GPIO_PORT_NUM, LED1_GPIO_BIT_NUM, FALSE);    // Ensure off

    // Check did we restart from deep power down?
    if ((Chip_PMU_GetSleepFlags(LPC_PMU) & PMU_PCON_DPDFLAG) != FALSE){
        // We woke from deep power down, must clear
        Chip_PMU_ClearSleepFlags(LPC_PMU, PMU_PCON_DPDFLAG | PMU_PCON_SLEEPFLAG );

        // Flash LED
        //Chip_GPIO_SetPinState(LPC_GPIO_PORT, LED1_GPIO_PORT_NUM, LED1_GPIO_BIT_NUM, TRUE);
        //delay_ms(300);
        //Chip_GPIO_SetPinState(LPC_GPIO_PORT, LED1_GPIO_PORT_NUM, LED1_GPIO_BIT_NUM, FALSE);
    }

    while (1){
        // Get brighter over RAMP_TIME
        ms_old = millis; // Record time

        for  (time_per = 1; time_per < 100;){

            Chip_GPIO_SetPinState(LPC_GPIO_PORT, LED1_GPIO_PORT_NUM, LED1_GPIO_BIT_NUM, TRUE);

            // Wait
            for (c = 0; c < time_per; c++);

            Chip_GPIO_SetPinState(LPC_GPIO_PORT, LED1_GPIO_PORT_NUM, LED1_GPIO_BIT_NUM, FALSE);

            // Wait
            for (c = 0; c < (100 -time_per); c++);

            if ((millis - ms_old) >  (RAMP_TIME * 10)){
                // Increase brightness
                time_per++;
                ms_old = millis;
            }

        }

        // Dwell
        Chip_GPIO_SetPinState(LPC_GPIO_PORT, LED1_GPIO_PORT_NUM, LED1_GPIO_BIT_NUM, TRUE);
        delay_ms(1000);

        // Get dimmer over RAMP_TIME
        ms_old = millis; // Record time

        for  (time_per = 100; time_per > 1;){

            Chip_GPIO_SetPinState(LPC_GPIO_PORT, LED1_GPIO_PORT_NUM, LED1_GPIO_BIT_NUM, TRUE);

            // Wait
            for (c = 0; c < time_per; c++);

            Chip_GPIO_SetPinState(LPC_GPIO_PORT, LED1_GPIO_PORT_NUM, LED1_GPIO_BIT_NUM, FALSE);

            // Wait
            for (c = 0; c < (100 -time_per); c++);

            if ((millis - ms_old) >  (RAMP_TIME * 10)){
                // decrease brightness
                time_per--;
                ms_old = millis;
            }

        }

        // Switch off & wait
        Chip_GPIO_SetPinState(LPC_GPIO_PORT, LED1_GPIO_PORT_NUM, LED1_GPIO_BIT_NUM, FALSE);
        deep_power_down(6);

    }

    return 0 ;
}

0 Kudos

128 Views
jeremyzhou
NXP TechSupport
NXP TechSupport

Hi,

Thank you for your interest in NXP Semiconductor products and for the opportunity to serve you.
To provide the fastest possible support, I'd highly recommend you to refer to the periph_wkt demo in the SDK library. And you can download the library via the link.
https://www.nxp.com/support/developer-resources/software-development-tools/lpc-developer-resources-/...


Have a great day,
TIC

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos