Arm Community
Arm Community
  • Site
  • User
  • Site
  • Search
  • User
  • Groups
    • Arm Research
    • DesignStart
    • Education Hub
    • Graphics and Gaming
    • High Performance Computing
    • Innovation
    • Multimedia
    • Open Source Software and Platforms
    • Physical
    • Processors
    • Security
    • System
    • Software Tools
    • TrustZone for Armv8-M
    • 中文社区
  • Blog
    • Artificial Intelligence
    • Automotive
    • Healthcare
    • HPC
    • Infrastructure
    • Innovation
    • Internet of Things
    • Machine Learning
    • Mobile
    • Smart Homes
    • Wearables
  • Forums
    • All developer forums
    • IP Product forums
    • Tool & Software forums
    • Pelion IoT Platform
  • Activity
  • Support
    • Open a support case
    • Documentation
    • Downloads
    • Training
    • Arm Approved program
    • Arm Design Reviews
  • More
  • Cancel
System
  • Developer Community
  • IP Products
  • System
  • Jump...
  • Cancel
System
Embedded blog Utilising The LLS Mode And The LLWU For The Kl25z Series
  • Blogs
  • Forums
  • Videos & Files
  • Mentions
  • Sub-Groups
  • Tags
  • Jump...
  • Cancel
  • New
More blogs in System
  • Embedded blog

  • SoC Design blog

Tags
  • adxl-345
  • energy-harvesting
  • accelerometer
  • llwu
  • remote-control
  • Cortex-M0+
  • lls
Actions
  • RSS
  • More
  • Cancel
Related blog posts
Related forum threads

Utilising The LLS Mode And The LLWU For The Kl25z Series

Elliott Smith
Elliott Smith
December 2, 2013

This blog post is concerned with how we got the MCU in the Batteryless Energy Harvesting Remote Control to go into a Low Leakage Mode. It is also concerned with the Low Leakage Wake Up Unit (LLWU) and how this can be used to wake up the remote control from sleep.

In the Energy Harvesting Remote Control we used an MCU from the Freescale KL25 sub family of MCU’s have a number of different sleep modes that can be utilised for low power applications. We wanted to be able to enter into a stop mode to reduce power consumption after a degree of inactivity. We also wanted to be able to wake the MCU from a user input. The Low Leakage Stop (LLS) Modes and the Low Leakage Wake Up Unit (LLWU) are ideal for this application.

There are two modes we could have chosen to use the LLWU to wake the MCU up, Low Leakage Stop (LLS) mode or Very Low Leakage Stop (VLLS) mode (of which there are 3 options VLLS0, VLLS1 or VLLS3). The LLS mode leaves most of the peripherals in state retention mode and its normal recovery method is a Wakeup Interrupt. The VLLS mode disables most of the peripherals and its normal recovery method is a Wakeup Reset. See the Reference Manual for the MkL25Z series for more details.

We opted to put the MCU into the Low Leakage Stop Mode. The current in this mode is somewhere around 1.9uA. In VLLS0 mode this could have been reduced down to 381nA. We decided to use the LLS mode to avoid the reset, this would ultimately save time. We also wanted to wake the remote control using an Accelerometer, because the LLS mode keeps peripherals in a state of retention, this was ideal.  The Low Leakage Stop Mode has a sufficiently low current to allow the remote control to charge up.

We entered into a LLS mode as shown in the code below:

void SMC_sleep(void)
{
    //Enable the LLWU Pins before putting the MCU into a sleep state:
  PORTC->PCR[6] |= (0x1 << 8);
  FPTC->PDDR &= ~(0x1 << 6);

    PORTB->PCR[0] |= (0x1 << 8);
  FPTB->PDDR &= ~(0x1);

    LLWU_pinEnable(10,3);
    LLWU_pinEnable(5,3);

    NVIC_EnableIRQ(LLW_IRQn);
  SMC_sleepDeep(0);

}

void SMC_sleepDeep(int mode)
{
  volatile unsigned int dummyread;

  /* The PMPROT register allows the MCU to enter the LLS modes.*/
  SMC->PMPROT = SMC_PMPROT_ALLS_MASK;   

  /* Set the STOPM field to 0b011 for LLS mode */
  SMC->PMCTRL &= ~SMC_PMCTRL_STOPM_MASK; 
  SMC->PMCTRL |=  SMC_PMCTRL_STOPM(0x3); 

  /*wait for write to complete to SMC before stopping core */  
  dummyread = SMC->PMCTRL;
  dummyread++;

  /* Set the SLEEPDEEP bit to enable deep sleep mode (STOP) */
  SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;

  __wfi();
}


