Can't enter at86rf2xx sleep mode on SAMR21-Xpro

I posted about this before but took it down as I was convinced I missed something.

I have been running RIOT with nanocoap + sensors and it consumes about 10mA and using pm_set() only drops the current by about 3mA.

I have been looking at the datasheet on how to set the transceiver to sleep to get even lower consumption.

Following the procedure I have used:

/*set sleep pin low*/
gpio_clear(AT86RF2XX_PARAM_SLEEP);
/* set pin state to TRX_OFF, FORCE_TRX_OFF,STATE_SLEEP also attempted */
at86rf2xx_set_state(&dev, AT86RF2XX_STATE_TRX_OFF);
/* set sleep pin high*/
gpio_set(AT86RF2XX_PARAM_SLEEP);
pm_set(0);

However, when the set_state() function is executed the code gets stuck and I’m unable to either set the pin or enter the low power mode. The rtt that is meant to interrupt the sleep but still keeps going and does do a callback.

I put some print statements in the at86rf2xx_set_state() function and it seems to be looping in there.

I have also tried putting my sleep procedures in the at86rf2xx test files and it still gives me the same result.

Any help would be appreciated on how to proceed.

Thank you.

Hi @yian2k I don’t have myself much experience playing with samr21-xpro and low power, I’m not sure if the development BOARD allows it, but is it possible to isolate current consumption by the radio and the mcu? Where are you measuring the current? Are the sensors powered on or in sleep mode? Are there any LEDs on? Maybe @dylad could say more, he knows the samd family quite well.

You should not mess with registers or other driver internals, use gnrc_netapi_set() to put the radio to sleep.

e.g.

static void _gnrc_netapi_set_all(netopt_state_t state)
{
    gnrc_netif_t* netif = NULL;
    while ((netif = gnrc_netif_iter(netif))) {
        /* retry if busy */
        while (gnrc_netapi_set(netif->pid, NETOPT_STATE, 0,
                               &state, sizeof(state)) == -EBUSY) {}
    }
}

Then you can

    /* disable all network interfaces */
    _gnrc_netapi_set_all(NETOPT_STATE_SLEEP);

before entering sleep.

That did it, thank you.