mirror of https://github.com/ARMmbed/mbed-os.git
				
				
				
			Merge pull request #12139 from fkjagodzinski/hal-reset_reason-get_capabilities
HAL: Add a get_capabilities() function to ResetReason APIpull/12273/head
						commit
						31988d85fe
					
				| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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"
 | 
			
		||||
| 
						 | 
				
			
			@ -132,8 +130,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] = { };
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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"
 | 
			
		||||
| 
						 | 
				
			
			@ -127,8 +125,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] = { };
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
#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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue