NRF5340 RTC0 can't got the interrupt.

Hi,

    We are currently working on power optimization and want the device to wake up from the System ON state (PM_STATE_SUSPEND_TO_IDLE) using the RTC0 timer.
However, I found that when BLE is enabled, the RTC0 timer doesn’t seem to receive any interrupts back. Could you give me some suggestions?

Here is my sample code to use the counter API

struct counter_alarm_cfg alarm_cfg;
void rtc_callback(const struct device *dev, uint8_t chan_id, uint32_t ticks, void *user_data)
{
    ARG_UNUSED(dev);
    ARG_UNUSED(chan_id);
    ARG_UNUSED(ticks);
    ARG_UNUSED(user_data);
    usb_resume_devices();
    LOG_ERR("RTC wakeup event!\n");
    trans_deepsleep_to_standby();
    //deep_sleep_mode(false);
}
void setup_rtc_wakeup(void)
{
    int ret = 0;
    const struct device *rtc_dev = DEVICE_DT_GET(DT_NODELABEL(rtc0));
    if (!device_is_ready(rtc_dev)) {
        LOG_ERR("RTC device not ready\n");
        return;
    }
    uint32_t now;
    counter_get_value(rtc_dev, &now);
    ret = counter_start(rtc_dev);
    if (ret == 0) {
        LOG_INF("counter_start ret =%d", ret);
    } else {
        LOG_ERR("counter_start setup err(%d)", ret);
    }
    //k_sleep(K_MSEC(5));
    alarm_cfg.flags = 0;
    alarm_cfg.ticks = counter_us_to_ticks(rtc_dev, 2000000);
    alarm_cfg.callback = rtc_callback;
    alarm_cfg.user_data = &alarm_cfg;

    ret = counter_get_value(rtc_dev, &now);
    LOG_INF("RTC before sleep: %u us", counter_ticks_to_us(rtc_dev, now));
    ret = counter_set_channel_alarm(rtc_dev, 0, &alarm_cfg);
     if (ret == 0) {
        LOG_INF("counter_set_channel_alarm ret =%d", ret);
    } else {
        LOG_ERR("counter_set_channel_alarm setup err(%d)", ret);
    }
    k_msleep(3000);
    counter_get_value(rtc_dev, &now);
    printk("RTC value: %u us\n", counter_ticks_to_us(rtc_dev, now));
}
prj.conf
CONFIG_BT=y
CONFIG_BT_PERIPHERAL=y
CONFIG_COUNTER=y
CONFIG_COUNTER_LOG_LEVEL_INF=y

CONFIG_RTC=y
CONFIG_RTC_UPDATE=y
CONFIG_RTC_CALIBRATION=y
CONFIG_RTC_ALARM=y
Stanly
Parents
  • Hello Stanly,

    rtc0 should be available on the nRF5340 appcore even after enabling BLE. It's rtc1 that is reserved to the system clock, also when BLE is not enabled. So I'm not sure what's stopping the alarm from triggering. But is there any reason you are not using k_msleep(), Zephyr timer, or other zephyr primitives which are running of the System clock (rtc1) to trigger the wakeup?  

    Best regards,

    Vidar

Reply
  • Hello Stanly,

    rtc0 should be available on the nRF5340 appcore even after enabling BLE. It's rtc1 that is reserved to the system clock, also when BLE is not enabled. So I'm not sure what's stopping the alarm from triggering. But is there any reason you are not using k_msleep(), Zephyr timer, or other zephyr primitives which are running of the System clock (rtc1) to trigger the wakeup?  

    Best regards,

    Vidar

