Author Topic: SAML21 SleepWalking UART picoPower reception  (Read 2133 times)

0 Members and 1 Guest are viewing this topic.

Offline AloyseTechTopic starter

  • Regular Contributor
  • *
  • Posts: 121
  • Country: fr
SAML21 SleepWalking UART picoPower reception
« on: November 30, 2017, 10:28:04 am »
Hi,

I would like to use the picoPower functionnalities of the saml21 for continuous uart reception, but I don't know where to start. I can't find any example or application note describing the process with the low power sercom...

Anyone has tried this before? Could someone provide some guidance or documentation?

At the moment I have continuous reception enabled but not in low power mode...

Thanks in advance! :)
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11234
  • Country: us
    • Personal site
Re: SAML21 SleepWalking UART picoPower reception
« Reply #1 on: November 30, 2017, 05:55:12 pm »
I have not tried sleep walking, but it looks like specific configuration will mostly depend on what exactly you want to do.

Presumably you need to process the received data at some point. What is this point? Each byte? Fixed number of bytes?
Alex
 

Offline AloyseTechTopic starter

  • Regular Contributor
  • *
  • Posts: 121
  • Country: fr
Re: SAML21 SleepWalking UART picoPower reception
« Reply #2 on: December 01, 2017, 09:09:12 am »
I'm waiting a special char on uart to process it. At the moment I check each byte received in the uart callback IRQ. The number of byte is not fixed : between 10 and 60 bytes.

I forgot to say I'm using the ASF and AS7.

To reduce power I've tried the following code :

After all clocks and driver have been initialized and before main loop :
Code: [Select]
    system_set_sleepmode(SYSTEM_SLEEPMODE_STANDBY);
    struct system_standby_config config;
    system_standby_get_config_defaults(&config);
    config.enable_dpgpd1 = true;
    config.enable_dpgpd0 = true;
    config.power_domain = SYSTEM_POWER_DOMAIN_PD0;
    config.vregs_mode = SYSTEM_SYSTEM_VREG_SWITCH_LP;
    system_standby_set_config(&config);

at some point in the main loop, after a special char has been received in IRQ and a flag set to indicate the processing of data :
Code: [Select]
    printf("Going to sleep...\n");
    system_gclk_gen_disable(1);
    //system_gclk_gen_disable(0); //do not do that, system hangs because GCLK0 is used by the cpu?
    system_sleep();     
    //system_gclk_gen_enable(0)
    system_gclk_gen_enable(1);
    printf("Woke up!\n");

But I see no difference in the current consumption after calling system_sleep() ! I have a constant 2mA current used by the CPU.
I'm using the Power Debugger integrated in AS7, and my jumpers on the SAML21XPLAINED are set like this : I/O = BYPASS, MCU = MEASURE.
« Last Edit: December 01, 2017, 09:13:07 am by AloyseTech »
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11234
  • Country: us
    • Personal site
Re: SAML21 SleepWalking UART picoPower reception
« Reply #3 on: December 01, 2017, 06:56:28 pm »
You don't have to manually enable disable things when going to sleep. Just configure RUNSTDBY bits as appropriate.

I don't think sleepwalking will help you here. SERCOM will need to have clock supplied to it in order to receive a character. And then you will still need to process each character to get the one you need. You can lower the consumption by supplying a lower clock to the SERCOM, by dividing it at the source instead of using baudrate generator divider for this.
Alex
 

Offline AloyseTechTopic starter

  • Regular Contributor
  • *
  • Posts: 121
  • Country: fr
Re: SAML21 SleepWalking UART picoPower reception
« Reply #4 on: December 01, 2017, 07:34:34 pm »
I don't really know how to use the sleepwalking feature but this was somethng that looked interesting : no CPU clock but peripheral clock "on demand" in stndby.
I already run the whole core at 3MHz only...
I also have the Atmel/Microchip LoRaWan 1.1.0_0_E stack for SAM device. But there is no indication on how to reduce power consuption in this stack...

Some guidance would really be appreciated :)

