Merge pull request #12139 from fkjagodzinski/hal-reset_reason-get_capabilities

HAL: Add a get_capabilities() function to ResetReason API
pull/12273/head
Martin Kojtal 2020-01-16 14:44:31 +00:00 committed by GitHub
commit 31988d85fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 147 additions and 40 deletions

View File

@ -19,7 +19,7 @@ from mbed_host_tests import BaseHostTest
DEFAULT_SYNC_DELAY = 4.0 DEFAULT_SYNC_DELAY = 4.0
MSG_VALUE_WATCHDOG_PRESENT = 'wdg_present' MSG_VALUE_WATCHDOG_PRESENT = 1
MSG_VALUE_DUMMY = '0' MSG_VALUE_DUMMY = '0'
MSG_VALUE_RESET_REASON_GET = 'get' MSG_VALUE_RESET_REASON_GET = 'get'
MSG_VALUE_RESET_REASON_CLEAR = 'clear' MSG_VALUE_RESET_REASON_CLEAR = 'clear'
@ -66,6 +66,7 @@ class ResetReasonTest(BaseHostTest):
def __init__(self): def __init__(self):
super(ResetReasonTest, self).__init__() super(ResetReasonTest, self).__init__()
self.device_reasons = None
self.device_has_watchdog = None self.device_has_watchdog = None
self.raw_reset_reasons = set() self.raw_reset_reasons = set()
self.sync_delay = DEFAULT_SYNC_DELAY self.sync_delay = DEFAULT_SYNC_DELAY
@ -85,10 +86,13 @@ class ResetReasonTest(BaseHostTest):
def cb_device_ready(self, key, value, timestamp): def cb_device_ready(self, key, value, timestamp):
"""Request a raw value of the reset_reason register. """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: if self.device_reasons is None:
self.device_has_watchdog = (value == MSG_VALUE_WATCHDOG_PRESENT) 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) self.send_kv(MSG_KEY_RESET_REASON_RAW, MSG_VALUE_RESET_REASON_GET)
def cb_reset_reason_raw(self, key, value, timestamp): def cb_reset_reason_raw(self, key, value, timestamp):
@ -132,36 +136,46 @@ class ResetReasonTest(BaseHostTest):
self.send_kv(MSG_KEY_RESET_REASON, MSG_VALUE_RESET_REASON_CLEAR) self.send_kv(MSG_KEY_RESET_REASON, MSG_VALUE_RESET_REASON_CLEAR)
__ignored_clear_ack = yield __ignored_clear_ack = yield
# Request a NVIC_SystemReset() call.
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. # Request a NVIC_SystemReset() call.
self.send_kv(MSG_KEY_DEVICE_RESET, MSG_VALUE_DEVICE_RESET_NVIC) self.send_kv(MSG_KEY_DEVICE_RESET, MSG_VALUE_DEVICE_RESET_NVIC)
__ignored_reset_ack = yield __ignored_reset_ack = yield
time.sleep(self.sync_delay) time.sleep(self.sync_delay)
self.send_kv(MSG_KEY_SYNC, MSG_VALUE_DUMMY) self.send_kv(MSG_KEY_SYNC, MSG_VALUE_DUMMY)
reset_reason = yield reset_reason = yield
raise_if_different(RESET_REASONS['SOFTWARE'], reset_reason, 'Wrong reset reason. ') raise_if_different(RESET_REASONS[expected_reason], reset_reason, 'Wrong reset reason. ')
self.send_kv(MSG_KEY_RESET_REASON, MSG_VALUE_RESET_REASON_CLEAR) self.send_kv(MSG_KEY_RESET_REASON, MSG_VALUE_RESET_REASON_CLEAR)
__ignored_clear_ack = yield __ignored_clear_ack = yield
# Reset the device using DAP. # Reset the device using DAP.
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() self.reset()
__ignored_reset_ack = yield # 'reset_complete' __ignored_reset_ack = yield # 'reset_complete'
time.sleep(self.sync_delay) time.sleep(self.sync_delay)
self.send_kv(MSG_KEY_SYNC, MSG_VALUE_DUMMY) self.send_kv(MSG_KEY_SYNC, MSG_VALUE_DUMMY)
reset_reason = yield reset_reason = yield
raise_if_different(RESET_REASONS['PIN_RESET'], reset_reason, 'Wrong reset reason. ') raise_if_different(RESET_REASONS[expected_reason], reset_reason, 'Wrong reset reason. ')
self.send_kv(MSG_KEY_RESET_REASON, MSG_VALUE_RESET_REASON_CLEAR) self.send_kv(MSG_KEY_RESET_REASON, MSG_VALUE_RESET_REASON_CLEAR)
__ignored_clear_ack = yield __ignored_clear_ack = yield
# Start a watchdog timer and wait for it to reset the device. # Start a watchdog timer and wait for it to reset the device.
if not self.device_has_watchdog: expected_reason = 'WATCHDOG'
self.log('DUT does not have a watchdog. Skipping this reset reason.') 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: else:
self.send_kv(MSG_KEY_DEVICE_RESET, MSG_VALUE_DEVICE_RESET_WATCHDOG) self.send_kv(MSG_KEY_DEVICE_RESET, MSG_VALUE_DEVICE_RESET_WATCHDOG)
__ignored_reset_ack = yield __ignored_reset_ack = yield
time.sleep(self.sync_delay) time.sleep(self.sync_delay)
self.send_kv(MSG_KEY_SYNC, MSG_VALUE_DUMMY) self.send_kv(MSG_KEY_SYNC, MSG_VALUE_DUMMY)
reset_reason = yield 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. # The sequence is correct -- test passed.
yield True yield True

