From 57420fc2f5cc67523515e58c4aabe1091ff2226a Mon Sep 17 00:00:00 2001 From: Filip Jagodzinski Date: Wed, 18 Dec 2019 16:42:34 +0100 Subject: [PATCH 1/4] HAL: ResetReason: Add the get_capabilities function Add the hal_reset_reason_get_capabilities() to ResetReason HAL API. Add a default, weak implementation, that every target can override. --- hal/mbed_compat.c | 14 +++++++++++++- hal/reset_reason_api.h | 12 ++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/hal/mbed_compat.c b/hal/mbed_compat.c index 5aa93138f5..33e5930004 100644 --- a/hal/mbed_compat.c +++ b/hal/mbed_compat.c @@ -19,6 +19,7 @@ #include "i2c_api.h" #include "spi_api.h" #include "gpio_api.h" +#include "reset_reason_api.h" #include "mbed_toolchain.h" // To be re-implemented in the target layer if required @@ -90,4 +91,15 @@ MBED_WEAK void spi_get_capabilities(PinName ssel, bool slave, spi_capabilities_t } } -#endif \ No newline at end of file +#endif + +#if DEVICE_RESET_REASON +// To be re-implemented in the target layer if required +MBED_WEAK void hal_reset_reason_get_capabilities(reset_reason_capabilities_t *cap) +{ + cap->reasons = (1 << RESET_REASON_PIN_RESET) | (1 << RESET_REASON_SOFTWARE); +#if DEVICE_WATCHDOG + cap->reasons |= 1 << RESET_REASON_WATCHDOG; +#endif +} +#endif diff --git a/hal/reset_reason_api.h b/hal/reset_reason_api.h index e5b46fef09..23bb402909 100644 --- a/hal/reset_reason_api.h +++ b/hal/reset_reason_api.h @@ -41,6 +41,8 @@ extern "C" { * some other part of the application may have cleared the value. Therefore, * though there may have been a reset reason in the registers when the system * started, the reason may not be available when the user comes to check it. + * * The function ::hal_reset_reason_get_capabilities fills the given + * `reset_reason_capabilities_t` instance. * * # Undefined behavior * * There is no guarantee that the function ::hal_reset_reason_get will @@ -88,6 +90,12 @@ typedef enum { RESET_REASON_UNKNOWN /**< Unknown or unreadable reset reason **/ } reset_reason_t; +/** Reset reason capabilities of the platform + */ +typedef struct { + uint32_t reasons; /**< Supported reset reasons. Each bit represents a corresponding reset_reason_t value.**/ +} reset_reason_capabilities_t; + /** Fetch the reset reason for the last system reset. * * This function must return the contents of the system reset reason registers @@ -137,6 +145,10 @@ uint32_t hal_reset_reason_get_raw(void); */ void hal_reset_reason_clear(void); +/** Fill the given reset_reason_capabilities_t instance according to platform capabilities. + */ +void hal_reset_reason_get_capabilities(reset_reason_capabilities_t *cap); + /**@}*/ #ifdef __cplusplus From 0b8baa568d86c0afeeaab055b1cc7f87ada3771b Mon Sep 17 00:00:00 2001 From: Filip Jagodzinski Date: Wed, 18 Dec 2019 17:39:59 +0100 Subject: [PATCH 2/4] Tests: ResetReason: Use the get_capabilities() Make use of the new hal_reset_reason_get_capabilities() function to skip unsupported reset resaons during tests. --- TESTS/host_tests/reset_reason.py | 60 +++++++++++++++--------- TESTS/mbed_drivers/reset_reason/main.cpp | 24 ++++++---- TESTS/mbed_hal/reset_reason/main.cpp | 24 ++++++---- 3 files changed, 69 insertions(+), 39 deletions(-) diff --git a/TESTS/host_tests/reset_reason.py b/TESTS/host_tests/reset_reason.py index 819a5f676f..4e33606767 100644 --- a/TESTS/host_tests/reset_reason.py +++ b/TESTS/host_tests/reset_reason.py @@ -19,7 +19,7 @@ from mbed_host_tests import BaseHostTest DEFAULT_SYNC_DELAY = 4.0 -MSG_VALUE_WATCHDOG_PRESENT = 'wdg_present' +MSG_VALUE_WATCHDOG_PRESENT = 1 MSG_VALUE_DUMMY = '0' MSG_VALUE_RESET_REASON_GET = 'get' MSG_VALUE_RESET_REASON_CLEAR = 'clear' @@ -66,6 +66,7 @@ class ResetReasonTest(BaseHostTest): def __init__(self): super(ResetReasonTest, self).__init__() + self.device_reasons = None self.device_has_watchdog = None self.raw_reset_reasons = set() self.sync_delay = DEFAULT_SYNC_DELAY @@ -85,10 +86,13 @@ class ResetReasonTest(BaseHostTest): def cb_device_ready(self, key, value, timestamp): """Request a raw value of the reset_reason register. - Additionally, save the device's watchdog status on the first call. + Additionally, save the device's reset_reason capabilities + and the watchdog status on the first call. """ - if self.device_has_watchdog is None: - self.device_has_watchdog = (value == MSG_VALUE_WATCHDOG_PRESENT) + if self.device_reasons is None: + reasons, wdg_status = (int(i, base=16) for i in value.split(',')) + self.device_has_watchdog = (wdg_status == MSG_VALUE_WATCHDOG_PRESENT) + self.device_reasons = [k for k, v in RESET_REASONS.items() if (reasons & 1 << int(v))] self.send_kv(MSG_KEY_RESET_REASON_RAW, MSG_VALUE_RESET_REASON_GET) def cb_reset_reason_raw(self, key, value, timestamp): @@ -133,35 +137,45 @@ class ResetReasonTest(BaseHostTest): __ignored_clear_ack = yield # Request a NVIC_SystemReset() call. - self.send_kv(MSG_KEY_DEVICE_RESET, MSG_VALUE_DEVICE_RESET_NVIC) - __ignored_reset_ack = yield - time.sleep(self.sync_delay) - self.send_kv(MSG_KEY_SYNC, MSG_VALUE_DUMMY) - reset_reason = yield - raise_if_different(RESET_REASONS['SOFTWARE'], reset_reason, 'Wrong reset reason. ') - self.send_kv(MSG_KEY_RESET_REASON, MSG_VALUE_RESET_REASON_CLEAR) - __ignored_clear_ack = yield + expected_reason = 'SOFTWARE' + if expected_reason not in self.device_reasons: + self.log('Skipping the {} reset reason -- not supported.'.format(expected_reason)) + else: + # Request a NVIC_SystemReset() call. + self.send_kv(MSG_KEY_DEVICE_RESET, MSG_VALUE_DEVICE_RESET_NVIC) + __ignored_reset_ack = yield + time.sleep(self.sync_delay) + self.send_kv(MSG_KEY_SYNC, MSG_VALUE_DUMMY) + reset_reason = yield + raise_if_different(RESET_REASONS[expected_reason], reset_reason, 'Wrong reset reason. ') + self.send_kv(MSG_KEY_RESET_REASON, MSG_VALUE_RESET_REASON_CLEAR) + __ignored_clear_ack = yield # Reset the device using DAP. - self.reset() - __ignored_reset_ack = yield # 'reset_complete' - time.sleep(self.sync_delay) - self.send_kv(MSG_KEY_SYNC, MSG_VALUE_DUMMY) - reset_reason = yield - raise_if_different(RESET_REASONS['PIN_RESET'], reset_reason, 'Wrong reset reason. ') - self.send_kv(MSG_KEY_RESET_REASON, MSG_VALUE_RESET_REASON_CLEAR) - __ignored_clear_ack = yield + expected_reason = 'PIN_RESET' + if expected_reason not in self.device_reasons: + self.log('Skipping the {} reset reason -- not supported.'.format(expected_reason)) + else: + self.reset() + __ignored_reset_ack = yield # 'reset_complete' + time.sleep(self.sync_delay) + self.send_kv(MSG_KEY_SYNC, MSG_VALUE_DUMMY) + reset_reason = yield + raise_if_different(RESET_REASONS[expected_reason], reset_reason, 'Wrong reset reason. ') + self.send_kv(MSG_KEY_RESET_REASON, MSG_VALUE_RESET_REASON_CLEAR) + __ignored_clear_ack = yield # Start a watchdog timer and wait for it to reset the device. - if not self.device_has_watchdog: - self.log('DUT does not have a watchdog. Skipping this reset reason.') + expected_reason = 'WATCHDOG' + if expected_reason not in self.device_reasons or not self.device_has_watchdog: + self.log('Skipping the {} reset reason -- not supported.'.format(expected_reason)) else: self.send_kv(MSG_KEY_DEVICE_RESET, MSG_VALUE_DEVICE_RESET_WATCHDOG) __ignored_reset_ack = yield time.sleep(self.sync_delay) self.send_kv(MSG_KEY_SYNC, MSG_VALUE_DUMMY) reset_reason = yield - raise_if_different(RESET_REASONS['WATCHDOG'], reset_reason, 'Wrong reset reason. ') + raise_if_different(RESET_REASONS[expected_reason], reset_reason, 'Wrong reset reason. ') # The sequence is correct -- test passed. yield True diff --git a/TESTS/mbed_drivers/reset_reason/main.cpp b/TESTS/mbed_drivers/reset_reason/main.cpp index f12a5a50fc..783d23cf36 100644 --- a/TESTS/mbed_drivers/reset_reason/main.cpp +++ b/TESTS/mbed_drivers/reset_reason/main.cpp @@ -25,13 +25,11 @@ #include "mbed.h" #if DEVICE_WATCHDOG -#include "hal/watchdog_api.h" - -#define MSG_VALUE_WATCHDOG_STATUS "wdg_present" -#define WDG_TIMEOUT_MS 50UL - +# include "hal/watchdog_api.h" +# define MSG_VALUE_WATCHDOG_STATUS 1 +# define WDG_TIMEOUT_MS 50UL #else -#define MSG_VALUE_WATCHDOG_STATUS "no_wdg" +# define MSG_VALUE_WATCHDOG_STATUS 0 #endif #define MSG_VALUE_DUMMY "0" @@ -119,8 +117,18 @@ static cmd_status_t handle_command(const char *key, const char *value) void test_reset_reason() { - // Report readiness and watchdog status. - greentea_send_kv(MSG_KEY_DEVICE_READY, MSG_VALUE_WATCHDOG_STATUS); + reset_reason_capabilities_t rrcap = {}; + hal_reset_reason_get_capabilities(&rrcap); + char msg_value[11]; + int str_len = snprintf(msg_value, sizeof msg_value, "%08lx,%01x", rrcap.reasons, MSG_VALUE_WATCHDOG_STATUS); + if (str_len != (sizeof msg_value) - 1) { + printf("Failed to compose a value string to be sent to host."); + GREENTEA_TESTSUITE_RESULT(0); + return; + } + + // Report readiness, capabilities and watchdog status. + greentea_send_kv(MSG_KEY_DEVICE_READY, msg_value); cmd_status_t cmd_status = CMD_STATUS_CONTINUE; static char _key[MSG_KEY_LEN + 1] = { }; diff --git a/TESTS/mbed_hal/reset_reason/main.cpp b/TESTS/mbed_hal/reset_reason/main.cpp index b97b907409..84e10c9254 100644 --- a/TESTS/mbed_hal/reset_reason/main.cpp +++ b/TESTS/mbed_hal/reset_reason/main.cpp @@ -25,13 +25,11 @@ #include "mbed.h" #if DEVICE_WATCHDOG -#include "hal/watchdog_api.h" - -#define MSG_VALUE_WATCHDOG_STATUS "wdg_present" -#define WDG_TIMEOUT_MS 50UL - +# include "hal/watchdog_api.h" +# define MSG_VALUE_WATCHDOG_STATUS 1 +# define WDG_TIMEOUT_MS 50UL #else -#define MSG_VALUE_WATCHDOG_STATUS "no_wdg" +# define MSG_VALUE_WATCHDOG_STATUS 0 #endif #define MSG_VALUE_DUMMY "0" @@ -126,8 +124,18 @@ static cmd_status_t handle_command(const char *key, const char *value) void test_reset_reason() { - // Report readiness and watchdog status. - greentea_send_kv(MSG_KEY_DEVICE_READY, MSG_VALUE_WATCHDOG_STATUS); + reset_reason_capabilities_t rrcap = {}; + hal_reset_reason_get_capabilities(&rrcap); + char msg_value[11]; + int str_len = snprintf(msg_value, sizeof msg_value, "%08lx,%01x", rrcap.reasons, MSG_VALUE_WATCHDOG_STATUS); + if (str_len != (sizeof msg_value) - 1) { + printf("Failed to compose a value string to be sent to host."); + GREENTEA_TESTSUITE_RESULT(0); + return; + } + + // Report readiness, capabilities and watchdog status. + greentea_send_kv(MSG_KEY_DEVICE_READY, msg_value); cmd_status_t cmd_status = CMD_STATUS_CONTINUE; static char _key[MSG_KEY_LEN + 1] = { }; From ffd8d70a55ae1d4dc6f0705c657f56c97d99fada Mon Sep 17 00:00:00 2001 From: Filip Jagodzinski Date: Thu, 19 Dec 2019 10:34:00 +0100 Subject: [PATCH 3/4] K64F: Add hal_reset_reason_get_capabilities() --- .../TARGET_MCU_K64F/reset_reason.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/reset_reason.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/reset_reason.c index 6a646211d8..0009602f0d 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/reset_reason.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/reset_reason.c @@ -105,4 +105,23 @@ void hal_reset_reason_clear(void) #endif } +void hal_reset_reason_get_capabilities(reset_reason_capabilities_t *cap) +{ + cap->reasons = 1 << RESET_REASON_UNKNOWN; + cap->reasons |= 1 << RESET_REASON_POWER_ON; + cap->reasons |= 1 << RESET_REASON_BROWN_OUT; + cap->reasons |= 1 << RESET_REASON_WATCHDOG; + cap->reasons |= 1 << RESET_REASON_PIN_RESET; + cap->reasons |= 1 << RESET_REASON_SOFTWARE; + +#if (defined(FSL_FEATURE_RCM_HAS_WAKEUP) && FSL_FEATURE_RCM_HAS_WAKEUP) || \ + (defined(FSL_FEATURE_RCM_HAS_LOC) && FSL_FEATURE_RCM_HAS_LOC) || \ + (defined(FSL_FEATURE_RCM_HAS_LOL) && FSL_FEATURE_RCM_HAS_LOL) || \ + (defined(FSL_FEATURE_RCM_HAS_JTAG) && FSL_FEATURE_RCM_HAS_JTAG) || \ + (defined(FSL_FEATURE_RCM_HAS_MDM_AP) && FSL_FEATURE_RCM_HAS_MDM_AP) || \ + (defined(FSL_FEATURE_RCM_HAS_EZPORT) && FSL_FEATURE_RCM_HAS_EZPORT) + cap->reasons |= 1 << RESET_REASON_PLATFORM; +#endif +} + #endif // DEVICE_RESET_REASON From a9581995944ec568b7caf1e35fa9f4349ef4fa5f Mon Sep 17 00:00:00 2001 From: Filip Jagodzinski Date: Fri, 3 Jan 2020 16:47:09 +0100 Subject: [PATCH 4/4] TOSHIBA: Add hal_reset_reason_get_capabilities() Override the default, weak implementation of hal_reset_reason_get_capabilities() for TMPM066, TMPM3H6, TMPM3HQ, TMPM46B & TMPM4G9. --- targets/TARGET_TOSHIBA/TARGET_TMPM066/reset_reason_api.c | 7 +++++++ targets/TARGET_TOSHIBA/TARGET_TMPM3H6/reset_reason_api.c | 7 +++++++ targets/TARGET_TOSHIBA/TARGET_TMPM3HQ/reset_reason_api.c | 7 +++++++ targets/TARGET_TOSHIBA/TARGET_TMPM46B/reset_reason_api.c | 6 ++++++ targets/TARGET_TOSHIBA/TARGET_TMPM4G9/reset_reason_api.c | 7 +++++++ 5 files changed, 34 insertions(+) diff --git a/targets/TARGET_TOSHIBA/TARGET_TMPM066/reset_reason_api.c b/targets/TARGET_TOSHIBA/TARGET_TMPM066/reset_reason_api.c index 817a1f489f..0c17fcd410 100644 --- a/targets/TARGET_TOSHIBA/TARGET_TMPM066/reset_reason_api.c +++ b/targets/TARGET_TOSHIBA/TARGET_TMPM066/reset_reason_api.c @@ -86,6 +86,13 @@ reset_reason_t hal_reset_reason_get(void) return ret; } +void hal_reset_reason_get_capabilities(reset_reason_capabilities_t *cap) +{ + cap->reasons = 1 << RESET_REASON_UNKNOWN; + cap->reasons |= 1 << RESET_REASON_POWER_ON; + cap->reasons |= 1 << RESET_REASON_MULTIPLE; +} + static bool bit_status(uint32_t reg, uint8_t bit_no) { bool status = false; diff --git a/targets/TARGET_TOSHIBA/TARGET_TMPM3H6/reset_reason_api.c b/targets/TARGET_TOSHIBA/TARGET_TMPM3H6/reset_reason_api.c index d5b50a952b..1d65e9f425 100644 --- a/targets/TARGET_TOSHIBA/TARGET_TMPM3H6/reset_reason_api.c +++ b/targets/TARGET_TOSHIBA/TARGET_TMPM3H6/reset_reason_api.c @@ -83,6 +83,13 @@ reset_reason_t hal_reset_reason_get(void) return ret; } +void hal_reset_reason_get_capabilities(reset_reason_capabilities_t *cap) +{ + cap->reasons = 1 << RESET_REASON_UNKNOWN; + cap->reasons |= 1 << RESET_REASON_POWER_ON; + cap->reasons |= 1 << RESET_REASON_MULTIPLE; +} + static bool bit_status(uint32_t reg, uint8_t bit_no) { bool status = false; diff --git a/targets/TARGET_TOSHIBA/TARGET_TMPM3HQ/reset_reason_api.c b/targets/TARGET_TOSHIBA/TARGET_TMPM3HQ/reset_reason_api.c index f5873ea798..af5a06f633 100644 --- a/targets/TARGET_TOSHIBA/TARGET_TMPM3HQ/reset_reason_api.c +++ b/targets/TARGET_TOSHIBA/TARGET_TMPM3HQ/reset_reason_api.c @@ -83,6 +83,13 @@ reset_reason_t hal_reset_reason_get(void) return ret; } +void hal_reset_reason_get_capabilities(reset_reason_capabilities_t *cap) +{ + cap->reasons = 1 << RESET_REASON_UNKNOWN; + cap->reasons |= 1 << RESET_REASON_POWER_ON; + cap->reasons |= 1 << RESET_REASON_MULTIPLE; +} + static bool bit_status(uint32_t reg, uint8_t bit_no) { bool status = false; diff --git a/targets/TARGET_TOSHIBA/TARGET_TMPM46B/reset_reason_api.c b/targets/TARGET_TOSHIBA/TARGET_TMPM46B/reset_reason_api.c index 34176775d9..86ab7e6026 100644 --- a/targets/TARGET_TOSHIBA/TARGET_TMPM46B/reset_reason_api.c +++ b/targets/TARGET_TOSHIBA/TARGET_TMPM46B/reset_reason_api.c @@ -66,6 +66,12 @@ reset_reason_t hal_reset_reason_get(void) return ret; } +void hal_reset_reason_get_capabilities(reset_reason_capabilities_t *cap) +{ + cap->reasons = 1 << RESET_REASON_UNKNOWN; + cap->reasons |= 1 << RESET_REASON_MULTIPLE; +} + static uint8_t set_bit_count(uint32_t reg) { uint8_t count = 0; diff --git a/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/reset_reason_api.c b/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/reset_reason_api.c index 084cba3b48..0bf1cc56f4 100644 --- a/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/reset_reason_api.c +++ b/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/reset_reason_api.c @@ -88,6 +88,13 @@ reset_reason_t hal_reset_reason_get(void) return ret; } +void hal_reset_reason_get_capabilities(reset_reason_capabilities_t *cap) +{ + cap->reasons = 1 << RESET_REASON_UNKNOWN; + cap->reasons |= 1 << RESET_REASON_POWER_ON; + cap->reasons |= 1 << RESET_REASON_MULTIPLE; +} + static bool bit_status(uint32_t reg, uint8_t bit_no) { bool status = false;