diff --git a/code/nrf-connect/samples/zigbee/CMakeLists.txt b/code/nrf-connect/samples/zigbee/CMakeLists.txt index 18e9b62..d5e06ae 100644 --- a/code/nrf-connect/samples/zigbee/CMakeLists.txt +++ b/code/nrf-connect/samples/zigbee/CMakeLists.txt @@ -19,6 +19,7 @@ target_sources(app PRIVATE src/prst_zb_attrs.c src/prst_zb_soil_moisture_defs.c src/restart_handler.c + src/watchdog.c ) add_subdirectory(../../prstlib prstlib) diff --git a/code/nrf-connect/samples/zigbee/prj.conf b/code/nrf-connect/samples/zigbee/prj.conf index 5583e41..9e20278 100644 --- a/code/nrf-connect/samples/zigbee/prj.conf +++ b/code/nrf-connect/samples/zigbee/prj.conf @@ -60,6 +60,10 @@ CONFIG_FLASH_PAGE_LAYOUT=y CONFIG_FILE_SYSTEM=y CONFIG_FILE_SYSTEM_LITTLEFS=y +CONFIG_WATCHDOG=y +CONFIG_HWINFO=y +CONFIG_ASSERT=y + # Uncomment for debug log level. # CONFIG_LOG_DEFAULT_LEVEL=4 diff --git a/code/nrf-connect/samples/zigbee/src/main.c b/code/nrf-connect/samples/zigbee/src/main.c index 20cbe9f..baf34dc 100644 --- a/code/nrf-connect/samples/zigbee/src/main.c +++ b/code/nrf-connect/samples/zigbee/src/main.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -22,6 +23,7 @@ #include "prst_zb_endpoint_defs.h" #include "prst_zb_soil_moisture_defs.h" #include "restart_handler.h" +#include "watchdog.h" LOG_MODULE_REGISTER(app, CONFIG_LOG_DEFAULT_LEVEL); @@ -135,6 +137,8 @@ void update_sensors_cb(zb_uint8_t arg) { zb_reset(0); } + __ASSERT(!prst_watchdog_feed(), "Failed to feed watchdog"); + prst_debug_counters_increment("sensors_read_before"); if (prst_sensors_read_all(&sensors)) { prst_debug_counters_increment("sensors_read_error"); @@ -227,9 +231,10 @@ void zboss_signal_handler(zb_bufid_t bufid) { k_timer_start(&led_flashing_timer, K_NO_WAIT, K_SECONDS(1)); // Kick off main sensor update task. - ZB_SCHEDULE_APP_ALARM(update_sensors_cb, - /*param=*/0, - ZB_MILLISECONDS_TO_BEACON_INTERVAL(1000)); + ZB_ERROR_CHECK(ZB_SCHEDULE_APP_ALARM(update_sensors_cb, + /*param=*/0, + ZB_MILLISECONDS_TO_BEACON_INTERVAL(1000))); + __ASSERT_NO_MSG(!prst_watchdog_start()); break; } case ZB_NLME_STATUS_INDICATION: { @@ -255,10 +260,40 @@ void zboss_signal_handler(zb_bufid_t bufid) { } } -void log_counter(const char *counter_name, prst_debug_counter_t value) { +void dump_counter(const char *counter_name, prst_debug_counter_t value) { LOG_INF("- %s: %d", counter_name, value); } +int log_reset_reason_counter() { + uint32_t cause; + const char *reset_counter_str = "reset_cause_unknown"; + RET_IF_ERR(hwinfo_get_reset_cause(&cause)); + RET_IF_ERR(hwinfo_clear_reset_cause()); + if (cause & RESET_PIN) { + reset_counter_str = "reset_cause_pin"; + } else if (cause & RESET_SOFTWARE) { + // Includes fatal errors from __ASSERT, ZB_ERROR_CHECK and friends. + reset_counter_str = "reset_cause_software"; + } else if (cause & RESET_BROWNOUT) { + reset_counter_str = "reset_cause_brownout"; + } else if (cause & RESET_POR) { + reset_counter_str = "reset_cause_power_on"; + } else if (cause & RESET_WATCHDOG) { + reset_counter_str = "reset_cause_watchdog"; + } else if (cause & RESET_DEBUG) { + reset_counter_str = "reset_cause_debug"; + } else if (cause & RESET_LOW_POWER_WAKE) { + reset_counter_str = "reset_cause_low_power"; + } else if (cause & RESET_CPU_LOCKUP) { + reset_counter_str = "reset_cause_cpu_lockup"; + } else if (cause & RESET_HARDWARE) { + reset_counter_str = "reset_cause_hardware"; + } else if (cause & RESET_USER) { + reset_counter_str = "reset_cause_user"; + } + return prst_debug_counters_increment(reset_counter_str); +} + int main(void) { RET_IF_ERR(prst_adc_init()); RET_IF_ERR(prst_led_init()); @@ -267,20 +302,22 @@ int main(void) { RET_IF_ERR(prst_debug_counters_init()); // Initialize sensors - quickly put them into low power mode. - RET_IF_ERR(prst_sensors_read_all(&sensors)); + __ASSERT_NO_MSG(!prst_sensors_read_all(&sensors)); prst_debug_counters_increment("boot"); - LOG_INF("Dumping debug counters:"); - prst_debug_counters_get_all(log_counter); + log_reset_reason_counter(); - RET_IF_ERR(prst_zb_factory_reset_check()); + LOG_INF("Dumping debug counters:"); + prst_debug_counters_get_all(dump_counter); + + __ASSERT_NO_MSG(!prst_zb_factory_reset_check()); prst_zb_attrs_init(&dev_ctx); ZB_AF_REGISTER_DEVICE_CTX(&app_template_ctx); - RET_IF_ERR(prst_led_flash(2)); + prst_led_flash(2); k_msleep(100); ZB_AF_SET_IDENTIFY_NOTIFICATION_HANDLER(PRST_ZIGBEE_ENDPOINT, identify_cb); diff --git a/code/nrf-connect/samples/zigbee/src/watchdog.c b/code/nrf-connect/samples/zigbee/src/watchdog.c new file mode 100644 index 0000000..c7ccecf --- /dev/null +++ b/code/nrf-connect/samples/zigbee/src/watchdog.c @@ -0,0 +1,47 @@ +#include "watchdog.h" + +#include +#include +#include +#include +#include + +#define PRST_ZB_WATCHDOG_TIMEOUT_SEC (2 * CONFIG_PRST_ZB_SLEEP_DURATION_SEC) + +LOG_MODULE_REGISTER(watchdog, CONFIG_LOG_DEFAULT_LEVEL); + +typedef struct { + const struct device *const wdt; + int wtd_channel_id; +} wtd_data_t; + +static wtd_data_t wtd_data = { + .wdt = DEVICE_DT_GET(DT_NODELABEL(wdt)), +}; + +int prst_watchdog_start() { + static const struct wdt_timeout_cfg wdt_settings = { + .window = { + .min = 0, + .max = PRST_ZB_WATCHDOG_TIMEOUT_SEC * MSEC_PER_SEC, + }, + // NULL callback means use the default, which is the system reset. + .callback = NULL, + .flags = WDT_FLAG_RESET_SOC}; + + RET_IF_ERR(!device_is_ready(wtd_data.wdt)); + + // Install timeout. + wtd_data.wtd_channel_id = wdt_install_timeout(wtd_data.wdt, &wdt_settings); + RET_CHECK(wtd_data.wtd_channel_id >= 0, "Failed to install watchdog timeout."); + + // Start watchdog. + RET_IF_ERR(wdt_setup(wtd_data.wdt, WDT_OPT_PAUSE_HALTED_BY_DBG)); + + return 0; +} + +int prst_watchdog_feed() { + RET_IF_ERR(wdt_feed(wtd_data.wdt, wtd_data.wtd_channel_id)); + return 0; +} diff --git a/code/nrf-connect/samples/zigbee/src/watchdog.h b/code/nrf-connect/samples/zigbee/src/watchdog.h new file mode 100644 index 0000000..a2fda7d --- /dev/null +++ b/code/nrf-connect/samples/zigbee/src/watchdog.h @@ -0,0 +1,8 @@ +#ifndef _PRST_ZB_WATCHDOG_H_ +#define _PRST_ZB_WATCHDOG_H_ + +int prst_watchdog_start(); + +int prst_watchdog_feed(); + +#endif // _PRST_ZB_WATCHDOG_H_ \ No newline at end of file