View File

@ -26,12 +26,10 @@
#if DEVICE_WATCHDOG #if DEVICE_WATCHDOG
# include "hal/watchdog_api.h" # include "hal/watchdog_api.h"
# define MSG_VALUE_WATCHDOG_STATUS 1
#define MSG_VALUE_WATCHDOG_STATUS "wdg_present"
# define WDG_TIMEOUT_MS 50UL # define WDG_TIMEOUT_MS 50UL
#else #else
#define MSG_VALUE_WATCHDOG_STATUS "no_wdg" # define MSG_VALUE_WATCHDOG_STATUS 0
#endif #endif
#define MSG_VALUE_DUMMY "0" #define MSG_VALUE_DUMMY "0"
@ -132,8 +130,18 @@ static cmd_status_t handle_command(const char *key, const char *value)
void test_reset_reason() void test_reset_reason()
{ {
// Report readiness and watchdog status. reset_reason_capabilities_t rrcap = {};
greentea_send_kv(MSG_KEY_DEVICE_READY, MSG_VALUE_WATCHDOG_STATUS); 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; cmd_status_t cmd_status = CMD_STATUS_CONTINUE;
static char _key[MSG_KEY_LEN + 1] = { }; static char _key[MSG_KEY_LEN + 1] = { };

View File

@ -26,12 +26,10 @@
#if DEVICE_WATCHDOG #if DEVICE_WATCHDOG
# include "hal/watchdog_api.h" # include "hal/watchdog_api.h"
# define MSG_VALUE_WATCHDOG_STATUS 1
#define MSG_VALUE_WATCHDOG_STATUS "wdg_present"
# define WDG_TIMEOUT_MS 50UL # define WDG_TIMEOUT_MS 50UL
#else #else
#define MSG_VALUE_WATCHDOG_STATUS "no_wdg" # define MSG_VALUE_WATCHDOG_STATUS 0
#endif #endif
#define MSG_VALUE_DUMMY "0" #define MSG_VALUE_DUMMY "0"
@ -127,8 +125,18 @@ static cmd_status_t handle_command(const char *key, const char *value)
void test_reset_reason() void test_reset_reason()
{ {
// Report readiness and watchdog status. reset_reason_capabilities_t rrcap = {};
greentea_send_kv(MSG_KEY_DEVICE_READY, MSG_VALUE_WATCHDOG_STATUS); 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; cmd_status_t cmd_status = CMD_STATUS_CONTINUE;
static char _key[MSG_KEY_LEN + 1] = { }; static char _key[MSG_KEY_LEN + 1] = { };

View File

@ -19,6 +19,7 @@
#include "i2c_api.h" #include "i2c_api.h"
#include "spi_api.h" #include "spi_api.h"
#include "gpio_api.h" #include "gpio_api.h"
#include "reset_reason_api.h"
#include "mbed_toolchain.h" #include "mbed_toolchain.h"
// To be re-implemented in the target layer if required // To be re-implemented in the target layer if required
@ -91,3 +92,14 @@ MBED_WEAK void spi_get_capabilities(PinName ssel, bool slave, spi_capabilities_t
} }
#endif #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

View File

@ -41,6 +41,8 @@ extern "C" {
* some other part of the application may have cleared the value. Therefore, * 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 * 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. * 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 * # Undefined behavior
* * There is no guarantee that the function ::hal_reset_reason_get will * * 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_UNKNOWN /**< Unknown or unreadable reset reason **/
} reset_reason_t; } 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. /** Fetch the reset reason for the last system reset.
* *
* This function must return the contents of the system reset reason registers * 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); 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 #ifdef __cplusplus

View File

@ -105,4 +105,23 @@ void hal_reset_reason_clear(void)
#endif #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 #endif // DEVICE_RESET_REASON

View File

@ -86,6 +86,13 @@ reset_reason_t hal_reset_reason_get(void)
return ret; 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) static bool bit_status(uint32_t reg, uint8_t bit_no)
{ {
bool status = false; bool status = false;

View File

@ -83,6 +83,13 @@ reset_reason_t hal_reset_reason_get(void)
return ret; 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) static bool bit_status(uint32_t reg, uint8_t bit_no)
{ {
bool status = false; bool status = false;

View File

@ -83,6 +83,13 @@ reset_reason_t hal_reset_reason_get(void)
return ret; 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) static bool bit_status(uint32_t reg, uint8_t bit_no)
{ {
bool status = false; bool status = false;

View File

@ -66,6 +66,12 @@ reset_reason_t hal_reset_reason_get(void)
return ret; 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) static uint8_t set_bit_count(uint32_t reg)
{ {
uint8_t count = 0; uint8_t count = 0;

View File

@ -88,6 +88,13 @@ reset_reason_t hal_reset_reason_get(void)
return ret; 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) static bool bit_status(uint32_t reg, uint8_t bit_no)
{ {
bool status = false; bool status = false;