Here is my UART initialisation code :
Code: [Select]
struct usart_config config_usart;
    usart_get_config_defaults(&config_usart);
   
    // TIC usart protocol definition
    config_usart.baudrate = 9600;
    config_usart.character_size = USART_CHARACTER_SIZE_8BIT;
    config_usart.stopbits = USART_STOPBITS_1;
   
    //Pinmux setting
    config_usart.mux_setting = EXT3_LPUART_SERCOM_MUX_SETTING;
    config_usart.pinmux_pad0 = EXT3_LPUART_SERCOM_PINMUX_PAD0;
    config_usart.pinmux_pad1 = EXT3_LPUART_SERCOM_PINMUX_PAD1;
    config_usart.pinmux_pad2 = EXT3_LPUART_SERCOM_PINMUX_PAD2;
    config_usart.pinmux_pad3 = EXT3_LPUART_SERCOM_PINMUX_PAD3;
   
    config_usart.run_in_standby = false;
   
    status_code_genare_t status = usart_init(&uartInst, EXT3_LPUART_MODULE, &config_usart);
    while (status != STATUS_OK)
    {
        printf("Initializing SERCOM5 USART... err %#04X\n", status);
        status = usart_init(&uartInst, EXT3_LPUART_MODULE, &config_usart);
    }
    usart_enable(&uartInst);

And my conf_clocks.h file :
Code: [Select]
#include <clock.h>

#ifndef CONF_CLOCKS_H_INCLUDED
#  define CONF_CLOCKS_H_INCLUDED

/* System clock bus configuration */
#  define CONF_CLOCK_CPU_CLOCK_FAILURE_DETECT     false
#  define CONF_CLOCK_FLASH_WAIT_STATES            0
#  define CONF_CLOCK_CPU_DIVIDER                  SYSTEM_MAIN_CLOCK_DIV_32 //SYSTEM_MAIN_CLOCK_DIV_1
#  define CONF_CLOCK_LOW_POWER_DIVIDER            SYSTEM_MAIN_CLOCK_DIV_128 //SYSTEM_MAIN_CLOCK_DIV_1
#  define CONF_CLOCK_BACKUP_DIVIDER               SYSTEM_MAIN_CLOCK_DIV_128 //SYSTEM_MAIN_CLOCK_DIV_1

/* SYSTEM_CLOCK_SOURCE_OSC16M configuration - Internal 16MHz oscillator */
#  define CONF_CLOCK_OSC16M_FREQ_SEL              SYSTEM_OSC16M_4M          //SYSTEM_OSC16M_8M
#  define CONF_CLOCK_OSC16M_ON_DEMAND             false
#  define CONF_CLOCK_OSC16M_RUN_IN_STANDBY        false

/* SYSTEM_CLOCK_SOURCE_XOSC configuration - External clock/oscillator */
#  define CONF_CLOCK_XOSC_ENABLE                  true
#  define CONF_CLOCK_XOSC_EXTERNAL_CRYSTAL        SYSTEM_CLOCK_EXTERNAL_CRYSTAL
#  define CONF_CLOCK_XOSC_EXTERNAL_FREQUENCY      12000000UL
#  define CONF_CLOCK_XOSC_STARTUP_TIME            SYSTEM_XOSC_STARTUP_32768
#  define CONF_CLOCK_XOSC_AUTO_GAIN_CONTROL       true
#  define CONF_CLOCK_XOSC_ON_DEMAND               true
#  define CONF_CLOCK_XOSC_RUN_IN_STANDBY          false

/* SYSTEM_CLOCK_SOURCE_XOSC32K configuration - External 32KHz crystal/clock oscillator */
#  define CONF_CLOCK_XOSC32K_ENABLE               true
#  define CONF_CLOCK_XOSC32K_EXTERNAL_CRYSTAL     SYSTEM_CLOCK_EXTERNAL_CRYSTAL
#  define CONF_CLOCK_XOSC32K_STARTUP_TIME         SYSTEM_XOSC32K_STARTUP_65536
#  define CONF_CLOCK_XOSC32K_ENABLE_1KHZ_OUPUT    false
#  define CONF_CLOCK_XOSC32K_ENABLE_32KHZ_OUTPUT  true
#  define CONF_CLOCK_XOSC32K_ON_DEMAND            true
#  define CONF_CLOCK_XOSC32K_RUN_IN_STANDBY       false

/* SYSTEM_CLOCK_SOURCE_OSC32K configuration - Internal 32KHz oscillator */
#  define CONF_CLOCK_OSC32K_ENABLE                true
#  define CONF_CLOCK_OSC32K_STARTUP_TIME          SYSTEM_OSC32K_STARTUP_130
#  define CONF_CLOCK_OSC32K_ENABLE_1KHZ_OUTPUT    true
#  define CONF_CLOCK_OSC32K_ENABLE_32KHZ_OUTPUT   false
#  define CONF_CLOCK_OSC32K_ON_DEMAND             true
#  define CONF_CLOCK_OSC32K_RUN_IN_STANDBY        false

/* SYSTEM_CLOCK_SOURCE_OSCULP32K configuration - Internal Ultra Low Power 32KHz oscillator */
#  define CONF_CLOCK_OSCULP32K_ENABLE_1KHZ_OUTPUT    true
#  define CONF_CLOCK_OSCULP32K_ENABLE_32KHZ_OUTPUT   true

