Merge pull request #8328 from kjbracey-arm/noreturn

Error path tightening: use MBED_NORETURN; add+use core_util_atomic_flag
pull/8580/head
Cruz Monrreal 2018-10-29 20:49:54 -05:00 committed by GitHub
commit 5ed07c2dd4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 158 additions and 201 deletions

View File

@ -34,21 +34,6 @@ using utest::v1::Case;
using utest::v1::Specification;
using utest::v1::Harness;
static uint32_t num_test_errors = 0UL;
mbed_error_status_t mbed_error(mbed_error_status_t error_status, const char *error_msg, unsigned int error_value,
const char *filename, int line_number)
{
(void) error_status;
(void) error_msg;
(void) error_value;
(void) filename;
(void) line_number;
num_test_errors++;
return MBED_SUCCESS;
}
void test_lock_unlock()
{
TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep());
@ -60,16 +45,6 @@ void test_lock_unlock()
TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep());
}
void test_lone_unlock()
{
uint32_t expected_err_count = num_test_errors + 1;
sleep_manager_unlock_deep_sleep();
TEST_ASSERT_EQUAL_UINT32(expected_err_count, num_test_errors);
// Make sure upcoming tests won't be broken.
TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep());
}
void test_lock_eq_ushrt_max()
{
uint32_t lock_count = 0;
@ -87,27 +62,6 @@ void test_lock_eq_ushrt_max()
TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep());
}
void test_lock_gt_ushrt_max()
{
uint32_t lock_count = 0;
while (lock_count < USHRT_MAX) {
sleep_manager_lock_deep_sleep();
lock_count++;
TEST_ASSERT_FALSE(sleep_manager_can_deep_sleep());
}
uint32_t expected_err_count = num_test_errors + 1;
sleep_manager_lock_deep_sleep();
TEST_ASSERT_EQUAL_UINT32(expected_err_count, num_test_errors);
// Make sure upcoming tests won't be broken.
while (lock_count > 0) {
sleep_manager_unlock_deep_sleep();
lock_count--;
}
TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep());
}
#if DEVICE_LPTICKER
#if DEVICE_USTICKER
utest::v1::status_t testcase_setup(const Case *const source, const size_t index_of_case)
@ -279,9 +233,7 @@ utest::v1::status_t testsuite_setup(const size_t number_of_cases)
Case cases[] = {
Case("deep sleep lock/unlock", test_lock_unlock),
Case("deep sleep unbalanced unlock", test_lone_unlock),
Case("deep sleep locked USHRT_MAX times", test_lock_eq_ushrt_max),
Case("deep sleep locked more than USHRT_MAX times", test_lock_gt_ushrt_max),
#if DEVICE_LPTICKER
#if DEVICE_USTICKER
Case("sleep_auto calls sleep/deep sleep based on lock",

View File

@ -38,14 +38,6 @@
*/
void test_lock_unlock();
/** Test an unbalanced unlock call
*
* Given the deep sleep has not been locked
* When the deep sleep mode is unlocked
* Then an mbed_error is raised
*/
void test_lone_unlock();
/** Test lock USHRT_MAX times
*
* Given a device with sleep mode support
@ -58,14 +50,6 @@ void test_lone_unlock();
*/
void test_lock_eq_ushrt_max();
/** Test lock more than USHRT_MAX times
*
* Given the deep sleep has already been locked USHRT_MAX times
* When the deep sleep mode is locked again
* Then an mbed_error is raised
*/
void test_lock_gt_ushrt_max();
/** Test sleep_auto calls sleep and deep sleep based on lock
*
* Given a device with sleep mode support

View File

@ -48,26 +48,6 @@ using utest::v1::Case;
Semaphore sync_sem(0, 1);
/* In order to successfully run this test suite when compiled with --profile=debug
* error() has to be redefined as noop.
*
* EventFlags calls RTX API which uses Event Recorder functionality. When compiled
* with MBED_TRAP_ERRORS_ENABLED=1 (set in debug profile) EvrRtxEventFlagsError() calls error()
* which aborts test program.
*/
#if defined(MBED_TRAP_ERRORS_ENABLED) && MBED_TRAP_ERRORS_ENABLED
void error(const char *format, ...)
{
(void) format;
}
//Override the set_error function to trap the errors
mbed_error_status_t mbed_error(mbed_error_status_t error_status, const char *error_msg, unsigned int error_value, const char *filename, int line_number)
{
return MBED_SUCCESS;
}
#endif
template<uint32_t flags, uint32_t wait_ms>
void send_thread(EventFlags *ef)
{
@ -167,14 +147,18 @@ void test_prohibited(void)
ev.set(FLAG01 | FLAG02 | FLAG03);
#if !MBED_TRAP_ERRORS_ENABLED
flags = ev.clear(PROHIBITED_FLAG);
TEST_ASSERT_EQUAL(osFlagsErrorParameter, flags);
#endif
flags = ev.get();
TEST_ASSERT_EQUAL(FLAG01 | FLAG02 | FLAG03, flags);
#if !MBED_TRAP_ERRORS_ENABLED
flags = ev.set(PROHIBITED_FLAG);
TEST_ASSERT_EQUAL(osFlagsErrorParameter, flags);
#endif
flags = ev.get();
TEST_ASSERT_EQUAL(FLAG01 | FLAG02 | FLAG03, flags);

View File

@ -77,25 +77,6 @@ void sem_callback(Semaphore *sem)
sem->release();
}
/* In order to successfully run this test suite when compiled with --profile=debug
* error() has to be redefined as noop.
*
* RtosTimer calls RTX API which uses Event Recorder functionality. When compiled
* with MBED_TRAP_ERRORS_ENABLED=1 (set in debug profile) EvrRtxTimerError() calls error()
* which aborts test program.
*/
#if defined(MBED_TRAP_ERRORS_ENABLED) && MBED_TRAP_ERRORS_ENABLED
void error(const char *format, ...)
{
(void) format;
}
mbed_error_status_t mbed_error(mbed_error_status_t error_status, const char *error_msg, unsigned int error_value, const char *filename, int line_number)
{
return MBED_SUCCESS;
}
#endif
/** Test one-shot not restarted when elapsed
*
* Given a one-shot RtosTimer
@ -121,8 +102,11 @@ void test_oneshot_not_restarted()
slots = stopwatch.wait_until_stopped(DELAY_MS + DELTA_MS);
TEST_ASSERT_EQUAL(0, slots);
#if !MBED_TRAP_ERRORS_ENABLED
status = rtostimer.stop();
TEST_ASSERT_EQUAL(osErrorResource, status);
#endif
}
/** Test periodic repeats continuously
@ -160,8 +144,11 @@ void test_periodic_repeats()
slots = stopwatch.wait_until_stopped(DELAY_MS + DELTA_MS);
TEST_ASSERT_EQUAL(0, slots);
#if !MBED_TRAP_ERRORS_ENABLED
status = rtostimer.stop();
TEST_ASSERT_EQUAL(osErrorResource, status);
#endif
}
/** Test timer can be started again
@ -185,8 +172,10 @@ void test_start_again()
int32_t slots = sem.wait(DELAY_MS + DELTA_MS);
TEST_ASSERT_EQUAL(1, slots);
#if !MBED_TRAP_ERRORS_ENABLED
status = rtostimer.stop();
TEST_ASSERT_EQUAL(osErrorResource, status);
#endif
status = rtostimer.start(DELAY_MS);
TEST_ASSERT_EQUAL(osOK, status);
@ -194,8 +183,10 @@ void test_start_again()
slots = sem.wait(DELAY_MS + DELTA_MS);
TEST_ASSERT_EQUAL(1, slots);
#if !MBED_TRAP_ERRORS_ENABLED
status = rtostimer.stop();
TEST_ASSERT_EQUAL(osErrorResource, status);
#endif
}
/** Test timer restart updates delay
@ -228,8 +219,10 @@ void test_restart_updates_delay()
TEST_ASSERT_EQUAL(1, slots);
TEST_ASSERT_INT_WITHIN(DELTA_MS, DELAY2_MS, stopwatch.read_ms());
#if !MBED_TRAP_ERRORS_ENABLED
status = rtostimer.stop();
TEST_ASSERT_EQUAL(osErrorResource, status);
#endif
}
/** Test timer is created in stopped state
@ -241,8 +234,10 @@ void test_restart_updates_delay()
void test_created_stopped()
{
RtosTimer rtostimer(mbed::callback(sem_callback, (Semaphore *) NULL), osTimerOnce);
#if !MBED_TRAP_ERRORS_ENABLED
osStatus status = rtostimer.stop();
TEST_ASSERT_EQUAL(osErrorResource, status);
#endif
}
/** Test one-shot can be stopped
@ -269,8 +264,10 @@ void test_stop()
slots = sem.wait(DELAY_MS + DELTA_MS);
TEST_ASSERT_EQUAL(0, slots);
#if !MBED_TRAP_ERRORS_ENABLED
status = rtostimer.stop();
TEST_ASSERT_EQUAL(osErrorResource, status);
#endif
}
/** Test timer started with infinite delay
@ -290,6 +287,7 @@ void test_wait_forever()
TEST_ASSERT_EQUAL(osOK, status);
}
#if !MBED_TRAP_ERRORS_ENABLED
/** Test timer started with zero delay
*
* Given a one-shot RtosTimer
@ -331,6 +329,7 @@ void test_isr_calls_fail()
wait_ms(DELAY_MS + DELTA_MS);
}
#endif // !MBED_TRAP_ERRORS_ENABLED
utest::v1::status_t test_setup(const size_t number_of_cases)
{
@ -346,8 +345,10 @@ Case cases[] = {
Case("Timer can be stopped", test_stop),
Case("Timer is created in stopped state", test_created_stopped),
Case("Timer started with infinite delay", test_wait_forever),
#if !MBED_TRAP_ERRORS_ENABLED
Case("Timer started with zero delay", test_no_wait),
Case("Calls from ISR fail", test_isr_calls_fail)
#endif
};
Specification specification(test_setup, cases);

View File

@ -46,27 +46,6 @@ struct Sync {
Semaphore &sem_child;
};
/* In order to successfully run this test suite when compiled with --profile=debug
* error() has to be redefined as noop.
*
* ThreadFlags calls RTX API which uses Event Recorder functionality. When compiled
* with MBED_TRAP_ERRORS_ENABLED=1 (set in debug profile) EvrRtxEventFlagsError() calls error()
* which aborts test program.
*/
#if defined(MBED_TRAP_ERRORS_ENABLED) && MBED_TRAP_ERRORS_ENABLED
void error(const char *format, ...)
{
(void) format;
}
mbed_error_status_t mbed_error(mbed_error_status_t error_status, const char *error_msg, unsigned int error_value, const char *filename, int line_number)
{
return MBED_SUCCESS;
}
#endif
template <int32_t signals, uint32_t timeout, int32_t test_val>
void run_signal_wait(void)
{
@ -214,8 +193,10 @@ void test_set_prohibited(void)
sem_parent.wait();
t.signal_set(ALL_SIGNALS);
#if !MBED_TRAP_ERRORS_ENABLED
ret = t.signal_set(PROHIBITED_SIGNAL);
TEST_ASSERT_EQUAL(osErrorParameter, ret);
#endif
sem_child.release();
t.join();

View File

@ -97,7 +97,7 @@
void lwip_mbed_tracef_debug(const char *fmt, ...);
void lwip_mbed_tracef_error(const char *fmt, ...);
void lwip_mbed_tracef_warn(const char *fmt, ...);
void lwip_mbed_assert_fail(const char *msg, const char *func, const char *file, unsigned int line);
MBED_NORETURN void lwip_mbed_assert_fail(const char *msg, const char *func, const char *file, unsigned int line);
#define LWIP_PLATFORM_DIAG(vars) lwip_mbed_tracef_debug vars
#define LWIP_PLATFORM_DIAG_SEVERE(vars) lwip_mbed_tracef_error vars
@ -109,7 +109,7 @@ void lwip_mbed_assert_fail(const char *msg, const char *func, const char *file,
#else // MBED_CONF_LWIP_USE_MBED_TRACE
#include <stdio.h>
void assert_printf(char *msg, int line, char *file);
MBED_NORETURN void assert_printf(char *msg, int line, char *file);
/* Plaform specific diagnostic output */
#define LWIP_PLATFORM_DIAG(vars) printf vars

View File

@ -589,7 +589,7 @@ void lwip_mbed_tracef_error(const char *fmt, ...)
va_end(ap);
}
void lwip_mbed_assert_fail(const char *msg, const char *func, const char *file, unsigned int line)
MBED_NORETURN void lwip_mbed_assert_fail(const char *msg, const char *func, const char *file, unsigned int line)
{
mbed_tracef(TRACE_LEVEL_ERROR, "lwIP", "Assertion failed: %s, function %s, file %s, line %u.", msg, func, file, line);
exit(EXIT_FAILURE); // XXX how about abort? mbed_assert uses exit, so follow suit
@ -605,7 +605,7 @@ void lwip_mbed_assert_fail(const char *msg, const char *func, const char *file,
\param[in] line Line number in file with error
\param[in] file Filename with error
*/
void assert_printf(char *msg, int line, char *file) {
MBED_NORETURN void assert_printf(char *msg, int line, char *file) {
if (msg)
error("%s:%d in file %s\n", msg, line, file);
else

View File

@ -163,10 +163,6 @@ void sleep_manager_lock_deep_sleep_internal(void)
if (deep_sleep_lock == USHRT_MAX) {
core_util_critical_section_exit();
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_HAL, MBED_ERROR_CODE_OVERFLOW), "DeepSleepLock overflow (> USHRT_MAX)", deep_sleep_lock);
// When running sleep_manager tests, the mbed_error() is overridden
// and no longer calls mbed_halt_system(). Return to prevent
// execution of the following code.
return;
}
core_util_atomic_incr_u16(&deep_sleep_lock, 1);
core_util_critical_section_exit();
@ -178,10 +174,6 @@ void sleep_manager_unlock_deep_sleep_internal(void)
if (deep_sleep_lock == 0) {
core_util_critical_section_exit();
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_HAL, MBED_ERROR_CODE_UNDERFLOW), "DeepSleepLock underflow (< 0)", deep_sleep_lock);
// When running sleep_manager tests, the mbed_error() is overridden
// and no longer calls mbed_halt_system(). Return to prevent
// execution of the following code.
return;
}
core_util_atomic_decr_u16(&deep_sleep_lock, 1);
core_util_critical_section_exit();

View File

@ -20,7 +20,7 @@
#include "platform/mbed_critical.h"
#include "platform/mbed_error.h"
void mbed_assert_internal(const char *expr, const char *file, int line)
MBED_NORETURN void mbed_assert_internal(const char *expr, const char *file, int line)
{
core_util_critical_section_enter();
mbed_error(MBED_ERROR_ASSERTION_FAILED, expr, 0, file, line);

View File

@ -24,6 +24,7 @@
#define MBED_ASSERT_H
#include "mbed_preprocessor.h"
#include "mbed_toolchain.h"
#ifdef __cplusplus
extern "C" {
@ -37,7 +38,7 @@ extern "C" {
* @param file File where assertation failed.
* @param line Failing assertation line number.
*/
void mbed_assert_internal(const char *expr, const char *file, int line);
MBED_NORETURN void mbed_assert_internal(const char *expr, const char *file, int line);
#ifdef __cplusplus
}

View File

@ -21,7 +21,7 @@
#include "platform/mbed_retarget.h"
#include "platform/mbed_critical.h"
WEAK void mbed_die(void)
WEAK MBED_NORETURN void mbed_die(void)
{
#if !defined (NRF51_H) && !defined(TARGET_EFM32)
core_util_critical_section_enter();

View File

@ -100,6 +100,11 @@ void core_util_critical_section_exit(void)
}
}
void core_util_atomic_flag_clear(volatile core_util_atomic_flag *flagPtr)
{
flagPtr->_flag = false;
}
#if MBED_EXCLUSIVE_ACCESS
/* Supress __ldrex and __strex deprecated warnings - "#3731-D: intrinsic is deprecated" */
@ -107,6 +112,15 @@ void core_util_critical_section_exit(void)
#pragma diag_suppress 3731
#endif
bool core_util_atomic_flag_test_and_set(volatile core_util_atomic_flag *flagPtr)
{
uint8_t currentValue;
do {
currentValue = __LDREXB(&flagPtr->_flag);
} while (__STREXB(true, &flagPtr->_flag));
return currentValue;
}
bool core_util_atomic_cas_u8(volatile uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue)
{
do {
@ -204,6 +218,15 @@ uint32_t core_util_atomic_decr_u32(volatile uint32_t *valuePtr, uint32_t delta)
#else
bool core_util_atomic_flag_test_and_set(volatile core_util_atomic_flag *flagPtr)
{
core_util_critical_section_enter();
uint8_t currentValue = flagPtr->_flag;
flagPtr->_flag = true;
core_util_critical_section_exit();
return currentValue;
}
bool core_util_atomic_cas_u8(volatile uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue)
{
bool success;

View File

@ -89,6 +89,43 @@ void core_util_critical_section_exit(void);
*/
bool core_util_in_critical_section(void);
/**
* A lock-free, primitive atomic flag.
*
* Emulate C11's atomic_flag. The flag is initially in an indeterminate state
* unless explicitly initialised with CORE_UTIL_ATOMIC_FLAG_INIT.
*/
typedef struct core_util_atomic_flag {
uint8_t _flag;
} core_util_atomic_flag;
/**
* Initialiser for a core_util_atomic_flag.
*
* Example:
* ~~~
* core_util_atomic_flag in_progress = CORE_UTIL_ATOMIC_FLAG_INIT;
* ~~~
*/
#define CORE_UTIL_ATOMIC_FLAG_INIT { 0 }
/**
* Atomic test and set.
*
* Atomically tests then sets the flag to true, returning the previous value.
*
* @param flagPtr Target flag being tested and set.
* @return The previous value.
*/
bool core_util_atomic_flag_test_and_set(volatile core_util_atomic_flag *flagPtr);
/**
* Atomic clear.
*
* @param flagPtr Target flag being cleared.
*/
void core_util_atomic_flag_clear(volatile core_util_atomic_flag *flagPtr);
/**
* Atomic compare and set. It compares the contents of a memory location to a
* given value and, only if they are the same, modifies the contents of that

View File

@ -36,7 +36,8 @@ static void print_error_report(const mbed_error_ctx *ctx, const char *, const ch
#define ERROR_REPORT(ctx, error_msg, error_filename, error_line) ((void) 0)
#endif
static uint8_t error_in_progress = 0;
static core_util_atomic_flag error_in_progress = CORE_UTIL_ATOMIC_FLAG_INIT;
static core_util_atomic_flag halt_in_progress = CORE_UTIL_ATOMIC_FLAG_INIT;
static int error_count = 0;
static mbed_error_ctx first_error_ctx = {0};
static mbed_error_ctx last_error_ctx = {0};
@ -44,39 +45,43 @@ static mbed_error_hook_t error_hook = NULL;
static mbed_error_status_t handle_error(mbed_error_status_t error_status, unsigned int error_value, const char *filename, int line_number, void *caller);
//Helper function to halt the system
static void mbed_halt_system(void)
static MBED_NORETURN void mbed_halt_system(void)
{
//If not in ISR context exit, otherwise spin on WFI
if (core_util_is_isr_active() || !core_util_are_interrupts_enabled()) {
// Prevent recursion if halt is called again during halt attempt - try
// something simple instead.
if (core_util_atomic_flag_test_and_set(&halt_in_progress)) {
core_util_critical_section_enter();
__DSB();
for (;;) {
__WFI();
__WFE(); // Not WFI, as don't want to wake for pending interrupts
}
} else {
//exit eventually calls mbed_die
exit(1);
}
//If in ISR context, call mbed_die directly
if (core_util_is_isr_active() || !core_util_are_interrupts_enabled()) {
mbed_die();
}
// In normal context, try orderly exit(1), which eventually calls mbed_die
exit(1);
}
WEAK void error(const char *format, ...)
WEAK MBED_NORETURN void error(const char *format, ...)
{
// Prevent recursion if error is called again
if (error_in_progress) {
return;
}
//Call handle_error/print_error_report permanently setting error_in_progress flag
handle_error(MBED_ERROR_UNKNOWN, 0, NULL, 0, MBED_CALLER_ADDR());
ERROR_REPORT(&last_error_ctx, "Fatal Run-time error", NULL, 0);
error_in_progress = 1;
// Prevent recursion if error is called again during store+print attempt
if (!core_util_atomic_flag_test_and_set(&error_in_progress)) {
handle_error(MBED_ERROR_UNKNOWN, 0, NULL, 0, MBED_CALLER_ADDR());
ERROR_REPORT(&last_error_ctx, "Fatal Run-time error", NULL, 0);
#ifndef NDEBUG
va_list arg;
va_start(arg, format);
mbed_error_vprintf(format, arg);
va_end(arg);
va_list arg;
va_start(arg, format);
mbed_error_vprintf(format, arg);
va_end(arg);
#endif
exit(1);
}
mbed_halt_system();
}
//Set an error status with the error handling system
@ -91,18 +96,6 @@ static mbed_error_status_t handle_error(mbed_error_status_t error_status, unsign
error_status = MBED_ERROR_INVALID_ARGUMENT;
}
//Prevent corruption by holding out other callers
//and we also need this until we remove the "error" call completely
while (error_in_progress == 1);
//Use critsect here, as we don't want inadvertant modification of this global variable
core_util_critical_section_enter();
error_in_progress = 1;
core_util_critical_section_exit();
//Increment error count
error_count++;
//Clear the context capturing buffer
memset(&current_error_ctx, 0, sizeof(mbed_error_ctx));
//Capture error information
@ -126,6 +119,12 @@ static mbed_error_status_t handle_error(mbed_error_status_t error_status, unsign
current_error_ctx.error_line_number = line_number;
#endif
//Prevent corruption by holding out other callers
core_util_critical_section_enter();
//Increment error count
error_count++;
//Capture the fist system error and store it
if (error_count == 1) { //first error
memcpy(&first_error_ctx, &current_error_ctx, sizeof(mbed_error_ctx));
@ -144,7 +143,7 @@ static mbed_error_status_t handle_error(mbed_error_status_t error_status, unsign
error_hook(&last_error_ctx);
}
error_in_progress = 0;
core_util_critical_section_exit();
return MBED_SUCCESS;
}
@ -170,25 +169,25 @@ int mbed_get_error_count(void)
return error_count;
}
//Sets a fatal error
//Sets a non-fatal error
mbed_error_status_t mbed_warning(mbed_error_status_t error_status, const char *error_msg, unsigned int error_value, const char *filename, int line_number)
{
return handle_error(error_status, error_value, filename, line_number, MBED_CALLER_ADDR());
}
//Sets a fatal error, this function is marked WEAK to be able to override this for some tests
WEAK mbed_error_status_t mbed_error(mbed_error_status_t error_status, const char *error_msg, unsigned int error_value, const char *filename, int line_number)
WEAK MBED_NORETURN mbed_error_status_t mbed_error(mbed_error_status_t error_status, const char *error_msg, unsigned int error_value, const char *filename, int line_number)
{
//set the error reported and then halt the system
if (MBED_SUCCESS != handle_error(error_status, error_value, filename, line_number, MBED_CALLER_ADDR())) {
return MBED_ERROR_FAILED_OPERATION;
// Prevent recursion if error is called again during store+print attempt
if (!core_util_atomic_flag_test_and_set(&error_in_progress)) {
//set the error reported
(void) handle_error(error_status, error_value, filename, line_number, MBED_CALLER_ADDR());
//On fatal errors print the error context/report
ERROR_REPORT(&last_error_ctx, error_msg, filename, line_number);
}
//On fatal errors print the error context/report
ERROR_REPORT(&last_error_ctx, error_msg, filename, line_number);
mbed_halt_system();
return MBED_ERROR_FAILED_OPERATION;
}
//Register an application defined callback with error handling

View File

@ -169,8 +169,7 @@ typedef int mbed_error_status_t;
* @param error_status mbed_error_status_t status to be set(See mbed_error_status_t enum above for available error status values).
* @param error_msg The error message to be printed out to STDIO/Serial.
* @param error_value Value associated with the error status. This would depend on error code/error scenario. Only available with MBED_ERROR1
* @return 0 or MBED_SUCCESS.
* MBED_ERROR_INVALID_ARGUMENT if called with invalid error status/codes
* @return Does not return
*
* @code
*
@ -872,7 +871,7 @@ typedef struct _mbed_error_ctx {
*
*/
void error(const char *format, ...);
MBED_NORETURN void error(const char *format, ...);
/**
* Call this Macro to generate a mbed_error_status_t value for a System error
@ -979,8 +978,7 @@ int mbed_get_error_count(void);
* @param error_value Value associated with the error status. This would depend on error code/error scenario.
* @param filename Name of the source file originating the error( Most callers can pass __FILE__ here ).
* @param line_number The line number of the source file originating the error( Most callers can pass __LINE__ here ) .
* @return 0 or MBED_SUCCESS.
* MBED_ERROR_INVALID_ARGUMENT if called with invalid error status/codes
* @return Does not return.
*
* @code
*
@ -990,7 +988,7 @@ int mbed_get_error_count(void);
*
* @note See MBED_WARNING/MBED_ERROR macros which provides a wrapper on this API
*/
mbed_error_status_t mbed_error(mbed_error_status_t error_status, const char *error_msg, unsigned int error_value, const char *filename, int line_number);
MBED_NORETURN mbed_error_status_t mbed_error(mbed_error_status_t error_status, const char *error_msg, unsigned int error_value, const char *filename, int line_number);
/**
* Registers an application defined error callback with the error handling system.

View File

@ -121,7 +121,7 @@ void mbed_mac_address(char *mac);
/** Cause the mbed to flash the BLOD (Blue LEDs Of Death) sequence
*/
void mbed_die(void);
MBED_NORETURN void mbed_die(void);
/** Print out an error message. This is typically called when
* handling a crash.

View File

@ -46,8 +46,8 @@ extern "C" {
*
* # Defined behavior
* * The lock is a counter
* * The lock can be locked up to USHRT_MAX - Verified by ::test_lock_eq_ushrt_max and ::test_lock_gt_ushrt_max
* * The lock has to be equally unlocked as locked - Verified by ::test_lone_unlock and ::test_lock_eq_ushrt_max
* * The lock can be locked up to USHRT_MAX - Verified by ::test_lock_eq_ushrt_max
* * The lock has to be equally unlocked as locked - Verified by ::test_lock_eq_ushrt_max
* * The function sleep_manager_lock_deep_sleep_internal() locks the automatic deep mode selection - Verified by ::test_lock_unlock
* * The function sleep_manager_unlock_deep_sleep_internal() unlocks the automatic deep mode selection - Verified by ::test_lock_unlock
* * The function sleep_manager_sleep_auto() chooses the sleep or deep sleep modes based on the lock - Verified by ::test_sleep_auto

View File

@ -22,6 +22,7 @@
#include "mbed_interface.h"
#include "RTX_Config.h"
#include "rtos/rtos_handlers.h"
#include "rtos/rtos_idle.h"
#ifdef RTE_Compiler_EventRecorder
#include "EventRecorder.h" // Keil::Compiler:Event Recorder
@ -30,8 +31,6 @@
#define EvtRtxThreadTerminate EventID(EventLevelAPI, 0xF2U, 0x1AU)
#endif
extern void rtos_idle_loop(void);
static void (*terminate_hook)(osThreadId_t id);
static void thread_terminate_hook(osThreadId_t id)
@ -48,9 +47,7 @@ void rtos_attach_thread_terminate_hook(void (*fptr)(osThreadId_t id))
__NO_RETURN void osRtxIdleThread(void *argument)
{
for (;;) {
rtos_idle_loop();
}
rtos_idle_loop();
}
__NO_RETURN uint32_t osRtxErrorNotify(uint32_t code, void *object_id)

View File

@ -28,9 +28,10 @@
#include "mbed_assert.h"
#include <new>
#include "rtx_os.h"
/* Everything in rtx_lib.h, and provided by this file, has C linkage */
extern "C" {
#include "rtx_lib.h"
}
using namespace mbed;
@ -151,10 +152,12 @@ void rtos_attach_idle_hook(void (*fptr)(void))
}
}
extern "C" void rtos_idle_loop(void)
MBED_NORETURN void rtos_idle_loop(void)
{
//Continuously call the idle hook function pointer
while (1) {
idle_hook_fptr();
}
}
} // extern "C"

View File

@ -25,6 +25,7 @@
#ifndef RTOS_IDLE_H
#define RTOS_IDLE_H
#include "mbed_toolchain.h"
#include <stddef.h>
#ifdef __cplusplus
@ -41,6 +42,10 @@ extern "C" {
@param fptr Hook function pointer.
*/
void rtos_attach_idle_hook(void (*fptr)(void));
/** @private */
MBED_NORETURN void rtos_idle_loop(void);
/** @}*/
#ifdef __cplusplus