From 957f2404507a007807c8987d78d6abf4270df763 Mon Sep 17 00:00:00 2001 From: Deepika Date: Mon, 15 Oct 2018 14:07:42 -0500 Subject: [PATCH 1/4] Remove deep sleep lock from wait_ms API's updated as: 1. wait(float) calls wait_ms for >=0.01s and not in interrupt, else wait_us. 2. wait_ms() is just the thread sleep and doesn't lock hardware sleep. In order to have backward compatibility, if used in ISR `wait_us` is called if MBED_TRAP_ERRORS_ENABLED is false 3. wait_us() is a ticker-based wait, always spinning. --- platform/mbed_wait_api.h | 16 ++++++------ platform/mbed_wait_api_rtos.cpp | 44 +++++++++++++++++++++++++-------- 2 files changed, 42 insertions(+), 18 deletions(-) diff --git a/platform/mbed_wait_api.h b/platform/mbed_wait_api.h index e97400f46a..19f446ecd0 100644 --- a/platform/mbed_wait_api.h +++ b/platform/mbed_wait_api.h @@ -55,9 +55,9 @@ extern "C" { * @param s number of seconds to wait * * @note - * If the RTOS is present, this function always spins to get the exact number of microseconds, - * which potentially affects power (such as preventing deep sleep) and multithread performance. - * You can avoid it by using ThisThread::sleep_for(). + * If the RTOS is present, this function spins to get the exact number of microseconds for + * usec precision upto 10msec. If delay is larger then 10msec and not in ISR, it is same as + * `wait_ms`. `wait_us` and `wait_ms` are recommended over `wait` */ void wait(float s); @@ -66,9 +66,8 @@ void wait(float s); * @param ms the whole number of milliseconds to wait * * @note - * If the RTOS is present, this function always spins to get the exact number of microseconds, - * which potentially affects power (such as preventing deep sleep) and multithread performance. - * You can avoid it by using ThisThread::sleep_for(). + * If the RTOS is present, it is same as CMSIS osDelay() + * Not callable from interrupts, doesn't lock hardware sleep. */ void wait_ms(int ms); @@ -77,8 +76,9 @@ void wait_ms(int ms); * @param us the whole number of microseconds to wait * * @note - * If the RTOS is present, this function always spins to get the exact number of microseconds, - * which potentially affects power (such as preventing deep sleep) and multithread performance. + * This function always spins to get the exact number of microseconds. + * If RTOS is present, this will affect power (prevents deep sleep) and + * multithread performance, hence spinning for milli-sec wait is not recommended. */ void wait_us(int us); diff --git a/platform/mbed_wait_api_rtos.cpp b/platform/mbed_wait_api_rtos.cpp index 2e34d0f257..752536c797 100644 --- a/platform/mbed_wait_api_rtos.cpp +++ b/platform/mbed_wait_api_rtos.cpp @@ -23,21 +23,18 @@ #include "rtos/rtos.h" #include "platform/mbed_critical.h" #include "platform/mbed_power_mgmt.h" +#include "platform/mbed_error.h" +#include "rtos/ThisThread.h" void wait(float s) { - wait_us(s * 1000000.0f); -} + if ((s >= 0.01f) && core_util_are_interrupts_enabled()) { + wait_ms(s * 1000.0f); + return; + } -void wait_ms(int ms) -{ - wait_us(ms * 1000); -} - -void wait_us(int us) -{ + uint32_t us = (s * 1000000.0f); const ticker_data_t *const ticker = get_us_ticker_data(); - uint32_t start = ticker_read(ticker); if ((us >= 1000) && core_util_are_interrupts_enabled()) { // Use the RTOS to wait for millisecond delays if possible @@ -50,5 +47,32 @@ void wait_us(int us) while ((ticker_read(ticker) - start) < (uint32_t)us); } +/* The actual time delay may be up to one timer tick less - 1 msec */ +void wait_ms(int ms) +{ + if (core_util_is_isr_active() || !core_util_are_interrupts_enabled()) { +#if defined(MBED_TRAP_ERRORS_ENABLED) && MBED_TRAP_ERRORS_ENABLED + MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_INVALID_OPERATION), + "Deprecated behavior: milli-sec delay should not be used in interrupt.\n"); +#else + wait_us(ms * 1000); +#endif + } else { + rtos::ThisThread::sleep_for(ms); + } +} + +/* The actual time delay may be 1 less usec */ +void wait_us(int us) +{ + if (us > 10000) { + MBED_WARNING(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_UNKNOWN), + "wait_us blocks deep sleep, wait_ms recommended for long delays\n"); + } + const ticker_data_t *const ticker = get_us_ticker_data(); + uint32_t start = ticker_read(ticker); + while ((ticker_read(ticker) - start) < (uint32_t)us); +} + #endif // #if MBED_CONF_RTOS_PRESENT From f5e28fe729402de06aa940998097c14f6682c440 Mon Sep 17 00:00:00 2001 From: Amanda Butler Date: Tue, 30 Oct 2018 10:06:30 -0500 Subject: [PATCH 2/4] Edit mbed_wait_api.h Standardize unit of time measurements, and change passive to active voice. --- platform/mbed_wait_api.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform/mbed_wait_api.h b/platform/mbed_wait_api.h index 19f446ecd0..ad1293cbd3 100644 --- a/platform/mbed_wait_api.h +++ b/platform/mbed_wait_api.h @@ -56,8 +56,8 @@ extern "C" { * * @note * If the RTOS is present, this function spins to get the exact number of microseconds for - * usec precision upto 10msec. If delay is larger then 10msec and not in ISR, it is same as - * `wait_ms`. `wait_us` and `wait_ms` are recommended over `wait` + * microsecond precision up to 10 milliseconds. If delay is larger than 10 milliseconds and not in ISR, it is the same as + * `wait_ms`. We recommend `wait_us` and `wait_ms` over `wait`. */ void wait(float s); @@ -77,8 +77,8 @@ void wait_ms(int ms); * * @note * This function always spins to get the exact number of microseconds. - * If RTOS is present, this will affect power (prevents deep sleep) and - * multithread performance, hence spinning for milli-sec wait is not recommended. + * If RTOS is present, this will affect power (by preventing deep sleep) and + * multithread performance. Therefore, spinning for millisecond wait is not recommended. */ void wait_us(int us); From 5a87f048726afb85dd8fe4da3a95f59ecff06e7b Mon Sep 17 00:00:00 2001 From: Deepika Bhavnani Date: Tue, 30 Oct 2018 13:07:59 -0500 Subject: [PATCH 3/4] Update doc for wait_ms --- platform/mbed_wait_api.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/mbed_wait_api.h b/platform/mbed_wait_api.h index ad1293cbd3..5803245db7 100644 --- a/platform/mbed_wait_api.h +++ b/platform/mbed_wait_api.h @@ -66,7 +66,7 @@ void wait(float s); * @param ms the whole number of milliseconds to wait * * @note - * If the RTOS is present, it is same as CMSIS osDelay() + * If the RTOS is present, it calls ThisThread::sleep_for() which is same as CMSIS osDelay() * Not callable from interrupts, doesn't lock hardware sleep. */ void wait_ms(int ms); From c58c80e0421d02c2b0a1dfd5f52c60856753e510 Mon Sep 17 00:00:00 2001 From: Amanda Butler Date: Wed, 31 Oct 2018 11:12:35 -0500 Subject: [PATCH 4/4] Make minor copy edits to mbed_wait_api.h Make minor edits to existing text. --- platform/mbed_wait_api.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/mbed_wait_api.h b/platform/mbed_wait_api.h index 5803245db7..92a380ed9d 100644 --- a/platform/mbed_wait_api.h +++ b/platform/mbed_wait_api.h @@ -66,8 +66,8 @@ void wait(float s); * @param ms the whole number of milliseconds to wait * * @note - * If the RTOS is present, it calls ThisThread::sleep_for() which is same as CMSIS osDelay() - * Not callable from interrupts, doesn't lock hardware sleep. + * If the RTOS is present, it calls ThisThread::sleep_for(), which is same as CMSIS osDelay(). + * You can't call this from interrupts, and it doesn't lock hardware sleep. */ void wait_ms(int ms);