/* SYSTEM_CLOCK_SOURCE_DFLL configuration - Digital Frequency Locked Loop */
#  define CONF_CLOCK_DFLL_ENABLE                  true
#  define CONF_CLOCK_DFLL_LOOP_MODE               SYSTEM_CLOCK_DFLL_LOOP_MODE_CLOSED
#  define CONF_CLOCK_DFLL_ON_DEMAND               false
#  define CONF_CLOCK_DFLL_RUN_IN_STANDBY          false

/* DFLL open loop mode configuration */
#  define CONF_CLOCK_DFLL_FINE_VALUE              (512)

/* DFLL closed loop mode configuration */
#  define CONF_CLOCK_DFLL_SOURCE_GCLK_GENERATOR   GCLK_GENERATOR_1
#  define CONF_CLOCK_DFLL_MULTIPLY_FACTOR         (48000000 / 32768) //(48000000 / 32768)
#  define CONF_CLOCK_DFLL_QUICK_LOCK              true
#  define CONF_CLOCK_DFLL_TRACK_AFTER_FINE_LOCK   true
#  define CONF_CLOCK_DFLL_KEEP_LOCK_ON_WAKEUP     true
#  define CONF_CLOCK_DFLL_ENABLE_CHILL_CYCLE      true
#  define CONF_CLOCK_DFLL_MAX_COARSE_STEP_SIZE    (0x1f / 4)
#  define CONF_CLOCK_DFLL_MAX_FINE_STEP_SIZE      (0xff / 4)

/* SYSTEM_CLOCK_SOURCE_DPLL configuration - Digital Phase-Locked Loop */
#  define CONF_CLOCK_DPLL_ENABLE                  false
#  define CONF_CLOCK_DPLL_ON_DEMAND               true
#  define CONF_CLOCK_DPLL_RUN_IN_STANDBY          false
#  define CONF_CLOCK_DPLL_LOCK_BYPASS             false
#  define CONF_CLOCK_DPLL_WAKE_UP_FAST            false
#  define CONF_CLOCK_DPLL_LOW_POWER_ENABLE        false

#  define CONF_CLOCK_DPLL_LOCK_TIME               SYSTEM_CLOCK_SOURCE_DPLL_LOCK_TIME_DEFAULT
#  define CONF_CLOCK_DPLL_REFERENCE_CLOCK         SYSTEM_CLOCK_SOURCE_DPLL_REFERENCE_CLOCK_XOSC32K
#  define CONF_CLOCK_DPLL_FILTER                  SYSTEM_CLOCK_SOURCE_DPLL_FILTER_DEFAULT
#  define CONF_CLOCK_DPLL_PRESCALER               SYSTEM_CLOCK_SOURCE_DPLL_DIV_4


#  define CONF_CLOCK_DPLL_REFERENCE_FREQUENCY     32768
#  define CONF_CLOCK_DPLL_REFERENCE_DIVIDER       1
#  define CONF_CLOCK_DPLL_OUTPUT_FREQUENCY        48000000

/* DPLL GCLK reference configuration */
#  define CONF_CLOCK_DPLL_REFERENCE_GCLK_GENERATOR GCLK_GENERATOR_1
/* DPLL GCLK lock timer configuration */
#  define CONF_CLOCK_DPLL_LOCK_GCLK_GENERATOR     GCLK_GENERATOR_1


/* Set this to true to configure the GCLK when running clocks_init. If set to
 * false, none of the GCLK generators will be configured in clocks_init(). */
#  define CONF_CLOCK_CONFIGURE_GCLK               true

/* Configure GCLK generator 0 (Main Clock) */
#  define CONF_CLOCK_GCLK_0_ENABLE                true
#  define CONF_CLOCK_GCLK_0_RUN_IN_STANDBY        false
#  define CONF_CLOCK_GCLK_0_CLOCK_SOURCE          SYSTEM_CLOCK_SOURCE_DFLL
#  define CONF_CLOCK_GCLK_0_PRESCALER             1
#  define CONF_CLOCK_GCLK_0_OUTPUT_ENABLE         false

/* Configure GCLK generator 1 */
#  define CONF_CLOCK_GCLK_1_ENABLE                true
#  define CONF_CLOCK_GCLK_1_RUN_IN_STANDBY        true
#  define CONF_CLOCK_GCLK_1_CLOCK_SOURCE          SYSTEM_CLOCK_SOURCE_XOSC32K
#  define CONF_CLOCK_GCLK_1_PRESCALER             1
#  define CONF_CLOCK_GCLK_1_OUTPUT_ENABLE         false

