fix nordic watchdog implementation, remove sanity task and perform sanity checks in idle, and have OS tickle the watchdog after sanity execution in idle task.
Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/83309483 Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/83309483 Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/83309483 Branch: refs/heads/develop Commit: 83309483dcffac17f8e683a5bfa33fd819671ebe Parents: abd1d90 Author: Sterling Hughes <sterl...@apache.org> Authored: Thu Sep 22 22:47:58 2016 -0700 Committer: Sterling Hughes <sterl...@apache.org> Committed: Thu Sep 22 22:47:58 2016 -0700 ---------------------------------------------------------------------- hw/bsp/nrf52dk/pkg.yml | 1 - hw/bsp/nrf52dk/src/os_bsp.c | 2 + hw/hal/include/hal/hal_watchdog.h | 4 +- hw/mcu/native/src/hal_watchdog.c | 37 ++++++++ hw/mcu/nordic/nrf51xxx/src/hal_watchdog.c | 15 ++- hw/mcu/nordic/nrf52xxx/src/hal_watchdog.c | 15 ++- hw/mcu/stm/stm32f4xx/src/hal_watchdog.c | 37 ++++++++ libs/os/include/os/os.h | 1 - libs/os/include/os/os_sanity.h | 12 ++- libs/os/pkg.yml | 8 ++ libs/os/src/arch/sim/os_arch_sim.c | 3 +- libs/os/src/os.c | 39 +++++++- libs/os/src/os_sanity.c | 125 ++++++++++--------------- 13 files changed, 209 insertions(+), 90 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/83309483/hw/bsp/nrf52dk/pkg.yml ---------------------------------------------------------------------- diff --git a/hw/bsp/nrf52dk/pkg.yml b/hw/bsp/nrf52dk/pkg.yml index e3d81c0..e8727ae 100644 --- a/hw/bsp/nrf52dk/pkg.yml +++ b/hw/bsp/nrf52dk/pkg.yml @@ -66,7 +66,6 @@ pkg.syscfg_defs: XTAL_32768: description: 'TBD' value: 1 - ADC_0: description: 'TBD' value: 0 http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/83309483/hw/bsp/nrf52dk/src/os_bsp.c ---------------------------------------------------------------------- diff --git a/hw/bsp/nrf52dk/src/os_bsp.c b/hw/bsp/nrf52dk/src/os_bsp.c index fc135ff..396ef82 100644 --- a/hw/bsp/nrf52dk/src/os_bsp.c +++ b/hw/bsp/nrf52dk/src/os_bsp.c @@ -25,6 +25,7 @@ #include "hal/hal_cputime.h" #include "hal/hal_flash.h" #include "hal/hal_spi.h" +#include "hal/hal_watchdog.h" #include "mcu/nrf52_hal.h" #include "uart/uart.h" #include "uart_hal/uart_hal.h" @@ -188,4 +189,5 @@ bsp_init(void) nrf52_adc_dev_init, &os_bsp_adc0_config); assert(rc == 0); #endif + } http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/83309483/hw/hal/include/hal/hal_watchdog.h ---------------------------------------------------------------------- diff --git a/hw/hal/include/hal/hal_watchdog.h b/hw/hal/include/hal/hal_watchdog.h index 973f40d..4fc334e 100644 --- a/hw/hal/include/hal/hal_watchdog.h +++ b/hw/hal/include/hal/hal_watchdog.h @@ -26,12 +26,12 @@ * smaller than 'expire_secs'. Watchdog needs to be then started with * a call to hal_watchdog_enable(). * - * @param expire_secs Watchdog timer expiration time + * @param expire_msecs Watchdog timer expiration time in msecs * * @return < 0 on failure; on success return the actual * expiration time as positive value */ -int hal_watchdog_init(int expire_secs); +int hal_watchdog_init(int expire_msecs); /* * Starts the watchdog. http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/83309483/hw/mcu/native/src/hal_watchdog.c ---------------------------------------------------------------------- diff --git a/hw/mcu/native/src/hal_watchdog.c b/hw/mcu/native/src/hal_watchdog.c new file mode 100644 index 0000000..dfd7304 --- /dev/null +++ b/hw/mcu/native/src/hal_watchdog.c @@ -0,0 +1,37 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "hal/hal_watchdog.h" + +int +hal_watchdog_init(int expire_msecs) +{ + return (0); +} + +void +hal_watchdog_enable(void) +{ +} + +void +hal_watchdog_tickle(void) +{ +} + http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/83309483/hw/mcu/nordic/nrf51xxx/src/hal_watchdog.c ---------------------------------------------------------------------- diff --git a/hw/mcu/nordic/nrf51xxx/src/hal_watchdog.c b/hw/mcu/nordic/nrf51xxx/src/hal_watchdog.c index 486aeec..7eeb65d 100644 --- a/hw/mcu/nordic/nrf51xxx/src/hal_watchdog.c +++ b/hw/mcu/nordic/nrf51xxx/src/hal_watchdog.c @@ -18,6 +18,7 @@ */ #include "hal/hal_watchdog.h" +#include "bsp/cmsis_nvic.h" #include <assert.h> @@ -26,6 +27,8 @@ #include "nrf_wdt.h" #include "nrf_drv_wdt.h" +extern void WDT_IRQHandler(void); + static void nrf51_hal_wdt_default_handler(void) { @@ -33,20 +36,28 @@ nrf51_hal_wdt_default_handler(void) } int -hal_watchdog_init(int expire_secs) +hal_watchdog_init(int expire_msecs) { nrf_drv_wdt_config_t cfg; + nrf_drv_wdt_channel_id cid; int rc; + NVIC_SetVector(WDT_IRQn, (uint32_t) WDT_IRQHandler); + cfg.behaviour = NRF_WDT_BEHAVIOUR_RUN_SLEEP; cfg.interrupt_priority = WDT_CONFIG_IRQ_PRIORITY; - cfg.reload_value = (uint32_t) expire_secs; + cfg.reload_value = (uint32_t) expire_msecs; rc = nrf_drv_wdt_init(&cfg, nrf51_hal_wdt_default_handler); if (rc != 0) { goto err; } + rc = nrf_drv_wdt_channel_alloc(&cid); + if (rc != 0) { + goto err; + } + return (0); err: return (rc); http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/83309483/hw/mcu/nordic/nrf52xxx/src/hal_watchdog.c ---------------------------------------------------------------------- diff --git a/hw/mcu/nordic/nrf52xxx/src/hal_watchdog.c b/hw/mcu/nordic/nrf52xxx/src/hal_watchdog.c index 6ba1aba..7c6ba38 100644 --- a/hw/mcu/nordic/nrf52xxx/src/hal_watchdog.c +++ b/hw/mcu/nordic/nrf52xxx/src/hal_watchdog.c @@ -18,6 +18,7 @@ */ #include "hal/hal_watchdog.h" +#include "bsp/cmsis_nvic.h" #include <assert.h> @@ -26,6 +27,8 @@ #include "nrf_wdt.h" #include "nrf_drv_wdt.h" +extern void WDT_IRQHandler(void); + static void nrf52_hal_wdt_default_handler(void) { @@ -33,20 +36,28 @@ nrf52_hal_wdt_default_handler(void) } int -hal_watchdog_init(int expire_secs) +hal_watchdog_init(int expire_msecs) { nrf_drv_wdt_config_t cfg; + nrf_drv_wdt_channel_id cid; int rc; + NVIC_SetVector(WDT_IRQn, (uint32_t) WDT_IRQHandler); + cfg.behaviour = NRF_WDT_BEHAVIOUR_RUN_SLEEP; cfg.interrupt_priority = WDT_CONFIG_IRQ_PRIORITY; - cfg.reload_value = (uint32_t) expire_secs; + cfg.reload_value = (uint32_t) expire_msecs; rc = nrf_drv_wdt_init(&cfg, nrf52_hal_wdt_default_handler); if (rc != 0) { goto err; } + rc = nrf_drv_wdt_channel_alloc(&cid); + if (rc != 0) { + goto err; + } + return (0); err: return (rc); http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/83309483/hw/mcu/stm/stm32f4xx/src/hal_watchdog.c ---------------------------------------------------------------------- diff --git a/hw/mcu/stm/stm32f4xx/src/hal_watchdog.c b/hw/mcu/stm/stm32f4xx/src/hal_watchdog.c new file mode 100644 index 0000000..dfd7304 --- /dev/null +++ b/hw/mcu/stm/stm32f4xx/src/hal_watchdog.c @@ -0,0 +1,37 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "hal/hal_watchdog.h" + +int +hal_watchdog_init(int expire_msecs) +{ + return (0); +} + +void +hal_watchdog_enable(void) +{ +} + +void +hal_watchdog_tickle(void) +{ +} + http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/83309483/libs/os/include/os/os.h ---------------------------------------------------------------------- diff --git a/libs/os/include/os/os.h b/libs/os/include/os/os.h index 5b64159..19d85b4 100644 --- a/libs/os/include/os/os.h +++ b/libs/os/include/os/os.h @@ -75,7 +75,6 @@ enum os_error { typedef enum os_error os_error_t; -#define OS_SANITY_PRIO (0xfe) #define OS_IDLE_PRIO (0xff) void os_init(void); http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/83309483/libs/os/include/os/os_sanity.h ---------------------------------------------------------------------- diff --git a/libs/os/include/os/os_sanity.h b/libs/os/include/os/os_sanity.h index 6af9808..fb93570 100644 --- a/libs/os/include/os/os_sanity.h +++ b/libs/os/include/os/os_sanity.h @@ -6,7 +6,7 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, @@ -20,10 +20,10 @@ #ifndef _OS_SANITY_H #define _OS_SANITY_H -#include <stdint.h> +#include <stdint.h> #include "os/os_time.h" -#include "os/queue.h" +#include "os/queue.h" struct os_sanity_check; typedef int (*os_sanity_check_func_t)(struct os_sanity_check *, void *); @@ -32,7 +32,7 @@ struct os_sanity_check { os_time_t sc_checkin_last; os_time_t sc_checkin_itvl; os_sanity_check_func_t sc_func; - void *sc_arg; + void *sc_arg; SLIST_ENTRY(os_sanity_check) sc_next; @@ -43,7 +43,9 @@ struct os_sanity_check { (__sc)->sc_arg = (__arg); \ (__sc)->sc_checkin_itvl = (__itvl) * OS_TICKS_PER_SEC; -int os_sanity_task_init(int); +int os_sanity_init(void); +void os_sanity_run(void); + struct os_task; int os_sanity_task_checkin(struct os_task *); http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/83309483/libs/os/pkg.yml ---------------------------------------------------------------------- diff --git a/libs/os/pkg.yml b/libs/os/pkg.yml index d302374..aedaedf 100644 --- a/libs/os/pkg.yml +++ b/libs/os/pkg.yml @@ -47,6 +47,14 @@ pkg.syscfg_defs: description: 'TBD' value: 'MYNEWT_PKG_SYS_COREDUMP' + SANITY_INTERVAL: + description: 'The interval at which the sanity checks should run, should be at least 200ms prior to watchdog' + value: 500 + + WATCHDOG_INTERVAL: + description: 'The interval at which the watchdog should reset if not tickled, in ms' + value: 1000 + MSYS_1_BLOCK_COUNT: description: 'TBD' value: 12 http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/83309483/libs/os/src/arch/sim/os_arch_sim.c ---------------------------------------------------------------------- diff --git a/libs/os/src/arch/sim/os_arch_sim.c b/libs/os/src/arch/sim/os_arch_sim.c index 36fc87d..51731f7 100644 --- a/libs/os/src/arch/sim/os_arch_sim.c +++ b/libs/os/src/arch/sim/os_arch_sim.c @@ -115,7 +115,7 @@ static void ctxsw_handler(int sig) { struct os_task *t, *next_t; - struct stack_frame *sf; + struct stack_frame *sf; int rc; OS_ASSERT_CRITICAL(); @@ -417,7 +417,6 @@ os_arch_os_init(void) signals_init(); os_init_idle_task(); - os_sanity_task_init(1); return OS_OK; } http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/83309483/libs/os/src/os.c ---------------------------------------------------------------------- diff --git a/libs/os/src/os.c b/libs/os/src/os.c index 6f47789..a7c7a5b 100644 --- a/libs/os/src/os.c +++ b/libs/os/src/os.c @@ -25,6 +25,7 @@ #include "hal/hal_os_tick.h" #include "hal/hal_bsp.h" +#include "hal/hal_watchdog.h" #include <assert.h> @@ -43,6 +44,7 @@ int g_os_started; #endif #define MAX_IDLE_TICKS (600 * OS_TICKS_PER_SEC) /* 10 minutes */ + /** * Idle operating system task, runs when no other tasks are running. * The idle task operates in tickless mode, which means it looks for @@ -57,14 +59,35 @@ os_idle_task(void *arg) os_sr_t sr; os_time_t now; os_time_t iticks, sticks, cticks; + os_time_t sanity_last; + os_time_t sanity_itvl_ticks; + + sanity_itvl_ticks = (MYNEWT_VAL(SANITY_INTERVAL) * OS_TICKS_PER_SEC) / 1000; + sanity_last = 0; + + hal_watchdog_tickle(); while (1) { ++g_os_idle_ctr; + + now = os_time_get(); + if (OS_TIME_TICK_GT(now, sanity_last + sanity_itvl_ticks)) { + os_sanity_run(); + /* Tickle the watchdog after successfully running sanity */ + hal_watchdog_tickle(); + sanity_last = now; + } + OS_ENTER_CRITICAL(sr); now = os_time_get(); sticks = os_sched_wakeup_ticks(now); cticks = os_callout_wakeup_ticks(now); iticks = min(sticks, cticks); + /* Wakeup in time to run sanity as well from the idle context, + * as the idle task does not schedule itself. + */ + iticks = min(iticks, ((sanity_last + sanity_itvl_ticks) - now)); + if (iticks < MIN_IDLE_TICKS) { iticks = 0; } else if (iticks > MAX_IDLE_TICKS) { @@ -95,9 +118,20 @@ os_started(void) void os_init_idle_task(void) { - os_task_init(&g_idle_task, "idle", os_idle_task, NULL, + int rc; + + rc = os_task_init(&g_idle_task, "idle", os_idle_task, NULL, OS_IDLE_PRIO, OS_WAIT_FOREVER, g_idle_task_stack, OS_STACK_ALIGN(OS_IDLE_STACK_SIZE)); + assert(rc == 0); + + /* Initialize sanity */ + rc = os_sanity_init(); + assert(rc == 0); + + assert(MYNEWT_VAL(WATCHDOG_INTERVAL) - 200 > MYNEWT_VAL(SANITY_INTERVAL)); + + hal_watchdog_init(MYNEWT_VAL(WATCHDOG_INTERVAL)); } /** @@ -140,6 +174,9 @@ os_start(void) err = os_dev_initialize_all(OS_DEV_INIT_KERNEL); assert(err == OS_OK); + /* Enable the watchdog prior to starting the OS */ + hal_watchdog_enable(); + err = os_arch_os_start(); assert(err == OS_OK); } http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/83309483/libs/os/src/os_sanity.c ---------------------------------------------------------------------- diff --git a/libs/os/src/os_sanity.c b/libs/os/src/os_sanity.c index b1c7083..f0aa5d2 100644 --- a/libs/os/src/os_sanity.c +++ b/libs/os/src/os_sanity.c @@ -6,7 +6,7 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, @@ -18,20 +18,14 @@ */ #include <assert.h> -#include <string.h> - -#include "os/os.h" - -SLIST_HEAD(, os_sanity_check) g_os_sanity_check_list = - SLIST_HEAD_INITIALIZER(os_sanity_check_list); - -struct os_mutex g_os_sanity_check_mu; +#include <string.h> -int g_os_sanity_num_secs; +#include "os/os.h" -struct os_task g_os_sanity_task; -os_stack_t g_os_sanity_task_stack[OS_STACK_ALIGN(OS_SANITY_STACK_SIZE)]; +SLIST_HEAD(, os_sanity_check) g_os_sanity_check_list = + SLIST_HEAD_INITIALIZER(os_sanity_check_list); +struct os_mutex g_os_sanity_check_mu; /** * Initialize a sanity check @@ -40,10 +34,10 @@ os_stack_t g_os_sanity_task_stack[OS_STACK_ALIGN(OS_SANITY_STACK_SIZE)]; * * @return 0 on success, error code on failure. */ -int +int os_sanity_check_init(struct os_sanity_check *sc) { - memset(sc, 0, sizeof(*sc)); + memset(sc, 0, sizeof(*sc)); return (0); } @@ -51,12 +45,12 @@ os_sanity_check_init(struct os_sanity_check *sc) /** * Lock the sanity check list * - * @return 0 on success, error code on failure. + * @return 0 on success, error code on failure. */ static int os_sanity_check_list_lock(void) { - int rc; + int rc; if (!g_os_started) { return (0); @@ -73,14 +67,14 @@ err: } /** - * Unlock the sanity check list + * Unlock the sanity check list * * @return 0 on success, error code on failure */ -static int +static int os_sanity_check_list_unlock(void) { - int rc; + int rc; if (!g_os_started) { return (0); @@ -103,10 +97,10 @@ err: * * @return 0 on success, error code on failure */ -int +int os_sanity_task_checkin(struct os_task *t) { - int rc; + int rc; if (t == NULL) { t = os_sched_get_current_task(); @@ -124,13 +118,13 @@ err: /** - * Register a sanity check + * Register a sanity check * - * @param sc The sanity check to register + * @param sc The sanity check to register * * @return 0 on success, error code on failure */ -int +int os_sanity_check_register(struct os_sanity_check *sc) { int rc; @@ -154,14 +148,14 @@ err: /** - * Reset the os sanity check, so that it doesn't trip up the + * Reset the os sanity check, so that it doesn't trip up the * sanity timer. * - * @param sc The sanity check to reset + * @param sc The sanity check to reset * - * @return 0 on success, error code on failure + * @return 0 on success, error code on failure */ -int +int os_sanity_check_reset(struct os_sanity_check *sc) { int rc; @@ -183,78 +177,61 @@ err: return (rc); } -/** - * The main sanity check task loop. This executes every SANITY_CHECK_NUM_SECS - * and goes through to see if any of the registered sanity checks are expired. - * If the sanity checks have expired, it restarts the operating system. - * - * @param arg unused +/* + * Called from the IDLE task context, every MYNEWT_VAL(SANITY_INTERVAL) msecs. * - * @return never + * Goes through the sanity check list, and performs sanity checks. If any of + * these checks failed, or tasks have not checked in, it resets the processor. */ -static void -os_sanity_task_loop(void *arg) +void +os_sanity_run(void) { - struct os_sanity_check *sc; - int rc; - - while (1) { - rc = os_sanity_check_list_lock(); - if (rc != 0) { - assert(0); - } + struct os_sanity_check *sc; + int rc; - SLIST_FOREACH(sc, &g_os_sanity_check_list, sc_next) { - rc = OS_OK; + rc = os_sanity_check_list_lock(); + if (rc != 0) { + assert(0); + } - if (sc->sc_func) { - rc = sc->sc_func(sc, sc->sc_arg); - if (rc == OS_OK) { - sc->sc_checkin_last = os_time_get(); - continue; - } - } + SLIST_FOREACH(sc, &g_os_sanity_check_list, sc_next) { + rc = OS_OK; - if (OS_TIME_TICK_GT(os_time_get() - sc->sc_checkin_last, - sc->sc_checkin_itvl)) { - assert(0); + if (sc->sc_func) { + rc = sc->sc_func(sc, sc->sc_arg); + if (rc == OS_OK) { + sc->sc_checkin_last = os_time_get(); + continue; } } - - rc = os_sanity_check_list_unlock(); - if (rc != 0) { + if (OS_TIME_TICK_GT(os_time_get(), + sc->sc_checkin_last + sc->sc_checkin_itvl)) { assert(0); } + } - os_time_delay(g_os_sanity_num_secs); + rc = os_sanity_check_list_unlock(); + if (rc != 0) { + assert(0); } } /** - * Initialize the sanity task and mutex. + * Initialize the sanity task and mutex. * * @return 0 on success, error code on failure */ -int -os_sanity_task_init(int num_secs) +int +os_sanity_init(void) { int rc; - g_os_sanity_num_secs = num_secs * OS_TICKS_PER_SEC; - - rc = os_mutex_init(&g_os_sanity_check_mu); + rc = os_mutex_init(&g_os_sanity_check_mu); if (rc != 0) { goto err; } - rc = os_task_init(&g_os_sanity_task, "os_sanity", os_sanity_task_loop, - NULL, OS_SANITY_PRIO, OS_WAIT_FOREVER, g_os_sanity_task_stack, - OS_STACK_ALIGN(OS_SANITY_STACK_SIZE)); - if (rc != OS_OK) { - goto err; - } - return (0); err: return (rc);