To wake the remote control up we added two options. One of the LLWU pins for the KL25z series is TSI channel 0. We configured this so a touch on this electrode would wake up the remote control. Another solution we also incorporated was to get the remote control to wake up from an Accelerometer. This was configured using one of the ADXL345 accelerometer interrupt pins and was used to wake the MCU up if any activity was detected. The code to enable the LLWU pin is shown below, we configured the LLWU to wake the MCU up if there was any change experienced on the pins, but they could also have been configured for rising or falling edge:

/*------------------------------------------------------------------------------
  Enable a pin for use with the low leakage wake up unit
 *------------------------------------------------------------------------------*/
void LLWU_pinEnable(int pin, int mode)
{    
    if(pin < 4){
        switch(mode){
                case 0:
                LLWU->PE1 |=     (0x0 << (pin*2));
                break;
                case 1:
                LLWU->PE1 |=     (0x1 << (pin*2));
                break;
                case 2:
                LLWU->PE1 |=     (0x2 << (pin*2));
                break;
                case 3:
                LLWU->PE1 |=     (0x3 << (pin*2));
                break;    
            }    
    }
    else if((pin >= 4) && (pin < 8)){
        switch(mode){
                case 0:
                LLWU->PE2 |=     (0x0 << ((pin-4)*2));
                break;
                case 1:
                LLWU->PE2 |=     (0x1 << ((pin-4)*2));
                break;
                case 2:
                LLWU->PE2 |=     (0x2 << ((pin-4)*2));
                break;
                case 3:
                LLWU->PE2 |=     (0x3 << ((pin-4)*2));
                break;    
            }        
    }    
    else if((pin >= 8) && (pin < 12)){
        switch(mode){
                case 0:
                LLWU->PE3 |=     (0x0 << ((pin-8)*2));
                break;
                case 1:
                LLWU->PE3 |=     (0x1 << ((pin-8)*2));
                break;
                case 2:
                LLWU->PE3 |=     (0x2 << ((pin-8)*2));
                break;
                case 3:
                LLWU->PE3 |=     (0x3 << ((pin-8)*2));
                break;        
            }    
    }
    else if((pin >= 12) && (pin < 16)){
        switch(mode){
                case 0:
                LLWU->PE4 |=     (0x0 << ((pin-12)*2));
                break;
                case 1:
                LLWU->PE4 |=     (0x1 << ((pin-12)*2));
                break;
                case 2:
                LLWU->PE4 |=     (0x2 << ((pin-12)*2));
                break;
                case 3:
                LLWU->PE4 |=     (0x3 << ((pin-12)*2));
                break;    
            }    
    }
    NVIC_EnableIRQ(LLW_IRQn);
}


It was important to enable the interrupt in this section of code, this was done once the pin and mode were determined. The code called when the LLWU pins experience a change is shown below:

void LLW_IRQHandler()
{
        LLWU_clear();
        PMC->REGSC |= (1UL << 3);
        SystemCoreClockUpdate();                      /* Get Core Clock Frequency */
        SysTick_Config(SystemCoreClock/1000);         /* Generate interrupt each 1 ms    */

}


This is the code required to ensure that the MCU has fully woken from the stop mode.

A note on the Accelerometer used:

The accelerometer we used was an ADXL345. The code below shows how we configured the interrupt for this accelerometer:

void sensor_int(void)
{            
          char cmd[1];
          char interrupt=0;

          FPTC->PDOR |= (1UL << 11);
          Delay(500);
          I2C_configure();

          setInterruptEnableControl(0x00);           //disable all interrupts intially

          setActivityThreshold(150);                 //set the threshold for determining activity

          setActivityInactivityControl(0x70);        //set activity to be detected on any axis

          setInterruptMappingControl(0xEF);          //send interrupt for activity to interrupt pin 1
        
          setInterruptEnableControl(0x7E);           //enable interrupt for activity
    
          interrupt = getInterruptSource();          //get interrupt source for testing
    
}


The Datasheet for this accelerometer shows that an interrupt can be triggered for a single tap, a double tap, activity, inactivity and free fall. In our case we configured the accelerometer interrupt simply for activity.

Anonymous
Embedded blog
  • Embedded blog: Development of Arm based systems with Synopsys Virtual Prototyping: Anytime, Anywhere!

    Jason Andrews
    Jason Andrews
    Find out more about virtual prototyping from Synopsys as thousands of engineers around the world have been asked to work from home.
    • May 5, 2020
  • Embedded blog: Accelerating Innovation for Safety Systems with Arm Flexible Access

    Chet Babla
    Chet Babla
    Arm is proud to announce the addition of Arm Safety Packages for select IP within Arm Flexible Access, with the goal to make it easier for developers in the automotive and other safety-related industries…
    • February 19, 2020
  • Embedded blog: Functional Safety on Arm – Beyond Automotive

    Antonio Priore
    Antonio Priore
    Arm has moved a long way from the days where our only ‘safety’ requirement was to provide ECC or parity protections on CPU RAMs and we are now able to offer a number of System IP, GPUs, ISPs and NPUs as…
    • December 13, 2019