/* Configure GCLK generator 2  */
#  define CONF_CLOCK_GCLK_2_ENABLE                false
#  define CONF_CLOCK_GCLK_2_RUN_IN_STANDBY        false
#  define CONF_CLOCK_GCLK_2_CLOCK_SOURCE          SYSTEM_CLOCK_SOURCE_OSC16M
#  define CONF_CLOCK_GCLK_2_PRESCALER             1
#  define CONF_CLOCK_GCLK_2_OUTPUT_ENABLE         false

/* Configure GCLK generator 3 */
#  define CONF_CLOCK_GCLK_3_ENABLE                false
#  define CONF_CLOCK_GCLK_3_RUN_IN_STANDBY        false
#  define CONF_CLOCK_GCLK_3_CLOCK_SOURCE          SYSTEM_CLOCK_SOURCE_OSC16M
#  define CONF_CLOCK_GCLK_3_PRESCALER             1
#  define CONF_CLOCK_GCLK_3_OUTPUT_ENABLE         false

/* Configure GCLK generator 4 */
#  define CONF_CLOCK_GCLK_4_ENABLE                false
#  define CONF_CLOCK_GCLK_4_RUN_IN_STANDBY        false
#  define CONF_CLOCK_GCLK_4_CLOCK_SOURCE          SYSTEM_CLOCK_SOURCE_OSC16M
#  define CONF_CLOCK_GCLK_4_PRESCALER             1
#  define CONF_CLOCK_GCLK_4_OUTPUT_ENABLE         false

/* Configure GCLK generator 5 */
#  define CONF_CLOCK_GCLK_5_ENABLE                false
#  define CONF_CLOCK_GCLK_5_RUN_IN_STANDBY        false
#  define CONF_CLOCK_GCLK_5_CLOCK_SOURCE          SYSTEM_CLOCK_SOURCE_OSC16M
#  define CONF_CLOCK_GCLK_5_PRESCALER             1
#  define CONF_CLOCK_GCLK_5_OUTPUT_ENABLE         false

/* Configure GCLK generator 6 */
#  define CONF_CLOCK_GCLK_6_ENABLE                false
#  define CONF_CLOCK_GCLK_6_RUN_IN_STANDBY        false
#  define CONF_CLOCK_GCLK_6_CLOCK_SOURCE          SYSTEM_CLOCK_SOURCE_OSC16M
#  define CONF_CLOCK_GCLK_6_PRESCALER             1
#  define CONF_CLOCK_GCLK_6_OUTPUT_ENABLE         false

/* Configure GCLK generator 7 */
#  define CONF_CLOCK_GCLK_7_ENABLE                false
#  define CONF_CLOCK_GCLK_7_RUN_IN_STANDBY        false
#  define CONF_CLOCK_GCLK_7_CLOCK_SOURCE          SYSTEM_CLOCK_SOURCE_OSC16M
#  define CONF_CLOCK_GCLK_7_PRESCALER             1
#  define CONF_CLOCK_GCLK_7_OUTPUT_ENABLE         false

/* Configure GCLK generator 8 */
#  define CONF_CLOCK_GCLK_8_ENABLE                false
#  define CONF_CLOCK_GCLK_8_RUN_IN_STANDBY        false
#  define CONF_CLOCK_GCLK_8_CLOCK_SOURCE          SYSTEM_CLOCK_SOURCE_OSC16M
#  define CONF_CLOCK_GCLK_8_PRESCALER             1
#  define CONF_CLOCK_GCLK_8_OUTPUT_ENABLE         false
#endif /* CONF_CLOCKS_H_INCLUDED */
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11234
  • Country: us
    • Personal site
Re: SAML21 SleepWalking UART picoPower reception
« Reply #5 on: December 01, 2017, 07:45:06 pm »
With SleepWalking, you can have core stopped and SERCOM5 (in PD0) will wake up PD1 and DMA controller will transfer the byte, and go back to sleep. But you can't examine the byte and act on it without CPU intervention.

The best you can do is have the system be in a sleep mode with PD0 active for SERCOM, and wake up on the received byte. What exact power consumption to expect - I don't know, it depends on may factors, it may end up being 2 mA, UART has to consume something. I also have no idea about ASF.

Alex
 

Offline AloyseTechTopic starter

  • Regular Contributor
  • *
  • Posts: 121
  • Country: fr
Re: SAML21 SleepWalking UART picoPower reception
« Reply #6 on: December 01, 2017, 08:27:10 pm »
I don't mind using bare metal to reduce power consumption, but I don't have the choice for the stack wich use the asf...
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf