From 77edfab66b4eea7a5c3b05195bc05478f6dcfc6e Mon Sep 17 00:00:00 2001 From: jforgue <26842354+bandogora@users.noreply.github.com> Date: Wed, 10 Apr 2024 15:39:47 -0400 Subject: [PATCH 01/10] Use internal RTC --- .vscode/tasks.json | 4 +- .../circuitdojo_feather_nrf9160_ns.conf | 1 - app/prj.conf | 3 + app/src/{external_rtc.c => app_rtc.c} | 78 ++++++++++++++----- app/src/app_rtc.h | 5 ++ app/src/external_rtc.h | 5 -- app/src/json/jsmn_parse.c | 4 +- app/src/main.c | 4 +- app/src/update_stop.c | 4 +- 9 files changed, 74 insertions(+), 34 deletions(-) rename app/src/{external_rtc.c => app_rtc.c} (65%) create mode 100644 app/src/app_rtc.h delete mode 100644 app/src/external_rtc.h diff --git a/.vscode/tasks.json b/.vscode/tasks.json index dcba760..095d0bc 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -76,7 +76,9 @@ "-r", "nrfjprog", "--erase", - "--softreset" + "--softreset", + "--nrf-family", + "NRF52" ], "options": {}, "group": { diff --git a/app/boards/circuitdojo_feather_nrf9160_ns.conf b/app/boards/circuitdojo_feather_nrf9160_ns.conf index ee04338..1f113da 100644 --- a/app/boards/circuitdojo_feather_nrf9160_ns.conf +++ b/app/boards/circuitdojo_feather_nrf9160_ns.conf @@ -40,7 +40,6 @@ CONFIG_LTE_PTW_VALUE_LTE_M="0000" # Enable External RTC CONFIG_DATE_TIME=y -CONFIG_COUNTER=y CONFIG_PCF85063A=y # Neopixels over SPI diff --git a/app/prj.conf b/app/prj.conf index 6824056..9105be3 100644 --- a/app/prj.conf +++ b/app/prj.conf @@ -27,6 +27,9 @@ CONFIG_WDT_DISABLE_AT_BOOT=n CONFIG_GPIO=y CONFIG_MULTIPLEXER=y +# Counter +CONFIG_COUNTER=y + # I2C CONFIG_I2C=y diff --git a/app/src/external_rtc.c b/app/src/app_rtc.c similarity index 65% rename from app/src/external_rtc.c rename to app/src/app_rtc.c index 8bfc24b..5837a3e 100644 --- a/app/src/external_rtc.c +++ b/app/src/app_rtc.c @@ -1,19 +1,45 @@ +<<<<<<< HEAD:app/src/external_rtc.c #include "external_rtc.h" /* Zephyr includes */ #include +======= +#include + +/* Zephyr includes */ +#include +>>>>>>> 2d2bcbb (Use internal RTC):app/src/app_rtc.c #include #include -#include #include #include #include +<<<<<<< HEAD:app/src/external_rtc.c #define SNTP_SERVER "time.nist.gov" #define SNTP_FALLBACK_SERVER "us.pool.ntp.org" +======= +#include +#include +#include +#include + +#if CONFIG_PCF85063A +/* pcf85063a driver includes */ +#include +#include + +#define RTC DEVICE_DT_GET(DT_NODELABEL(pcf85063a)) +#else + +#define RTC DEVICE_DT_GET(DT_ALIAS(rtc)) +#endif + +#define SNTP_SERVER "pool.ntp.org" +#define SNTP_FALLBACK_SERVER "time.nist.gov" +>>>>>>> 2d2bcbb (Use internal RTC):app/src/app_rtc.c #define SNTP_INIT_TIMEOUT_MS 3000 #define RETRY_COUNT 3 -#define RTC DEVICE_DT_GET(DT_NODELABEL(pcf85063a)) LOG_MODULE_REGISTER(get_rtc); @@ -21,15 +47,19 @@ K_MUTEX_DEFINE(rtc_mutex); const struct device *const rtc = RTC; -static void get_ntp_time(struct sntp_time *ts) { +static struct sntp_time ts; + +static unsigned int turnover_count = 0; + +static void get_ntp_time(void) { int err; /* Get sntp time */ for (int rc = 0; rc < (RETRY_COUNT * 2); rc++) { if (rc < RETRY_COUNT) { - err = sntp_simple(SNTP_SERVER, SNTP_INIT_TIMEOUT_MS, ts); + err = sntp_simple(SNTP_SERVER, SNTP_INIT_TIMEOUT_MS, &ts); } else { - err = sntp_simple(SNTP_FALLBACK_SERVER, SNTP_INIT_TIMEOUT_MS, ts); + err = sntp_simple(SNTP_FALLBACK_SERVER, SNTP_INIT_TIMEOUT_MS, &ts); } if (err && (rc == (RETRY_COUNT * 2) - 1)) { @@ -53,8 +83,7 @@ static void get_ntp_time(struct sntp_time *ts) { } } -int set_external_rtc_time(void) { - struct sntp_time ts; +int set_app_rtc_time(void) { int err; err = k_mutex_lock(&rtc_mutex, K_MSEC(100)); @@ -65,7 +94,7 @@ int set_external_rtc_time(void) { if (!device_is_ready(rtc)) { err = 1; - LOG_WRN("pcf85063a isn't ready!"); + LOG_WRN("RTC isn't ready!"); goto clean_up; } @@ -75,17 +104,19 @@ int set_external_rtc_time(void) { goto clean_up; } - get_ntp_time(&ts); + get_ntp_time(); /* Convert time to struct tm */ struct tm rtc_time = *gmtime(&ts.seconds); +#if CONFIG_PCF85063A /* Set rtc time */ err = pcf85063a_set_time(rtc, &rtc_time); if (err) { LOG_WRN("Failed to set RTC counter. Err: %i", err); goto clean_up; } +#endif LOG_INF( "RTC time set to: %i:%i:%i %i/%i/%i - %i", rtc_time.tm_hour, @@ -98,27 +129,32 @@ int set_external_rtc_time(void) { return err; } -// TODO calculate and offset drift -// Drifted by 1sec between [00:50:35.348,510] and [00:51:05.355,407] - -int get_external_rtc_time(void) { +int get_app_rtc_time(void) { int err = k_mutex_lock(&rtc_mutex, K_MSEC(100)); if (err) { LOG_WRN("Can't set RTC, mutex locked"); return -1; } +/* Get current time from device */ +#if CONFIG_PCF85063A struct tm rtc_time = {0}; - - /* Get current time from device */ err = pcf85063a_get_time(rtc, &rtc_time); - k_mutex_unlock(&rtc_mutex); - // int err = counter_get_value_64(rtc, &rtc_time); - if (err) { - LOG_ERR("Unable to get time from pcf85063a. Err: %i", err); - return -1; +#else + uint32_t ticks; + err = counter_get_value(rtc, &ticks); + LOG_WRN("Counter value: %d", ticks); +#endif + if (err < -1) { + LOG_ERR("Failed to get RTC value. Err: %i", err); } + k_mutex_unlock(&rtc_mutex); + +#if CONFIG_PCF85063A /* Convert to Unix timestamp */ - return mktime(&rtc_time); + return mktime(rtc_time); +#else + return (ts.seconds + (ticks / 8)); +#endif } diff --git a/app/src/app_rtc.h b/app/src/app_rtc.h new file mode 100644 index 0000000..6a2e1f5 --- /dev/null +++ b/app/src/app_rtc.h @@ -0,0 +1,5 @@ +#ifndef APP_RTC_H +#define APP_RTC_H +int set_app_rtc_time(void); +int get_app_rtc_time(void); +#endif diff --git a/app/src/external_rtc.h b/app/src/external_rtc.h deleted file mode 100644 index 352cc6e..0000000 --- a/app/src/external_rtc.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef EXTERNAL_RTC_H -#define EXTERNAL_RTC_H -int set_external_rtc_time(void); -int get_external_rtc_time(void); -#endif diff --git a/app/src/json/jsmn_parse.c b/app/src/json/jsmn_parse.c index ca9a367..5d86d8a 100644 --- a/app/src/json/jsmn_parse.c +++ b/app/src/json/jsmn_parse.c @@ -7,7 +7,7 @@ #define JSMN_HEADER -#include "external_rtc.h" +#include "app_rtc.h" #include "json/jsmn.h" #include "json/json_helpers.h" #include "stop.h" @@ -296,7 +296,7 @@ int parse_stop_json(const char *const json_ptr, Stop *stop) { return EXIT_FAILURE; } - const int time_now = get_external_rtc_time(); + const int time_now = get_app_rtc_time(); if (time_now == -1) { return EXIT_FAILURE; } diff --git a/app/src/main.c b/app/src/main.c index 03795f9..eacd46e 100644 --- a/app/src/main.c +++ b/app/src/main.c @@ -4,8 +4,8 @@ #include #include +#include "app_rtc.h" #include "display/display_switches.h" -#include "external_rtc.h" #include "net/lte_manager.h" #include "update_stop.h" #include "watchdog_app.h" @@ -172,7 +172,7 @@ int main(void) { } if (k_sem_take(<e_connected_sem, K_FOREVER) == 0) { - ret = set_external_rtc_time(); + ret = set_app_rtc_time(); if (ret) { LOG_ERR("Failed to set rtc."); goto reset; diff --git a/app/src/update_stop.c b/app/src/update_stop.c index ba7d773..065091e 100644 --- a/app/src/update_stop.c +++ b/app/src/update_stop.c @@ -3,9 +3,9 @@ #include #include +#include "app_rtc.h" #include "display/display_switches.h" #include "display/led_display.h" -#include "external_rtc.h" #include "json/jsmn_parse.h" #include "net/custom_http_client.h" #include "stop.h" @@ -18,7 +18,7 @@ K_SEM_DEFINE(stop_sem, 1, 1); static unsigned int minutes_to_departure(Departure* departure) { int edt_ms = departure->etd; - return (unsigned int)(edt_ms - get_external_rtc_time()) / 60; + return (unsigned int)(edt_ms - get_app_rtc_time()) / 60; } static DisplayBox* get_display_address( From d263bff43ad33d1d2098873372c55bccd7b2af27 Mon Sep 17 00:00:00 2001 From: jforgue <26842354+bandogora@users.noreply.github.com> Date: Tue, 5 Nov 2024 11:41:25 -0500 Subject: [PATCH 02/10] Remove pcf85063a and setup nrf rtc0 + merge fixes --- .vscode/tasks.json | 4 +-- .../circuitdojo_feather_nrf9160_ns.conf | 4 --- .../circuitdojo_feather_nrf9160_ns.overlay | 28 +++++++++++++------ app/prj.conf | 2 +- app/west.yml | 6 ---- 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 095d0bc..dcba760 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -76,9 +76,7 @@ "-r", "nrfjprog", "--erase", - "--softreset", - "--nrf-family", - "NRF52" + "--softreset" ], "options": {}, "group": { diff --git a/app/boards/circuitdojo_feather_nrf9160_ns.conf b/app/boards/circuitdojo_feather_nrf9160_ns.conf index 1f113da..838c3d8 100644 --- a/app/boards/circuitdojo_feather_nrf9160_ns.conf +++ b/app/boards/circuitdojo_feather_nrf9160_ns.conf @@ -38,10 +38,6 @@ CONFIG_LTE_PTW_VALUE_LTE_M="0000" # RAI is only supported for NBIoT currently # CONFIG_LTE_RAI_REQ=y -# Enable External RTC -CONFIG_DATE_TIME=y -CONFIG_PCF85063A=y - # Neopixels over SPI CONFIG_SPI=y CONFIG_LED_STRIP=y diff --git a/app/boards/circuitdojo_feather_nrf9160_ns.overlay b/app/boards/circuitdojo_feather_nrf9160_ns.overlay index 12dd1b2..b9fe6fa 100644 --- a/app/boards/circuitdojo_feather_nrf9160_ns.overlay +++ b/app/boards/circuitdojo_feather_nrf9160_ns.overlay @@ -35,14 +35,19 @@ pinctrl-0 = <&i2c1_default>; pinctrl-1 = <&i2c1_sleep>; pinctrl-names = "default", "sleep"; - pcf85063a: pcf85063a@51 { - compatible = "nxp,pcf85063a"; - reg = <0x51>; -}; -sen0562@23 { - compatible = "dfrobot,sen0562"; - reg = <0x23>; -}; + + pcf85063a: pcf85063a@51 { + status = "disabled"; + }; + + lis2dh: lis2dh@18 { + status = "disabled"; + }; + + sen0562@23 { + compatible = "dfrobot,sen0562"; + reg = <0x23>; + }; }; &uart0 { @@ -85,6 +90,12 @@ sen0562@23 { }; }; +&rtc0 { + status = "okay"; + // Set the frequency to 8Hz + prescaler = <4095>; +}; + &pwm0 { status = "okay"; pinctrl-0 = <&pwm0_default>; @@ -170,6 +181,7 @@ sen0562@23 { }; aliases { + rtc = &rtc0; led-strip = &led_strip; mux = &multiplexer; }; diff --git a/app/prj.conf b/app/prj.conf index 9105be3..fb73054 100644 --- a/app/prj.conf +++ b/app/prj.conf @@ -9,7 +9,7 @@ CONFIG_REBOOT=y CONFIG_PM_DEVICE=y # Compiler optimizations -# Optimize for speed since spce isn't a huge concern for this app +# Optimize for speed since space isn't a huge concern for this app CONFIG_SPEED_OPTIMIZATIONS=y # Flash operations. diff --git a/app/west.yml b/app/west.yml index dbb11d3..cbfc810 100644 --- a/app/west.yml +++ b/app/west.yml @@ -28,12 +28,6 @@ manifest: - zcbor - zephyr - # RTC Driver - - name: pcf85063a - url: https://github.com/circuitdojo/pcf85063a - revision: master - path: pcf85063a - # Multiplexer Driver - name: multiplexer url: https://github.com/justins-engineering/zephyr-multiplexer From 7a801054d2d73d442473ba0c9a8c9035986b1526 Mon Sep 17 00:00:00 2001 From: jforgue <26842354+bandogora@users.noreply.github.com> Date: Tue, 5 Nov 2024 11:42:49 -0500 Subject: [PATCH 03/10] Use NRF RTC (real time counter) for time keeping - Remove all calls to pcf85063a - Setup rtc with 24 hour top value (86400 seconds) - Setup rtc top callback and semaphore - Update stored NTP time on top value expiry (sem take in main) - Set 30 sec guard time for real time counter - Get current time once in update_stop.c and pass it to jsmn_parse.c - Removed missed merge conflicts --- app/src/app_rtc.c | 103 +++++++++++++++----------------------- app/src/app_rtc.h | 4 +- app/src/json/jsmn_parse.c | 10 ++-- app/src/json/jsmn_parse.h | 4 +- app/src/main.c | 9 ++++ app/src/update_stop.c | 19 ++++--- 6 files changed, 71 insertions(+), 78 deletions(-) diff --git a/app/src/app_rtc.c b/app/src/app_rtc.c index 5837a3e..f904330 100644 --- a/app/src/app_rtc.c +++ b/app/src/app_rtc.c @@ -1,47 +1,20 @@ -<<<<<<< HEAD:app/src/external_rtc.c -#include "external_rtc.h" +#include "app_rtc.h" -/* Zephyr includes */ -#include -======= -#include - -/* Zephyr includes */ -#include ->>>>>>> 2d2bcbb (Use internal RTC):app/src/app_rtc.c #include #include #include #include #include -<<<<<<< HEAD:app/src/external_rtc.c - -#define SNTP_SERVER "time.nist.gov" -#define SNTP_FALLBACK_SERVER "us.pool.ntp.org" -======= -#include -#include #include -#include - -#if CONFIG_PCF85063A -/* pcf85063a driver includes */ -#include -#include - -#define RTC DEVICE_DT_GET(DT_NODELABEL(pcf85063a)) -#else #define RTC DEVICE_DT_GET(DT_ALIAS(rtc)) -#endif -#define SNTP_SERVER "pool.ntp.org" -#define SNTP_FALLBACK_SERVER "time.nist.gov" ->>>>>>> 2d2bcbb (Use internal RTC):app/src/app_rtc.c +#define SNTP_SERVER "time.nist.gov" +#define SNTP_FALLBACK_SERVER "us.pool.ntp.org" #define SNTP_INIT_TIMEOUT_MS 3000 #define RETRY_COUNT 3 -LOG_MODULE_REGISTER(get_rtc); +LOG_MODULE_REGISTER(rtc, LOG_LEVEL_DBG); K_MUTEX_DEFINE(rtc_mutex); @@ -49,7 +22,7 @@ const struct device *const rtc = RTC; static struct sntp_time ts; -static unsigned int turnover_count = 0; +K_SEM_DEFINE(rtc_sync_sem, 0, 1); static void get_ntp_time(void) { int err; @@ -83,8 +56,16 @@ static void get_ntp_time(void) { } } +static void counter_top_callback( + const struct device *counter_dev, void *user_data +) { + LOG_INF("Updating RTC with NTP time"); + (void)k_sem_give(&rtc_sync_sem); +} + int set_app_rtc_time(void) { int err; + struct counter_top_cfg top_cfg; err = k_mutex_lock(&rtc_mutex, K_MSEC(100)); if (err) { @@ -98,63 +79,59 @@ int set_app_rtc_time(void) { goto clean_up; } - err = counter_start(rtc); - if (err < -1) { - LOG_WRN("Failed to start RTC. Err: %i", err); - goto clean_up; + top_cfg.flags = COUNTER_TOP_CFG_RESET_WHEN_LATE; + // 24 hours = 86400 sec + top_cfg.ticks = 86400 * counter_get_frequency(rtc); + top_cfg.callback = counter_top_callback; + top_cfg.user_data = &top_cfg; + + err = counter_set_guard_period(rtc, 240, 0); + if (err) { + LOG_ERR("Failed to set RTC guard value, ERR: %d", err); } - get_ntp_time(); + err = counter_set_top_value(rtc, &top_cfg); + if (err) { + LOG_ERR("Failed to set RTC top value, ERR: %d", err); + } - /* Convert time to struct tm */ - struct tm rtc_time = *gmtime(&ts.seconds); + (void)get_ntp_time(); + LOG_INF( + "time since Epoch: high word: %u, low word: %u", + (uint32_t)(ts.seconds >> 32), (uint32_t)ts.seconds + ); -#if CONFIG_PCF85063A - /* Set rtc time */ - err = pcf85063a_set_time(rtc, &rtc_time); + err = counter_start(rtc); if (err) { - LOG_WRN("Failed to set RTC counter. Err: %i", err); + LOG_WRN("Failed to start RTC. Err: %i", err); goto clean_up; } -#endif - LOG_INF( - "RTC time set to: %i:%i:%i %i/%i/%i - %i", rtc_time.tm_hour, - rtc_time.tm_min, rtc_time.tm_sec, rtc_time.tm_mon + 1, rtc_time.tm_mday, - 1900 + rtc_time.tm_year, rtc_time.tm_isdst - ); + // LOG_DBG("Frequency: %u", counter_get_frequency(rtc)); + // LOG_DBG("Max top Value: %u", counter_get_max_top_value(rtc)); + // LOG_DBG("Top Value: %u", counter_get_top_value(rtc)); clean_up: k_mutex_unlock(&rtc_mutex); return err; } -int get_app_rtc_time(void) { +unsigned int get_app_rtc_time(void) { int err = k_mutex_lock(&rtc_mutex, K_MSEC(100)); if (err) { - LOG_WRN("Can't set RTC, mutex locked"); + LOG_WRN("Can't read RTC, mutex locked"); return -1; } -/* Get current time from device */ -#if CONFIG_PCF85063A - struct tm rtc_time = {0}; - err = pcf85063a_get_time(rtc, &rtc_time); -#else + /* Get current time from device */ uint32_t ticks; err = counter_get_value(rtc, &ticks); LOG_WRN("Counter value: %d", ticks); -#endif if (err < -1) { LOG_ERR("Failed to get RTC value. Err: %i", err); } k_mutex_unlock(&rtc_mutex); -#if CONFIG_PCF85063A - /* Convert to Unix timestamp */ - return mktime(rtc_time); -#else - return (ts.seconds + (ticks / 8)); -#endif + return ((uint32_t)ts.seconds + (ticks / counter_get_frequency(rtc))); } diff --git a/app/src/app_rtc.h b/app/src/app_rtc.h index 6a2e1f5..ce43602 100644 --- a/app/src/app_rtc.h +++ b/app/src/app_rtc.h @@ -1,5 +1,7 @@ #ifndef APP_RTC_H #define APP_RTC_H int set_app_rtc_time(void); -int get_app_rtc_time(void); +unsigned int get_app_rtc_time(void); + +extern struct k_sem rtc_sync_sem; #endif diff --git a/app/src/json/jsmn_parse.c b/app/src/json/jsmn_parse.c index 5d86d8a..4c23afe 100644 --- a/app/src/json/jsmn_parse.c +++ b/app/src/json/jsmn_parse.c @@ -7,7 +7,6 @@ #define JSMN_HEADER -#include "app_rtc.h" #include "json/jsmn.h" #include "json/json_helpers.h" #include "stop.h" @@ -245,7 +244,9 @@ static int parse_route_directions( * * TODO: Acount for size of *optional* arrays while iterating. */ -int parse_stop_json(const char *const json_ptr, Stop *stop) { +int parse_stop_json( + const char *const json_ptr, Stop *stop, unsigned int time_now +) { jsmn_parser p; /** The number of maximum possible tokens we expect in our JSON string + 1 for @@ -296,11 +297,6 @@ int parse_stop_json(const char *const json_ptr, Stop *stop) { return EXIT_FAILURE; } - const int time_now = get_app_rtc_time(); - if (time_now == -1) { - return EXIT_FAILURE; - } - /* We want to loop over all the keys of the root object. * We know the token after a key is a value so we skip that iteration. */ diff --git a/app/src/json/jsmn_parse.h b/app/src/json/jsmn_parse.h index 1ff6e02..076eb21 100644 --- a/app/src/json/jsmn_parse.h +++ b/app/src/json/jsmn_parse.h @@ -2,5 +2,7 @@ #define JSMN_PARSE_H #include "stop.h" -int parse_stop_json(const char *const json_ptr, Stop *stop); +int parse_stop_json( + const char *const json_ptr, Stop *stop, unsigned int time_now +); #endif diff --git a/app/src/main.c b/app/src/main.c index eacd46e..3b23567 100644 --- a/app/src/main.c +++ b/app/src/main.c @@ -196,6 +196,14 @@ int main(void) { LOG_INF("update_stop_timer started"); while (1) { + if (k_sem_take(&rtc_sync_sem, K_NO_WAIT) == 0) { + ret = set_app_rtc_time(); + if (ret) { + LOG_ERR("Failed to set rtc."); + goto reset; + } + } + if (k_sem_take(&stop_sem, K_NO_WAIT) == 0) { /* A returned 2 corresponds to a successful response with no scheduled * departures. @@ -230,6 +238,7 @@ int main(void) { goto reset; } } + k_cpu_idle(); } diff --git a/app/src/update_stop.c b/app/src/update_stop.c index 065091e..ea238b4 100644 --- a/app/src/update_stop.c +++ b/app/src/update_stop.c @@ -16,9 +16,11 @@ K_TIMER_DEFINE(update_stop_timer, update_stop_timeout_handler, NULL); K_SEM_DEFINE(stop_sem, 1, 1); -static unsigned int minutes_to_departure(Departure* departure) { +static unsigned int minutes_to_departure( + Departure* departure, unsigned int time_now +) { int edt_ms = departure->etd; - return (unsigned int)(edt_ms - get_app_rtc_time()) / 60; + return (unsigned int)(edt_ms - time_now) / 60; } static DisplayBox* get_display_address( @@ -34,7 +36,9 @@ static DisplayBox* get_display_address( return NULL; } -static int parse_returned_routes(Stop stop, DisplayBox display_boxes[]) { +static int parse_returned_routes( + Stop stop, DisplayBox display_boxes[], unsigned int time_now +) { unsigned int min = 0; unsigned int times[6] = {0, 0, 0, 0, 0, 0}; @@ -54,7 +58,7 @@ static int parse_returned_routes(Stop stop, DisplayBox display_boxes[]) { for (size_t departure_num = 0; departure_num < route_direction.departures_size; departure_num++) { struct Departure departure = route_direction.departures[departure_num]; - min = minutes_to_departure(&departure); + min = minutes_to_departure(&departure, time_now); LOG_INF("Display text: %s", departure.display_text); LOG_INF("Minutes to departure: %d", min); @@ -93,6 +97,7 @@ static int parse_returned_routes(Stop stop, DisplayBox display_boxes[]) { int update_stop(void) { int ret; + unsigned int time_now; static Stop stop = {.last_updated = 0, .id = CONFIG_STOP_ID}; static const DisplayBox display_boxes[] = DISPLAY_BOXES; @@ -115,7 +120,9 @@ int update_stop(void) { return 1; } - ret = parse_stop_json(&json_buf[0], &stop); + time_now = get_app_rtc_time(); + + ret = parse_stop_json(&json_buf[0], &stop, time_now); if (ret) { LOG_DBG( "recv_body_buf size: %d, recv_body strlen: %d", @@ -146,7 +153,7 @@ int update_stop(void) { stop.routes_size, stop.last_updated ); - ret = parse_returned_routes(stop, display_boxes); + ret = parse_returned_routes(stop, display_boxes, time_now); if (ret) { return 1; } From 9abad44cf840044dde92a17b5b77a063a4d2e09d Mon Sep 17 00:00:00 2001 From: jforgue <26842354+bandogora@users.noreply.github.com> Date: Tue, 5 Nov 2024 12:04:21 -0500 Subject: [PATCH 04/10] Rename app_rtc to real_time_counter and cleanup --- app/src/app_rtc.h | 7 ------- app/src/main.c | 6 +++--- app/src/{app_rtc.c => real_time_counter.c} | 22 ++++++++++------------ app/src/real_time_counter.h | 7 +++++++ app/src/update_stop.c | 4 ++-- 5 files changed, 22 insertions(+), 24 deletions(-) delete mode 100644 app/src/app_rtc.h rename app/src/{app_rtc.c => real_time_counter.c} (85%) create mode 100644 app/src/real_time_counter.h diff --git a/app/src/app_rtc.h b/app/src/app_rtc.h deleted file mode 100644 index ce43602..0000000 --- a/app/src/app_rtc.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef APP_RTC_H -#define APP_RTC_H -int set_app_rtc_time(void); -unsigned int get_app_rtc_time(void); - -extern struct k_sem rtc_sync_sem; -#endif diff --git a/app/src/main.c b/app/src/main.c index 3b23567..db82a0b 100644 --- a/app/src/main.c +++ b/app/src/main.c @@ -4,9 +4,9 @@ #include #include -#include "app_rtc.h" #include "display/display_switches.h" #include "net/lte_manager.h" +#include "real_time_counter.h" #include "update_stop.h" #include "watchdog_app.h" @@ -172,7 +172,7 @@ int main(void) { } if (k_sem_take(<e_connected_sem, K_FOREVER) == 0) { - ret = set_app_rtc_time(); + ret = set_rtc_time(); if (ret) { LOG_ERR("Failed to set rtc."); goto reset; @@ -197,7 +197,7 @@ int main(void) { while (1) { if (k_sem_take(&rtc_sync_sem, K_NO_WAIT) == 0) { - ret = set_app_rtc_time(); + ret = set_rtc_time(); if (ret) { LOG_ERR("Failed to set rtc."); goto reset; diff --git a/app/src/app_rtc.c b/app/src/real_time_counter.c similarity index 85% rename from app/src/app_rtc.c rename to app/src/real_time_counter.c index f904330..d39bc93 100644 --- a/app/src/app_rtc.c +++ b/app/src/real_time_counter.c @@ -1,4 +1,4 @@ -#include "app_rtc.h" +#include "real_time_counter.h" #include #include @@ -14,7 +14,7 @@ #define SNTP_INIT_TIMEOUT_MS 3000 #define RETRY_COUNT 3 -LOG_MODULE_REGISTER(rtc, LOG_LEVEL_DBG); +LOG_MODULE_REGISTER(real_time_counter, LOG_LEVEL_DBG); K_MUTEX_DEFINE(rtc_mutex); @@ -63,8 +63,9 @@ static void counter_top_callback( (void)k_sem_give(&rtc_sync_sem); } -int set_app_rtc_time(void) { +int set_rtc_time(void) { int err; + uint32_t freq; struct counter_top_cfg top_cfg; err = k_mutex_lock(&rtc_mutex, K_MSEC(100)); @@ -79,13 +80,15 @@ int set_app_rtc_time(void) { goto clean_up; } + freq = counter_get_frequency(rtc); + top_cfg.flags = COUNTER_TOP_CFG_RESET_WHEN_LATE; // 24 hours = 86400 sec - top_cfg.ticks = 86400 * counter_get_frequency(rtc); + top_cfg.ticks = 86400 * freq; top_cfg.callback = counter_top_callback; top_cfg.user_data = &top_cfg; - err = counter_set_guard_period(rtc, 240, 0); + err = counter_set_guard_period(rtc, 30 * freq, 0); if (err) { LOG_ERR("Failed to set RTC guard value, ERR: %d", err); } @@ -107,26 +110,21 @@ int set_app_rtc_time(void) { goto clean_up; } - // LOG_DBG("Frequency: %u", counter_get_frequency(rtc)); - // LOG_DBG("Max top Value: %u", counter_get_max_top_value(rtc)); - // LOG_DBG("Top Value: %u", counter_get_top_value(rtc)); - clean_up: k_mutex_unlock(&rtc_mutex); return err; } -unsigned int get_app_rtc_time(void) { +unsigned int get_rtc_time(void) { int err = k_mutex_lock(&rtc_mutex, K_MSEC(100)); if (err) { LOG_WRN("Can't read RTC, mutex locked"); return -1; } - /* Get current time from device */ uint32_t ticks; + err = counter_get_value(rtc, &ticks); - LOG_WRN("Counter value: %d", ticks); if (err < -1) { LOG_ERR("Failed to get RTC value. Err: %i", err); } diff --git a/app/src/real_time_counter.h b/app/src/real_time_counter.h new file mode 100644 index 0000000..ccf5884 --- /dev/null +++ b/app/src/real_time_counter.h @@ -0,0 +1,7 @@ +#ifndef REAL_TIME_COUNTER_H +#define REAL_TIME_COUNTER_H +int set_rtc_time(void); +unsigned int get_rtc_time(void); + +extern struct k_sem rtc_sync_sem; +#endif // REAL_TIME_COUNTER_H diff --git a/app/src/update_stop.c b/app/src/update_stop.c index ea238b4..f79a77d 100644 --- a/app/src/update_stop.c +++ b/app/src/update_stop.c @@ -3,11 +3,11 @@ #include #include -#include "app_rtc.h" #include "display/display_switches.h" #include "display/led_display.h" #include "json/jsmn_parse.h" #include "net/custom_http_client.h" +#include "real_time_counter.h" #include "stop.h" LOG_MODULE_REGISTER(update_stop); @@ -120,7 +120,7 @@ int update_stop(void) { return 1; } - time_now = get_app_rtc_time(); + time_now = get_rtc_time(); ret = parse_stop_json(&json_buf[0], &stop, time_now); if (ret) { From 26b49194aa65adb7a1f1d6f5a6ea361d0932c129 Mon Sep 17 00:00:00 2001 From: jforgue <26842354+bandogora@users.noreply.github.com> Date: Fri, 6 Dec 2024 11:49:13 -0500 Subject: [PATCH 05/10] Add update stop frequency config option - Make rtc0 a wakeup source - Remove real_time_counter log level - Rename stop_sem to update_stop_sem - Remove LOG_DBG statement from timer call back --- app/Kconfig | 3 +++ app/VERSION | 4 ++-- app/app.conf | 2 ++ app/boards/circuitdojo_feather_nrf9160_ns.overlay | 1 + app/src/main.c | 7 +++++-- app/src/real_time_counter.c | 2 +- app/src/update_stop.c | 5 ++--- app/src/update_stop.h | 2 +- 8 files changed, 17 insertions(+), 9 deletions(-) diff --git a/app/Kconfig b/app/Kconfig index 904e2b1..ab01264 100644 --- a/app/Kconfig +++ b/app/Kconfig @@ -4,6 +4,9 @@ source "Kconfig.zephyr" config STOP_ID string "Bus stop ID" +config UPDATE_STOP_FREQUENCY + int "Defines the frequency of stop updates in seconds" + config STOP_REQUEST_INFOPOINT bool "Select if JSON feed is directly from InfoPoint servers" diff --git a/app/VERSION b/app/VERSION index 9830013..932f91d 100644 --- a/app/VERSION +++ b/app/VERSION @@ -1,5 +1,5 @@ VERSION_MAJOR = 0 -VERSION_MINOR = 6 -PATCHLEVEL = 1 +VERSION_MINOR = 7 +PATCHLEVEL = 0 VERSION_TWEAK = 0 EXTRAVERSION = stable diff --git a/app/app.conf b/app/app.conf index 54c7a7d..5d4cf90 100644 --- a/app/app.conf +++ b/app/app.conf @@ -1,5 +1,7 @@ CONFIG_STOP_ID="73" +CONFIG_UPDATE_STOP_FREQUENCY=30 + # Stop data request options CONFIG_STOP_REQUEST_INFOPOINT=y CONFIG_STOP_REQUEST_HOSTNAME="bustracker.pvta.com" diff --git a/app/boards/circuitdojo_feather_nrf9160_ns.overlay b/app/boards/circuitdojo_feather_nrf9160_ns.overlay index b9fe6fa..0267120 100644 --- a/app/boards/circuitdojo_feather_nrf9160_ns.overlay +++ b/app/boards/circuitdojo_feather_nrf9160_ns.overlay @@ -94,6 +94,7 @@ status = "okay"; // Set the frequency to 8Hz prescaler = <4095>; + wakeup-source; }; &pwm0 { diff --git a/app/src/main.c b/app/src/main.c index db82a0b..d08e340 100644 --- a/app/src/main.c +++ b/app/src/main.c @@ -192,7 +192,10 @@ int main(void) { // TODO: check for update or wait for update socket // (void)download_update(); - (void)k_timer_start(&update_stop_timer, K_SECONDS(30), K_SECONDS(30)); + (void)k_timer_start( + &update_stop_timer, K_SECONDS(CONFIG_UPDATE_STOP_FREQUENCY), + K_SECONDS(CONFIG_UPDATE_STOP_FREQUENCY) + ); LOG_INF("update_stop_timer started"); while (1) { @@ -204,7 +207,7 @@ int main(void) { } } - if (k_sem_take(&stop_sem, K_NO_WAIT) == 0) { + if (k_sem_take(&update_stop_sem, K_NO_WAIT) == 0) { /* A returned 2 corresponds to a successful response with no scheduled * departures. */ diff --git a/app/src/real_time_counter.c b/app/src/real_time_counter.c index d39bc93..06c81d4 100644 --- a/app/src/real_time_counter.c +++ b/app/src/real_time_counter.c @@ -14,7 +14,7 @@ #define SNTP_INIT_TIMEOUT_MS 3000 #define RETRY_COUNT 3 -LOG_MODULE_REGISTER(real_time_counter, LOG_LEVEL_DBG); +LOG_MODULE_REGISTER(real_time_counter); K_MUTEX_DEFINE(rtc_mutex); diff --git a/app/src/update_stop.c b/app/src/update_stop.c index f79a77d..3fe60a5 100644 --- a/app/src/update_stop.c +++ b/app/src/update_stop.c @@ -14,7 +14,7 @@ LOG_MODULE_REGISTER(update_stop); K_TIMER_DEFINE(update_stop_timer, update_stop_timeout_handler, NULL); -K_SEM_DEFINE(stop_sem, 1, 1); +K_SEM_DEFINE(update_stop_sem, 1, 1); static unsigned int minutes_to_departure( Departure* departure, unsigned int time_now @@ -162,6 +162,5 @@ int update_stop(void) { } void update_stop_timeout_handler(struct k_timer* timer_id) { - LOG_DBG("Update stop timeout\n"); - (void)k_sem_give(&stop_sem); + (void)k_sem_give(&update_stop_sem); } diff --git a/app/src/update_stop.h b/app/src/update_stop.h index b24cfa4..faabefd 100644 --- a/app/src/update_stop.h +++ b/app/src/update_stop.h @@ -31,6 +31,6 @@ void update_stop_timeout_handler(struct k_timer* timer_id); int update_stop(void); extern struct k_timer update_stop_timer; -extern struct k_sem stop_sem; +extern struct k_sem update_stop_sem; #endif From 812d641a73b051740c666ffaf635177eea6a51e7 Mon Sep 17 00:00:00 2001 From: jforgue <26842354+bandogora@users.noreply.github.com> Date: Mon, 9 Dec 2024 12:09:43 -0500 Subject: [PATCH 06/10] Cleanup/simplify prj.conf & http_client comments - Regenerated pm_static.yml --- app/pm_static.yml | 2 +- app/prj.conf | 22 ++++++++++------------ app/src/net/custom_http_client.c | 16 ++++++++-------- 3 files changed, 19 insertions(+), 21 deletions(-) diff --git a/app/pm_static.yml b/app/pm_static.yml index bd39201..3cafcaa 100644 --- a/app/pm_static.yml +++ b/app/pm_static.yml @@ -39,8 +39,8 @@ mcuboot_primary: end_address: 0xf2000 orig_span: &id001 - tfm - - app - mcuboot_pad + - app region: flash_primary size: 0xd2000 span: *id001 diff --git a/app/prj.conf b/app/prj.conf index fb73054..a9f2578 100644 --- a/app/prj.conf +++ b/app/prj.conf @@ -87,26 +87,24 @@ CONFIG_FAULT_DUMP=0 # Logging CONFIG_LOG=y +CONFIG_LOG_MODE_DEFERRED=y +# 1 = Error, 2 = Warn, 3 = Info, 4 = Debug CONFIG_LOG_DEFAULT_LEVEL=2 -# CONFIG_LOG_MAX_LEVEL=2 -# CONFIG_LOG_INFO_COLOR_GREEN=y -# CONFIG_LOG_BACKEND_SHOW_COLOR=n +# The default stack size of 1024 seems okay for log level 1 and 2, but not 3 and 4. +# We have enough unused RAM and I'd rather avoid any potential logging stack overflows either way. +CONFIG_LOG_PROCESS_THREAD_STACK_SIZE=2048 # Log UART -# CONFIG_LOG_MODE_MINIMAL=y -# CONFIG_LOG_MODE_DEFERRED=y -# CONFIG_LOG_MODE_OVERFLOW=y -# CONFIG_LOG_BUFFER_SIZE=2048 -# CONFIG_LOG_PROCESS_THREAD_STACK_SIZE=2048 +# We can't use MCUMGR over serial when serial logging is enabled, so we use RTT in production. +# Uncomment this option and comment out the Log RTT options if you want to use the USB serial logging testing. +# CONFIG_LOG_BACKEND_UART=y -# Log RTT +# # Log RTT +CONFIG_LOG_BACKEND_UART=n CONFIG_LOG_MODE_MINIMAL=n -CONFIG_RTT_CONSOLE=y CONFIG_USE_SEGGER_RTT=y CONFIG_LOG_BACKEND_RTT=y -CONFIG_LOG_BACKEND_UART=n CONFIG_SEGGER_RTT_MODE_NO_BLOCK_TRIM=y -# CONFIG_SEGGER_RTT_BUFFER_SIZE_UP=4096 # Network Logging # CONFIG_NET_LOG=y diff --git a/app/src/net/custom_http_client.c b/app/src/net/custom_http_client.c index 04eebb7..13e0b5a 100644 --- a/app/src/net/custom_http_client.c +++ b/app/src/net/custom_http_client.c @@ -116,7 +116,7 @@ static int parse_headers(int *sock, char *headers_buf, int headers_buf_size) { state++; } else if (state == 3) { headers_size = headers_offset; - LOG_INF("Received Headers. Size: %d bytes", headers_offset); + LOG_DBG("Received Headers. Size: %d bytes", headers_offset); headers_buf[headers_offset + 1] = '\0'; @@ -194,7 +194,7 @@ static long parse_response( offset += bytes; } while (bytes != 0); - LOG_INF("Received Body. Size: %ld bytes", offset); + LOG_DBG("Received Body. Size: %ld bytes", offset); LOG_INF("Total bytes received: %ld", offset + headers_size); if (write_nvs) { @@ -324,7 +324,7 @@ static int send_http_request( return errno; } - LOG_INF("Resolved %s (%s)", peer_addr, net_family2str(addr_inf->ai_family)); + LOG_DBG("Resolved %s (%s)", peer_addr, net_family2str(addr_inf->ai_family)); if (sec_tag == NO_SEC_TAG) { sock = socket(addr_inf->ai_family, SOCK_STREAM, addr_inf->ai_protocol); @@ -360,10 +360,10 @@ static int send_http_request( } LOG_DBG( - "addrinfo @%p: ai_family=%d, ai_socktype=%d, ai_protocol=%d, " - "sa_family=%d, sin_port=%x\n", - addr_inf, addr_inf->ai_family, addr_inf->ai_socktype, - addr_inf->ai_protocol, addr_inf->ai_addr->sa_family, + "Socket %d addrinfo: ai_family=%d, ai_socktype=%d, ai_protocol=%d, " + "sa_family=%d, sin_port=%x", + sock, addr_inf->ai_family, addr_inf->ai_socktype, addr_inf->ai_protocol, + addr_inf->ai_addr->sa_family, ((struct sockaddr_in *)addr_inf->ai_addr)->sin_port ); @@ -388,7 +388,7 @@ static int send_http_request( } clean_up: - LOG_INF("Closing socket %d", sock); + LOG_DBG("Closing socket %d", sock); err = close(sock); if (err) { LOG_ERR("close() failed, %s", strerror(errno)); From fe2a3afb6560c44c43f679b7e164139d89c5c72e Mon Sep 17 00:00:00 2001 From: jforgue <26842354+bandogora@users.noreply.github.com> Date: Mon, 9 Dec 2024 13:27:15 -0500 Subject: [PATCH 07/10] Move sign specific config options to sign.conf - Renamed app.conf to sign.conf - Converted many configurable #defines to Kconfig options for easier sign tuning - Set clang-format ColumnLimit back to 100 (from 90) --- app/.clang-format | 2 +- app/CMakeLists.txt | 2 +- app/Kconfig | 25 +++++++++++++++++++++++-- app/VERSION | 2 +- app/{app.conf => sign.conf} | 22 +++++++++++++++++----- app/src/display/led_display.c | 12 ++++++------ app/src/json/jsmn_parse.c | 4 ++-- app/src/main.c | 6 +++--- app/src/real_time_counter.c | 24 +++++++++--------------- app/src/stop.h | 19 ++----------------- app/src/update_stop.c | 4 ++-- app/src/update_stop.h | 5 +---- 12 files changed, 68 insertions(+), 59 deletions(-) rename app/{app.conf => sign.conf} (53%) diff --git a/app/.clang-format b/app/.clang-format index e6c968b..ace65e0 100644 --- a/app/.clang-format +++ b/app/.clang-format @@ -3,5 +3,5 @@ Language: Cpp BasedOnStyle: Google AlignAfterOpenBracket: BlockIndent -# ColumnLimit: 100 +ColumnLimit: 100 ... diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 33bfffd..305bc15 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -5,7 +5,7 @@ if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/keys/private/boot-ecdsa-p256.pem") SET(mcuboot_CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256 "y") endif() -set(EXTRA_CONF_FILE ${CMAKE_CURRENT_SOURCE_DIR}/app.conf) +set(EXTRA_CONF_FILE ${CMAKE_CURRENT_SOURCE_DIR}/sign.conf) find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(embedded-departure-board) diff --git a/app/Kconfig b/app/Kconfig index ab01264..9d06fdf 100644 --- a/app/Kconfig +++ b/app/Kconfig @@ -4,8 +4,17 @@ source "Kconfig.zephyr" config STOP_ID string "Bus stop ID" -config UPDATE_STOP_FREQUENCY - int "Defines the frequency of stop updates in seconds" +config STOP_MAX_ROUTES + int "Maximum number of routes expected at the configured stop" + +config ROUTE_MAX_DEPARTURES + int "Maximum number of departures expected for EACH route" + +config UPDATE_STOP_FREQUENCY_SECONDS + int "The frequency at which stop departure times are updated in seconds" + +config NUMBER_OF_DISPLAY_BOXES + int "The number of display boxes connected to the sign" config STOP_REQUEST_INFOPOINT bool "Select if JSON feed is directly from InfoPoint servers" @@ -19,6 +28,18 @@ config STOP_REQUEST_PATH config STOP_JSON_BUF_SIZE int "Defines the max size for stop JSON response body receive buffer" +config PRIMARY_NTP_SERVER + string "Primary NTP server used to synchronize system time" + +config FALLBACK_NTP_SERVER + string "Fallback NTP server used to synchronize system time if the primary server is unavailable" + +config NTP_REQUEST_TIMEOUT_MS + int "Max amount of time allowed waiting for a single NTP query response for in milliseconds" + +config NTP_FETCH_RETRY_COUNT + int "Max attempts to fetch time from NTP server before changing to fallback server" + config OTA_HOSTNAME string "HTTP hostname used to download firmware upgade file" diff --git a/app/VERSION b/app/VERSION index 932f91d..5a0a35c 100644 --- a/app/VERSION +++ b/app/VERSION @@ -1,5 +1,5 @@ VERSION_MAJOR = 0 VERSION_MINOR = 7 -PATCHLEVEL = 0 +PATCHLEVEL = 1 VERSION_TWEAK = 0 EXTRAVERSION = stable diff --git a/app/app.conf b/app/sign.conf similarity index 53% rename from app/app.conf rename to app/sign.conf index 5d4cf90..34939f5 100644 --- a/app/app.conf +++ b/app/sign.conf @@ -1,12 +1,17 @@ +# Stop settings CONFIG_STOP_ID="73" +CONFIG_STOP_MAX_ROUTES=6 +CONFIG_ROUTE_MAX_DEPARTURES=4 +CONFIG_UPDATE_STOP_FREQUENCY_SECONDS=30 -CONFIG_UPDATE_STOP_FREQUENCY=30 +# Display settings +CONFIG_NUMBER_OF_DISPLAY_BOXES=5 +# Adjust DISPLAY_BOXES display settings in app/src/update_stop.h -# Stop data request options +# Stop data request settings CONFIG_STOP_REQUEST_INFOPOINT=y CONFIG_STOP_REQUEST_HOSTNAME="bustracker.pvta.com" # CONFIG_STOP_REQUEST_HOSTNAME="pvta.jes.contact" - CONFIG_STOP_REQUEST_PATH="/InfoPoint/rest/SignageStopDepartures/GetSignageDeparturesByStopId?stopId=73" # CONFIG_STOP_REQUEST_PATH="/stop/73" @@ -15,12 +20,19 @@ CONFIG_STOP_REQUEST_PATH="/InfoPoint/rest/SignageStopDepartures/GetSignageDepart # are currently running for a given stop. CONFIG_STOP_JSON_BUF_SIZE=10240 -# OTA DFU options +# NTP settings +CONFIG_PRIMARY_NTP_SERVER="time.nist.gov" +CONFIG_FALLBACK_NTP_SERVER="us.pool.ntp.org" +# The NIST time servers should never be queried more frequently than once every 4 seconds. +CONFIG_NTP_REQUEST_TIMEOUT_MS=4010 +CONFIG_NTP_FETCH_RETRY_COUNT=2 + +# OTA DFU settings CONFIG_OTA_HOSTNAME="pvta.jes.contact" CONFIG_OTA_PATH="/firmware" # Set to 'y' to enable I2C ambient light sensor CONFIG_LIGHT_SENSOR=y -# Set to 'y' to run visiual display tests +# Set to 'y' to run visual display tests CONFIG_LED_DISPLAY_TEST=n diff --git a/app/src/display/led_display.c b/app/src/display/led_display.c index c8960e9..cd1218d 100644 --- a/app/src/display/led_display.c +++ b/app/src/display/led_display.c @@ -152,7 +152,7 @@ int led_test_patern(void) { memcpy(&pixels[test], &pixel, sizeof(struct led_rgb)); memcpy(&pixels[63 + test], &pixel, sizeof(struct led_rgb)); - for (size_t i = 0; i < NUMBER_OF_DISPLAY_BOXES; i++) { + for (size_t i = 0; i < CONFIG_NUMBER_OF_DISPLAY_BOXES; i++) { mux_set_active_port(mux, i); if (led_strip_update_rgb(strip, pixels, STRIP_NUM_PIXELS) != 0) { LOG_ERR("Failed to update LED strip, test: %d", 0); @@ -168,7 +168,7 @@ int led_test_patern(void) { LOG_INF("Running number display test."); static const DisplayBox display_boxes[] = DISPLAY_BOXES; for (size_t test = 0; test < 10; test++) { - for (size_t i = 0; i < NUMBER_OF_DISPLAY_BOXES; i++) { + for (size_t i = 0; i < CONFIG_NUMBER_OF_DISPLAY_BOXES; i++) { if (write_num_to_display( &display_boxes[i], display_boxes[i].brightness, test * 111 )) { @@ -180,7 +180,7 @@ int led_test_patern(void) { LOG_INF("Number display test done. Setting enable pin low on all displays."); - for (size_t i = 0; i < NUMBER_OF_DISPLAY_BOXES; i++) { + for (size_t i = 0; i < CONFIG_NUMBER_OF_DISPLAY_BOXES; i++) { if (display_off(i)) { return -1; } @@ -204,7 +204,7 @@ int max_power_test(void) { return -1; } - for (size_t box = 0; box < NUMBER_OF_DISPLAY_BOXES; box++) { + for (size_t box = 0; box < CONFIG_NUMBER_OF_DISPLAY_BOXES; box++) { if (display_off(box)) { return -1; } @@ -212,7 +212,7 @@ int max_power_test(void) { LOG_INF("Running individual box power display test."); - for (size_t i = 0; i < NUMBER_OF_DISPLAY_BOXES; i++) { + for (size_t i = 0; i < CONFIG_NUMBER_OF_DISPLAY_BOXES; i++) { if (i != 0) { if (display_off(i - 1)) { return -1; @@ -227,7 +227,7 @@ int max_power_test(void) { } LOG_INF("Running max power display test."); - for (size_t j = 0; j < NUMBER_OF_DISPLAY_BOXES; j++) { + for (size_t j = 0; j < CONFIG_NUMBER_OF_DISPLAY_BOXES; j++) { if (write_num_to_display( &display_boxes[j], display_boxes[j].brightness, 888 )) { diff --git a/app/src/json/jsmn_parse.c b/app/src/json/jsmn_parse.c index 4c23afe..143f195 100644 --- a/app/src/json/jsmn_parse.c +++ b/app/src/json/jsmn_parse.c @@ -17,8 +17,8 @@ LOG_MODULE_REGISTER(jsmn_parse); #define DEPARTURE_TOK_COUNT 18 #define HEADWAY_TOK_COUNT 14 #define ROUTE_DIRECTION_TOK_COUNT \ - (12 + (MAX_DEPARTURES * (DEPARTURE_TOK_COUNT + HEADWAY_TOK_COUNT))) -#define STOP_TOK_COUNT (6 + (MAX_ROUTES * ROUTE_DIRECTION_TOK_COUNT)) + (12 + (CONFIG_ROUTE_MAX_DEPARTURES * (DEPARTURE_TOK_COUNT + HEADWAY_TOK_COUNT))) +#define STOP_TOK_COUNT (6 + (CONFIG_STOP_MAX_ROUTES * ROUTE_DIRECTION_TOK_COUNT)) /** With jsmn JSON objects count as a token, so we need to offset by an * additional 1 for each level deeper we go. diff --git a/app/src/main.c b/app/src/main.c index d08e340..60d5896 100644 --- a/app/src/main.c +++ b/app/src/main.c @@ -129,7 +129,7 @@ int main(void) { } // Set all displays off because the LEDs have memory - for (size_t box = 0; box < NUMBER_OF_DISPLAY_BOXES; box++) { + for (size_t box = 0; box < CONFIG_NUMBER_OF_DISPLAY_BOXES; box++) { ret = display_off(box); if (ret < 0) { LOG_ERR("Failed to set display switch %d off.", box); @@ -193,8 +193,8 @@ int main(void) { // (void)download_update(); (void)k_timer_start( - &update_stop_timer, K_SECONDS(CONFIG_UPDATE_STOP_FREQUENCY), - K_SECONDS(CONFIG_UPDATE_STOP_FREQUENCY) + &update_stop_timer, K_SECONDS(CONFIG_UPDATE_STOP_FREQUENCY_SECONDS), + K_SECONDS(CONFIG_UPDATE_STOP_FREQUENCY_SECONDS) ); LOG_INF("update_stop_timer started"); diff --git a/app/src/real_time_counter.c b/app/src/real_time_counter.c index 06c81d4..501e24b 100644 --- a/app/src/real_time_counter.c +++ b/app/src/real_time_counter.c @@ -9,11 +9,6 @@ #define RTC DEVICE_DT_GET(DT_ALIAS(rtc)) -#define SNTP_SERVER "time.nist.gov" -#define SNTP_FALLBACK_SERVER "us.pool.ntp.org" -#define SNTP_INIT_TIMEOUT_MS 3000 -#define RETRY_COUNT 3 - LOG_MODULE_REGISTER(real_time_counter); K_MUTEX_DEFINE(rtc_mutex); @@ -28,28 +23,27 @@ static void get_ntp_time(void) { int err; /* Get sntp time */ - for (int rc = 0; rc < (RETRY_COUNT * 2); rc++) { - if (rc < RETRY_COUNT) { - err = sntp_simple(SNTP_SERVER, SNTP_INIT_TIMEOUT_MS, &ts); + for (int rc = 0; rc < (CONFIG_NTP_FETCH_RETRY_COUNT * 2); rc++) { + if (rc < CONFIG_NTP_FETCH_RETRY_COUNT) { + err = sntp_simple(CONFIG_PRIMARY_NTP_SERVER, CONFIG_NTP_REQUEST_TIMEOUT_MS, &ts); } else { - err = sntp_simple(SNTP_FALLBACK_SERVER, SNTP_INIT_TIMEOUT_MS, &ts); + err = sntp_simple(CONFIG_FALLBACK_NTP_SERVER, CONFIG_NTP_REQUEST_TIMEOUT_MS, &ts); } - if (err && (rc == (RETRY_COUNT * 2) - 1)) { + if (err && (rc == (CONFIG_NTP_FETCH_RETRY_COUNT * 2) - 1)) { LOG_ERR( "Failed to get time from all NTP pools! Err: %i\n Check your network " "connection.", err ); - } else if (err && (rc == RETRY_COUNT - 1)) { + } else if (err && (rc == CONFIG_NTP_FETCH_RETRY_COUNT - 1)) { LOG_WRN( - "Unable to get time after 3 tries from NTP pool " SNTP_SERVER - " . Err: %i\n Attempting to use fallback NTP pool...", - err + "Unable to get time after %d tries from NTP " + "pool " CONFIG_PRIMARY_NTP_SERVER " . Err: %i\n Attempting to use fallback NTP pool...", + CONFIG_NTP_FETCH_RETRY_COUNT, err ); } else if (err) { LOG_WRN("Failed to get time using SNTP, Err: %i. Retrying...", err); - k_msleep(100); } else { break; } diff --git a/app/src/stop.h b/app/src/stop.h index 8c5ef36..0c844de 100644 --- a/app/src/stop.h +++ b/app/src/stop.h @@ -1,21 +1,6 @@ #ifndef STOP_H #define STOP_H -/** @def MAX_ROUTES - * @brief A macro that defines the maximum number of routes expected for a stop. - * - * Specify the maximum number of routes you expect your selected stop to have. - */ -#define MAX_ROUTES 6 - -/** @def MAX_DEPARTURES - * @brief A macro that defines the maximum number of departures expected for a route. - * - * Specify the maximum number of departures you expect each route to have. - * Applies to **ALL** departures. - */ -#define MAX_DEPARTURES 4 - typedef struct Departure { char display_text[50]; unsigned int etd; @@ -25,13 +10,13 @@ typedef struct RouteDirection { char direction_code; int id; unsigned int departures_size; - Departure departures[MAX_DEPARTURES]; + Departure departures[CONFIG_ROUTE_MAX_DEPARTURES]; } RouteDirection; typedef struct Stop { unsigned long long last_updated; const char *id; unsigned int routes_size; - RouteDirection route_directions[MAX_ROUTES]; + RouteDirection route_directions[CONFIG_STOP_MAX_ROUTES]; } Stop; #endif diff --git a/app/src/update_stop.c b/app/src/update_stop.c index 3fe60a5..1259f5c 100644 --- a/app/src/update_stop.c +++ b/app/src/update_stop.c @@ -27,7 +27,7 @@ static DisplayBox* get_display_address( const DisplayBox display_boxes[], const int route_id, const char direction_code ) { - for (size_t box = 0; box < NUMBER_OF_DISPLAY_BOXES; box++) { + for (size_t box = 0; box < CONFIG_NUMBER_OF_DISPLAY_BOXES; box++) { if ((route_id == display_boxes[box].id) && (display_boxes[box].direction_code == direction_code)) { return &display_boxes[box]; @@ -43,7 +43,7 @@ static int parse_returned_routes( unsigned int times[6] = {0, 0, 0, 0, 0, 0}; - for (size_t box = 0; box < NUMBER_OF_DISPLAY_BOXES; box++) { + for (size_t box = 0; box < CONFIG_NUMBER_OF_DISPLAY_BOXES; box++) { (void)display_off(box); } diff --git a/app/src/update_stop.h b/app/src/update_stop.h index faabefd..7bcf46a 100644 --- a/app/src/update_stop.h +++ b/app/src/update_stop.h @@ -3,10 +3,7 @@ #include -/** Specify the number of display boxes connected*/ -#define NUMBER_OF_DISPLAY_BOXES 5 - -/** Specify the route, display text, and position for each display box */ +/** Specify the route, position, direction, color, and brightness for each display box */ // clang-format off #define DISPLAY_BOXES { \ { .id = 30038, .position = 0, .direction_code = 'S', .color = 0x660066, .brightness = 0xFF }, \ From a69ac338df09b5a0c44e7e45c6a998c97934a2aa Mon Sep 17 00:00:00 2001 From: jforgue <26842354+bandogora@users.noreply.github.com> Date: Mon, 9 Dec 2024 13:56:42 -0500 Subject: [PATCH 08/10] Refactor watchdog_app.c & add max timeout Kconfig --- app/Kconfig | 3 +++ app/sign.conf | 4 ++++ app/src/watchdog_app.c | 37 +++++++------------------------------ 3 files changed, 14 insertions(+), 30 deletions(-) diff --git a/app/Kconfig b/app/Kconfig index 9d06fdf..dd2a31d 100644 --- a/app/Kconfig +++ b/app/Kconfig @@ -16,6 +16,9 @@ config UPDATE_STOP_FREQUENCY_SECONDS config NUMBER_OF_DISPLAY_BOXES int "The number of display boxes connected to the sign" +config MAX_TIME_INACTIVE_BEFORE_RESET_MS + int "Maximum amount of time the system can remain inactive before it resets in milliseconds" + config STOP_REQUEST_INFOPOINT bool "Select if JSON feed is directly from InfoPoint servers" diff --git a/app/sign.conf b/app/sign.conf index 34939f5..388f22d 100644 --- a/app/sign.conf +++ b/app/sign.conf @@ -8,6 +8,10 @@ CONFIG_UPDATE_STOP_FREQUENCY_SECONDS=30 CONFIG_NUMBER_OF_DISPLAY_BOXES=5 # Adjust DISPLAY_BOXES display settings in app/src/update_stop.h +# Maximum amount of time the system can remain inactive before it resets. +# Must be larger than CONFIG_UPDATE_STOP_FREQUENCY_SECONDS +CONFIG_MAX_TIME_INACTIVE_BEFORE_RESET_MS=60000 + # Stop data request settings CONFIG_STOP_REQUEST_INFOPOINT=y CONFIG_STOP_REQUEST_HOSTNAME="bustracker.pvta.com" diff --git a/app/src/watchdog_app.c b/app/src/watchdog_app.c index 2999c4c..a771608 100644 --- a/app/src/watchdog_app.c +++ b/app/src/watchdog_app.c @@ -5,35 +5,12 @@ LOG_MODULE_REGISTER(watchdog); -#define WDT DEVICE_DT_GET(DT_NODELABEL(wdt0)) -/* Nordic supports a callback, but it has 61.2 us to complete before - * the reset occurs, which is too short for this sample to do anything - * useful. Explicitly disallow use of the callback. - */ -#if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_wdt) -#define WDT_ALLOW_CALLBACK 0 -#else -#define WDT_ALLOW_CALLBACK 1 -#endif -#define WDT_MAX_WINDOW 60000U -#define WDT_MIN_WINDOW 0U -#define WDT_OPT WDT_OPT_PAUSE_HALTED_BY_DBG - -#define WDT0_NODE DT_NODELABEL(wdt0) - -#ifndef WDT_MAX_WINDOW -#define WDT_MAX_WINDOW 2000U -#endif - -#ifndef WDT_MIN_WINDOW -#define WDT_MIN_WINDOW 0U -#endif - -#if DT_NODE_HAS_STATUS(WDT0_NODE, okay) -const struct device *const wdt = DEVICE_DT_GET(WDT0_NODE); +#define WDT0 DT_NODELABEL(wdt0) +#if DT_NODE_HAS_STATUS(WDT0, okay) +const struct device *const wdt = DEVICE_DT_GET(WDT0); #else -#error "Node is disabled" +#error "wdt0 node is disabled" #endif int wdt_channel_id; @@ -47,12 +24,12 @@ int watchdog_init(void) { } struct wdt_timeout_cfg wdt_config = { - /* Reset SoC when watchdog timer expires. */ + /* Reset SoC when watchdog timer expires */ .flags = WDT_FLAG_RESET_SOC, /* Expire watchdog after max window */ - .window.min = WDT_MIN_WINDOW, - .window.max = WDT_MAX_WINDOW, + .window.min = 0U, + .window.max = (uint32_t)CONFIG_MAX_TIME_INACTIVE_BEFORE_RESET_MS, .callback = NULL, }; From 4326bca37398991b7a754491bee909d03198c2ab Mon Sep 17 00:00:00 2001 From: jforgue <26842354+bandogora@users.noreply.github.com> Date: Mon, 9 Dec 2024 16:51:06 -0500 Subject: [PATCH 09/10] Don't reset if light sensor is unreachable We don't want the who system to fail if the light sensor does, just turn the PWM lights off --- .../circuitdojo_feather_nrf9160_ns.overlay | 1 + app/src/light_sensor.c | 19 ++++++++++--------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/app/boards/circuitdojo_feather_nrf9160_ns.overlay b/app/boards/circuitdojo_feather_nrf9160_ns.overlay index 0267120..220c15c 100644 --- a/app/boards/circuitdojo_feather_nrf9160_ns.overlay +++ b/app/boards/circuitdojo_feather_nrf9160_ns.overlay @@ -45,6 +45,7 @@ }; sen0562@23 { + status = "okay"; compatible = "dfrobot,sen0562"; reg = <0x23>; }; diff --git a/app/src/light_sensor.c b/app/src/light_sensor.c index c1954d4..091372e 100644 --- a/app/src/light_sensor.c +++ b/app/src/light_sensor.c @@ -7,24 +7,25 @@ LOG_MODULE_REGISTER(light_sensor); +#define I2C1 DT_NODELABEL(i2c1) + +#if DT_NODE_HAS_STATUS(I2C1, okay) +const struct device *const i2c_dev = DEVICE_DT_GET(I2C1); +#else +#error "i2c1 node is disabled" +#endif + #define SEN_ADDR 0x23 #define SEN_REG_LUX 0x10 -const struct device *i2c_dev = DEVICE_DT_GET(DT_NODELABEL(i2c1)); - int get_lux(void) { uint8_t lux[2] = {0, 0}; int ret; - if (i2c_dev == NULL || !device_is_ready(i2c_dev)) { - LOG_ERR("Could not get I2C device"); - return -1; - } - ret = i2c_burst_read(i2c_dev, SEN_ADDR, SEN_REG_LUX, &lux[0], 2); if (ret) { - LOG_ERR("Unable get lux data. (err %i)\n", ret); - return -1; + LOG_WRN("Unable get lux data. Keeping PWM lights off. (err %i)", ret); + return 0xFF; } ret = ((uint16_t)lux[0] << 8) | (uint16_t)lux[1]; From 61f045c2b3df8fd24b88204e029aaa7f67338aa3 Mon Sep 17 00:00:00 2001 From: jforgue <26842354+bandogora@users.noreply.github.com> Date: Wed, 11 Dec 2024 11:50:58 -0500 Subject: [PATCH 10/10] Clean up mcuboot child image config - Remove unused UART options - Changed RTT mode to trim no block - Set log level to warn - Turned off debugging - Removed mcumgr echo for testing --- app/child_image/mcuboot.conf | 34 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/app/child_image/mcuboot.conf b/app/child_image/mcuboot.conf index 166e9b2..45c1af7 100644 --- a/app/child_image/mcuboot.conf +++ b/app/child_image/mcuboot.conf @@ -1,9 +1,6 @@ # Core should be on a clean state when TF-M starts CONFIG_MCUBOOT_CLEANUP_ARM_CORE=y -# Enable echo command -CONFIG_BOOT_MGMT_ECHO=y - # Increase MCUboot image sectors and set static partition size CONFIG_BOOT_MAX_IMG_SECTORS=256 CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x20000 @@ -32,27 +29,22 @@ CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY=y CONFIG_PM_OVERRIDE_EXTERNAL_DRIVER_CHECK=y -# Logging RTT +# Console CONFIG_CONSOLE=y -CONFIG_UART_CONSOLE=n + +# Logging CONFIG_LOG=y -CONFIG_LOG_DEFAULT_LEVEL=3 CONFIG_LOG_MODE_MINIMAL=n -CONFIG_LOG_MODE_IMMEDIATE=y -CONFIG_RTT_CONSOLE=y +CONFIG_LOG_DEFAULT_LEVEL=2 + +# RTT +# We use serial for MCUmgr so no UART CONFIG_USE_SEGGER_RTT=y +CONFIG_UART_CONSOLE=n +CONFIG_RTT_CONSOLE=y CONFIG_LOG_BACKEND_RTT=y CONFIG_LOG_BACKEND_UART=n -CONFIG_DEBUG=y -CONFIG_LOG_BACKEND_RTT_MODE_DROP=y - -# # Logging UART -# CONFIG_CONSOLE=y -# CONFIG_UART_CONSOLE=y -# CONFIG_LOG=y -# CONFIG_LOG_DEFAULT_LEVEL=3 -# CONFIG_LOG_MODE_MINIMAL=n -# CONFIG_LOG_MODE_IMMEDIATE=y -# CONFIG_LOG_BACKEND_UART=y -# CONFIG_DEBUG=y -# CONFIG_LOG_MODE_OVERFLOW=y +CONFIG_SEGGER_RTT_MODE_NO_BLOCK_TRIM=y + +# Debugging +CONFIG_DEBUG=n