Hi @satheesh-ramasamy
This is a common gotcha especially when testing low power/deep sleep states.
The best method to get the device working again is to:
- Unplug
- Plug and hold the reset button
- Immediately execute
probe-rs erase --chip nrf9151_xxAA in a terminal (you may need to release the reset button once you run this)
- This will erase your application and prevent it from disabling power to the RP2040
The low power state does require you to disable the RP2040 so you must be careful about how its executed. (It is your programmer and USB-UART devices after all!) I typically add button handler to optionally keep the console alive when debugging:
/* Local */
atomic_t console_active = ATOMIC_INIT(0);
static struct gpio_callback button_cb_data;
int gpio_init(void)
{
/* Init work */
k_work_init_delayable(&button_press_work, button_press_cb);
k_work_init_delayable(&led_blink_work, led_blink_cb);
k_work_init_delayable(&sample_work, sample_cb);
/* Init button */
gpio_pin_configure_dt(&button, GPIO_INPUT);
/* Enable button interrupt */
gpio_pin_interrupt_configure_dt(&button, GPIO_INT_EDGE_TO_ACTIVE);
/* Set gpio callback */
gpio_init_callback(&button_cb_data, button_cb, BIT(button.pin));
/* Add gpio callback */
gpio_add_callback(button.port, &button_cb_data);
/* LED stuff */
#if DT_NODE_HAS_STATUS(DT_ALIAS(led0), okay)
gpio_pin_configure_dt(&led, GPIO_OUTPUT_INACTIVE);
#endif
return 0;
}
void button_cb(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
{
LOG_INF("Button pressed.");
k_work_schedule(&button_press_work, K_NO_WAIT);
k_work_schedule(&led_blink_work, K_NO_WAIT);
}
/* Delayable work cb */
void button_press_cb(struct k_work *work)
{
/* Check if button is still pressed */
LOG_INF("Keep console alive.");
atomic_set(&console_active, 1);
}
static int setup_pmic()
{
#if defined(CONFIG_BOARD_CIRCUITDOJO_FEATHER_NRF9151)
int err;
/* Get pmic */
static const struct device *pmic = DEVICE_DT_GET(DT_NODELABEL(npm1300_pmic));
if (!pmic)
{
LOG_ERR("Failed to get PMIC device\n");
return -ENODEV;
}
/* Disable if not already disabled */
if (regulator_is_enabled(buck2))
{
err = regulator_disable(buck2);
if (err < 0)
{
LOG_ERR("Failed to disable buck2: %d", err);
return err;
}
}
uint8_t reg = 0;
/* See if pulldown is not already enabled */
err = mfd_npm1300_reg_read(pmic, NPM1300_BUCK_BASE, NPM1300_BUCK_BUCKCTRL0,
®);
if (err < 0)
LOG_ERR("Failed to set VBUSINLIM. Err: %d", err);
if ((reg & (NPM1300_BUCK2_PULLDOWN_EN)) == 0)
{
/* Write to MFD to enable pulldown for BUCK2 */
err = mfd_npm1300_reg_write(pmic, NPM1300_BUCK_BASE, NPM1300_BUCK_BUCKCTRL0,
NPM1300_BUCK2_PULLDOWN_EN);
if (err < 0)
LOG_ERR("Failed to set VBUSINLIM. Err: %d", err);
}
#endif
return 0;
}
int setup_uart()
{
static const struct device *const console_dev =
DEVICE_DT_GET(DT_CHOSEN(zephyr_console));
/* Disable console UART */
int err = pm_device_action_run(console_dev, PM_DEVICE_ACTION_SUSPEND);
if (err < 0)
{
LOG_ERR("Unable to suspend console UART. (err: %d)", err);
return err;
}
/* Turn off to save power */
NRF_CLOCK->TASKS_HFCLKSTOP = 1;
return 0;
}
/* Inside main before the end of it or before your loop */
if (atomic_get(&console_active) == 0)
{
LOG_INF("Console inactive.");
setup_uart();
setup_pmic();
}
/* Disable gpio interrupt */
gpio_remove_callback_dt(&button, &button_cb_data);