Children
  • Hi Vidar,

         Because I want my device to enter the PM_STATE_SUSPEND_TO_IDLE state to achieve lower power consumption, I looked into the relevant specifications. In this state, the CPU is turned off, so regular timers can no longer be used. That’s why I’m trying to use the RTC to wake up the device and restore it to its previous state.

    Here is my sample code to force change the device PM state.

            struct pm_state_info state = {
                .state = PM_STATE_SUSPEND_TO_IDLE, // 或 PM_STATE_SUSPEND_TO_IDLE
                .substate_id = 0,
            };

            bool success = pm_state_force(0, &state);
            if (!success) {
                LOG_INF("Failed to enter deep sleep\n");
            } else {
                LOG_WRN("System entering deep sleep...\n");
            }
    Stanly
  • Hi Stanly,

    The PM CPU power states are not implemented on the nRF53: https://github.com/nrfconnect/sdk-zephyr/commit/96b38273138f05dd06cf7a58fa361f401e773e5e. The chip has two power modes: System ON mode or System OFF. System ON is the normal sleep which is entered automatically when the program enters the IDLE thread (not using the power management subsystem - CONFIG_PM), and System OFF mode is the deep sleep mode where a wakeup will trigger a system reset. 

  • Hi Vidar:
         

    Thank you for your response. I now understand that the system only supports the System OFF state. However, if I enter System OFF, the only wake-up sources available are an external sensor interrupt, USB VBUS, or reset. This means I cannot use something like an RTC timer interrupt to wake up the device, which doesn’t meet my requirements.
    May I ask if there are any alternative methods that would allow me to achieve timer-based wake-up?

    In addition, I have another issue. I switched from UART to USB CDC ACM, but in low-power mode I need to dynamically disable USB to reduce power consumption. Could you provide some suggestions on how to properly turn off USB CDC ACM during low-power operation? Thank you.

    Stanly

  • Hi Stanly,

    It supports System ON and System OFF. System ON is what you want here because it doesn’t power off the RTC. Normally you can expect and idle current of around 3 ua with the RTC running and both the appcore and netcore enabled. What are you measuring?

  • Hi,
        Around 6.2mA. I follow the instruction to reduce the power consumption

    you can see the below code.
    1. set app core freq 128mHz to 64mhz.

    2. set the i2c bus, spi and i2s to suspend mode.

    3. set the BLE tx power to -20dbm.

    4. cut the unuse ram power.

    5. set the qspi external flash to suspend mode.

    here is my code:(doing a lot of thing for reducing the power consumption)

    if(suspend){
            cpu_freq_64mhz();
           // k_timer_start(&m_sleep_timer, K_SECONDS(5), K_SECONDS(0));
            ret = pm_device_action_run(i2c0_dev, PM_DEVICE_ACTION_SUSPEND);
            LOG_INF("I2C0 bus suspend -> %d\n", ret);
            ret = pm_device_action_run(i2c1_dev, PM_DEVICE_ACTION_SUSPEND);
            LOG_INF("I2C1 bus suspend -> %d\n", ret);
            ret = pm_device_action_run(i2c2_dev, PM_DEVICE_ACTION_SUSPEND);
            LOG_INF( "I2C2 bus suspend -> %d\n", ret);
            ret = pm_device_action_run(i2c3_dev, PM_DEVICE_ACTION_SUSPEND);
            LOG_INF( "I2C3 bus suspend -> %d\n", ret);
            //ret = pm_device_action_run(i2s_dev, PM_DEVICE_ACTION_SUSPEND);
            nrf_i2s_disable(NRF_I2S0);
            ret = pinctrl_apply_state(i2s_dev->config, PINCTRL_STATE_SLEEP);
            LOG_INF( "I2S bus suspend -> %d\n", ret);
            ret = pm_device_action_run(spi4_dev, PM_DEVICE_ACTION_SUSPEND);
            LOG_INF( "SPI4 bus suspend -> %d\n", ret);

            ret = bt_hci_get_conn_handle(get_bt_conn(), &conn_handle);
            set_tx_power(BT_HCI_VS_LL_HANDLE_TYPE_CONN, conn_handle, -20);

            power_down_unused_ram();
            ret = pm_device_action_run(qspi_dev, PM_DEVICE_ACTION_SUSPEND);
            LOG_INF("qspi flash suspend -> %d\n", ret);
        }

    Stanly
Related