Hi,
I'm using nRF52840 with nRF Connect SDK v2.2.0.
I need my device to go to sleep and wake up after a button press.
I followed "system_off" example.
In my main function I have this snippet:
static int disable_ds_1(const struct device *dev) { ARG_UNUSED(dev); pm_policy_state_lock_get(PM_STATE_SOFT_OFF, PM_ALL_SUBSTATES); return 0; } SYS_INIT(disable_ds_1, PRE_KERNEL_2, 0);
Then I initialize GPIO and P0.25 (button line): I set it as input and enable internal pull-up.
Then I configure port event to wake up when the button is pressed (low state):
/* Configure to generate PORT event (wakeup) on push button press */ nrf_gpio_cfg_sense_set(NRF_DT_GPIOS_TO_PSEL(DT_ALIAS(push_button), gpios), NRF_GPIO_PIN_SENSE_LOW);
Then, the application counts several minutes, and after that, it automatically shuts down using this code. This code is also executed after long button press and then release, if the user wants to shut down the device without waiting for timeout:
pm_state_force(0u, &(struct pm_state_info){PM_STATE_SOFT_OFF, 0, 0, 0}); k_sleep(K_SECONDS(2U));
This code works fine most of the time, but sometimes it won't wake up after pressing the button. The only way to recover from this state is to reset the MCU or power cycle the board.
I was looking for similar issues in DevZone, and I found this topic although it's related to a different Nordic MCU:
I don't use Bluetooth mesh, but I do use "regular" BLE functionalities.
When the system starts I enable BLE like that:
// Registering callback here... err = bt_enable(NULL); err = bt_le_adv_start(BT_LE_ADV_CONN, ad_, ARRAY_SIZE(ad_), sd_, ARRAY_SIZE(sd_)); smp_bt_register();
Following the ideas from the other ticket mentioned above, I modified the code so that the BLE is disabled before putting the system to sleep:
const int ble_disable_err = bt_disable(); if (ble_disable_err) { NVIC_SystemReset(); } pm_state_force(0u, &(struct pm_state_info){PM_STATE_SOFT_OFF, 0, 0, 0}); k_sleep(K_SECONDS(2U)); NVIC_SystemReset();
I also reset the system in case of unlikely errors when disabling BLE or going to SOFT_OFF - this is better than having the board not waking up.
This worked for me. To test it, I hooked up Arduino to the button line to simulate long press-then-release to put it to sleep and then short press to wake up.
Without disabling BLE, the board got stuck after 30-50 cycles several times. When I added the fix, I kept the test running overnight (around 3000 cycles) and the issue did not occur anymore. This made me think that the problem is fixed for good.
Can anyone explain what is the root cause and if the changes I made make sense? Or my fix only covers a real root cause that Iam not aware of?