Hardware:
Custom board using DA14683
SDK:
1.0.14.1081 (last updated in 2018, despite what the new renesas download link says)
Situation:
The DA14683 won't go into extended sleep mode.
I issue the "pm_set_sleep_mode(pm_mode_extended_sleep);" command but the sleep state does not change. The power consumption does not change. From what I can tell it never changes the sleep state.
Questions:
1) How should I go about troubleshooting what is keeping the sleep mode from running? How can I determine what is keeping the code from going into sleep mode?
2) Can you debug the sleep mode operation?
Hi Nathan,
When issuing pm_set_sleep_mode(pm_mode_extended_sleep) the device should go into sleep mode between advertising or connection intervals.
If you could share more information about your firmware it would be very helpful to understand why you are getting increased power consumption. Which SDK project are you using?
Best regards,
PM_Renesas
In addition to my previous comment, the SDK includes hooks that holds all the user-defined functions that will be usedby the Power Manager at every wakeup/sleep cycle.
Please check : https://www.renesas.com/eu/en/document/sws/sw-example-generating-pwm-pulses-timer0?language=en&r=1600761
/* * Structure that holds all the user-defined functions that will be used * by the Power Manager at every wakeup/sleep cycle. */ const adapter_call_backs_t timer_0_callbacks = { .ad_prepare_for_sleep = ad_prepare_for_sleep_cb, .ad_wake_up_ind = ad_wake_up_ind_cb, /* * Here, you can define a callback that hits in case the system was about * to sleep but eventually the sleep process was aborted. */ .ad_sleep_canceled = NULL, /* * Here, you can define a callback that hits once XTAL16MHz crystal is settled. */ .ad_xtal16m_ready_ind = NULL, /* * Here, you can define extra clock cycles needed for the system * to stay active, before entering sleep. */ .ad_sleep_preparation_time = 0 };
(Sorry it took me a while to get back to this)
I think I found the thing that's keeping the system from sleeping when I issue pm_set_sleep_mode(pm_mode_extended_sleep);
In sys_power_mgr.c: "void pm_sleep_enter(uint32_t low_power_periods)"
#if defined CONFIG_USE_BLE || defined CONFIG_USE_FTDF uint32_t tmp = CRG_TOP->SYS_STAT_REG; #endif #ifdef CONFIG_USE_BLE if ((tmp & CRG_TOP_SYS_STAT_REG_BLE_IS_UP_Msk) == CRG_TOP_SYS_STAT_REG_BLE_IS_UP_Msk) { mac_status = true; } #endif
The problem here is that "tmp" is getting a value of 1786 from CRG_TOP->SYS_STAT_REG. That causes "mac_status" to be set to "TRUE".
Then later in that same pm_sleep_enter() function, having mac_status=true causes this conditional to fail and allow_entering_sleep remains "FALSE"
if ((pm_current_sleep_mode != pm_mode_idle) && !mac_status) { /* We plan to enter sleep */ allow_entering_sleep = true; }
This keeps the system from going to sleep since allow_entering_sleep remains FALSE!
1) What is going on here? What is CRG_TOP->SYS_STAT_REG and why is it causing that check for mac_status to fail?
2) Given this issue, what can I do here to get the system to sleep successfully?
More research:
This is defined in DA14680BB.h
/* ---------------------------- CRG_TOP_SYS_STAT_REG ---------------------------- */ #define CRG_TOP_SYS_STAT_REG_RAD_IS_DOWN_Pos (0UL) /*!< CRG_TOP SYS_STAT_REG: RAD_IS_DOWN (Bit 0) */ #define CRG_TOP_SYS_STAT_REG_RAD_IS_DOWN_Msk (0x1UL) /*!< CRG_TOP SYS_STAT_REG: RAD_IS_DOWN (Bitfield-Mask: 0x01) */ #define CRG_TOP_SYS_STAT_REG_RAD_IS_UP_Pos (1UL) /*!< CRG_TOP SYS_STAT_REG: RAD_IS_UP (Bit 1) */ #define CRG_TOP_SYS_STAT_REG_RAD_IS_UP_Msk (0x2UL) /*!< CRG_TOP SYS_STAT_REG: RAD_IS_UP (Bitfield-Mask: 0x01) */ #define CRG_TOP_SYS_STAT_REG_PER_IS_DOWN_Pos (2UL) /*!< CRG_TOP SYS_STAT_REG: PER_IS_DOWN (Bit 2) */ #define CRG_TOP_SYS_STAT_REG_PER_IS_DOWN_Msk (0x4UL) /*!< CRG_TOP SYS_STAT_REG: PER_IS_DOWN (Bitfield-Mask: 0x01) */ #define CRG_TOP_SYS_STAT_REG_PER_IS_UP_Pos (3UL) /*!< CRG_TOP SYS_STAT_REG: PER_IS_UP (Bit 3) */ #define CRG_TOP_SYS_STAT_REG_PER_IS_UP_Msk (0x8UL) /*!< CRG_TOP SYS_STAT_REG: PER_IS_UP (Bitfield-Mask: 0x01) */ #define CRG_TOP_SYS_STAT_REG_XTAL16_SW2_Pos (4UL) /*!< CRG_TOP SYS_STAT_REG: XTAL16_SW2 (Bit 4) */ #define CRG_TOP_SYS_STAT_REG_XTAL16_SW2_Msk (0x10UL) /*!< CRG_TOP SYS_STAT_REG: XTAL16_SW2 (Bitfield-Mask: 0x01) */ #define CRG_TOP_SYS_STAT_REG_DBG_IS_ACTIVE_Pos (5UL) /*!< CRG_TOP SYS_STAT_REG: DBG_IS_ACTIVE (Bit 5) */ #define CRG_TOP_SYS_STAT_REG_DBG_IS_ACTIVE_Msk (0x20UL) /*!< CRG_TOP SYS_STAT_REG: DBG_IS_ACTIVE (Bitfield-Mask: 0x01) */ #define CRG_TOP_SYS_STAT_REG_XTAL16_TRIM_READY_Pos (6UL) /*!< CRG_TOP SYS_STAT_REG: XTAL16_TRIM_READY (Bit 6) */ #define CRG_TOP_SYS_STAT_REG_XTAL16_TRIM_READY_Msk (0x40UL) /*!< CRG_TOP SYS_STAT_REG: XTAL16_TRIM_READY (Bitfield-Mask: 0x01) */ #define CRG_TOP_SYS_STAT_REG_XTAL16_SETTLE_READY_Pos (7UL) /*!< CRG_TOP SYS_STAT_REG: XTAL16_SETTLE_READY (Bit 7) */ #define CRG_TOP_SYS_STAT_REG_XTAL16_SETTLE_READY_Msk (0x80UL) /*!< CRG_TOP SYS_STAT_REG: XTAL16_SETTLE_READY (Bitfield-Mask: 0x01) */ #define CRG_TOP_SYS_STAT_REG_BLE_IS_DOWN_Pos (8UL) /*!< CRG_TOP SYS_STAT_REG: BLE_IS_DOWN (Bit 8) */ #define CRG_TOP_SYS_STAT_REG_BLE_IS_DOWN_Msk (0x100UL) /*!< CRG_TOP SYS_STAT_REG: BLE_IS_DOWN (Bitfield-Mask: 0x01) */ #define CRG_TOP_SYS_STAT_REG_BLE_IS_UP_Pos (9UL) /*!< CRG_TOP SYS_STAT_REG: BLE_IS_UP (Bit 9) */ #define CRG_TOP_SYS_STAT_REG_BLE_IS_UP_Msk (0x200UL) /*!< CRG_TOP SYS_STAT_REG: BLE_IS_UP (Bitfield-Mask: 0x01) */ #define CRG_TOP_SYS_STAT_REG_FTDF_IS_DOWN_Pos (10UL) /*!< CRG_TOP SYS_STAT_REG: FTDF_IS_DOWN (Bit 10) */ #define CRG_TOP_SYS_STAT_REG_FTDF_IS_DOWN_Msk (0x400UL) /*!< CRG_TOP SYS_STAT_REG: FTDF_IS_DOWN (Bitfield-Mask: 0x01) */ #define CRG_TOP_SYS_STAT_REG_FTDF_IS_UP_Pos (11UL) /*!< CRG_TOP SYS_STAT_REG: FTDF_IS_UP (Bit 11) */ #define CRG_TOP_SYS_STAT_REG_FTDF_IS_UP_Msk (0x800UL) /*!< CRG_TOP SYS_STAT_REG: FTDF_IS_UP (Bitfield-Mask: 0x01) */
And these are from the Datasheet: www.renesas.com/.../da14683-datasheet
bump.
I think this may be covered by your explanation here: https://community.renesas.com/wireles-connectivity/f/bluetooth-low-energy/29023/da14683-implementing-a-soft-power-button-push-to-sleep-push-again-to-wake
More testing needs to confirm.
Question:
1) Can I use the "hw_cpm_wait_rad_power_down()" function after the "ble_gap_adv_stop()" function to confirm the radio is powered down before going to sleep? Will that work?
__STATIC_INLINE void hw_cpm_wait_rad_power_down(void) { while ((CRG_TOP->SYS_STAT_REG & REG_MSK(CRG_TOP, SYS_STAT_REG, RAD_IS_DOWN)) == 0); }
When I first call: ble_gap_adv_stop()
Then Call: hw_cpm_wait_rad_power_down()
... The code hangs in the hw_cpm_wait_rad_power_down() function and never exits.
1) What is the correct way to fully power down the ble radio before going to sleep?
NOTE: This should be a simple question to answer. Either point me to the established answer in any available document or forum thread, or please answer it here. I would appreciate it if this question didn't take a long time to answer and if I didn't have to ping it back to the top of the list every couple days so it doesn't get lost. If for some reason this is a hard question, please describe why. Thanks!
In extended sleep mode, the device goes to sleep between advertising or connection intervals. It wakes up automatically via the BLE timer.
This means that during extended sleep mode, the chip can advertise and sleep between advertising intervals. Same for the connection, as it can be kept during extended sleep.
Of course, the average power consumption in t depends on the intervals: larger interval means more time in extended sleep, so less average power consumption.
If you have any peripheral blocks, such as sensors, please put them in power-down mode.
In case you would like to put the device into permanent sleep mode, all you need to do is to stop advertising by using ble_gap_adv_stop(). This can be done either via a timer (synchronously) or via an external interrupt.
In both cases, when calling the ble_gap_adv_stop(), you should get a BLE_EVT_GAP_ADV_COMPLETED message that is handled in for (;;) { } in the application task. So, the handle_evt_gap_adv_completed() callback is triggered when the advertising has been stopped. Inside handle_evt_gap_adv_completed(), put the device into the desired sleep mode.
static void handle_evt_gap_adv_completed( ble_evt_gap_adv_completed_t *evt) { pm_sleep_mode_set(pm_mode_extended_sleep); } case BLE_EVT_GAP_ADV_COMPLETED : handle_evt_gap_adv_completed((ble_evt_gap_pair_req_t *) hdr); break;
Regards,
PM_renesas