From 28b770510ce9932f22ad1d82de9133d2feaababe Mon Sep 17 00:00:00 2001 From: Kevin Bracey Date: Thu, 14 Mar 2019 13:33:04 +0200 Subject: [PATCH 01/17] CPU stats: strip more when disabled --- platform/mbed_sleep_manager.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/platform/mbed_sleep_manager.c b/platform/mbed_sleep_manager.c index 6626039237..01ce380a39 100644 --- a/platform/mbed_sleep_manager.c +++ b/platform/mbed_sleep_manager.c @@ -25,6 +25,7 @@ #include "hal/us_ticker_api.h" #include "hal/lp_ticker_api.h" +#include "platform/mbed_wait_api.h" #include @@ -32,18 +33,18 @@ // deep sleep locking counter. A target is allowed to deep sleep if counter == 0 static uint16_t deep_sleep_lock = 0U; +#if defined(MBED_CPU_STATS_ENABLED) && DEVICE_LPTICKER static us_timestamp_t sleep_time = 0; static us_timestamp_t deep_sleep_time = 0; -#if defined(MBED_CPU_STATS_ENABLED) && DEVICE_LPTICKER -static ticker_data_t *sleep_ticker = NULL; +static const ticker_data_t *sleep_ticker = NULL; #endif static inline us_timestamp_t read_us(void) { #if defined(MBED_CPU_STATS_ENABLED) && DEVICE_LPTICKER if (NULL == sleep_ticker) { - sleep_ticker = (ticker_data_t *)get_lp_ticker_data(); + sleep_ticker = get_lp_ticker_data(); } return ticker_read_us(sleep_ticker); #else @@ -53,7 +54,11 @@ static inline us_timestamp_t read_us(void) us_timestamp_t mbed_time_idle(void) { +#if defined(MBED_CPU_STATS_ENABLED) && DEVICE_LPTICKER return (sleep_time + deep_sleep_time); +#else + return 0; +#endif } us_timestamp_t mbed_uptime(void) @@ -63,12 +68,20 @@ us_timestamp_t mbed_uptime(void) us_timestamp_t mbed_time_sleep(void) { +#if defined(MBED_CPU_STATS_ENABLED) && DEVICE_LPTICKER return sleep_time; +#else + return 0; +#endif } us_timestamp_t mbed_time_deepsleep(void) { +#if defined(MBED_CPU_STATS_ENABLED) && DEVICE_LPTICKER return deep_sleep_time; +#else + return 0; +#endif } #ifdef MBED_SLEEP_TRACING_ENABLED @@ -211,27 +224,33 @@ void sleep_manager_sleep_auto(void) sleep_tracker_print_stats(); #endif core_util_critical_section_enter(); +#if defined(MBED_CPU_STATS_ENABLED) && DEVICE_LPTICKER us_timestamp_t start = read_us(); bool deep = false; +#endif // debug profile should keep debuggers attached, no deep sleep allowed #ifdef MBED_DEBUG hal_sleep(); #else if (sleep_manager_can_deep_sleep()) { +#if defined(MBED_CPU_STATS_ENABLED) && DEVICE_LPTICKER deep = true; +#endif hal_deepsleep(); } else { hal_sleep(); } #endif +#if defined(MBED_CPU_STATS_ENABLED) && DEVICE_LPTICKER us_timestamp_t end = read_us(); if (true == deep) { deep_sleep_time += end - start; } else { sleep_time += end - start; } +#endif core_util_critical_section_exit(); } From 20451082c18b3185ac21e9161f3296cb2147624e Mon Sep 17 00:00:00 2001 From: Kevin Bracey Date: Wed, 22 May 2019 12:20:34 +0300 Subject: [PATCH 02/17] Move SysTimer to platform, for non-RTOS use --- TESTS/mbedmicro-rtos-mbed/systimer/main.cpp | 4 ++-- {rtos/TARGET_CORTEX => platform}/SysTimer.cpp | 4 ++-- {rtos/TARGET_CORTEX => platform}/SysTimer.h | 2 +- rtos/LICENSE.md | 2 -- rtos/TARGET_CORTEX/mbed_rtx_idle.cpp | 10 +++++----- 5 files changed, 10 insertions(+), 12 deletions(-) rename {rtos/TARGET_CORTEX => platform}/SysTimer.cpp (98%) rename {rtos/TARGET_CORTEX => platform}/SysTimer.h (99%) diff --git a/TESTS/mbedmicro-rtos-mbed/systimer/main.cpp b/TESTS/mbedmicro-rtos-mbed/systimer/main.cpp index 883be87ae3..b2ca9238f7 100644 --- a/TESTS/mbedmicro-rtos-mbed/systimer/main.cpp +++ b/TESTS/mbedmicro-rtos-mbed/systimer/main.cpp @@ -26,7 +26,7 @@ extern "C" { #include "rtx_lib.h" } -#include "rtos/TARGET_CORTEX/SysTimer.h" +#include "platform/SysTimer.h" #define TEST_TICKS 42UL #define DELAY_DELTA_US 2500ULL @@ -44,7 +44,7 @@ using namespace utest::v1; const us_timestamp_t DELAY_US = 1000000ULL * TEST_TICKS / OS_TICK_FREQ; // Override the handler() -- the SysTick interrupt must not be set as pending by the test code. -class SysTimerTest: public rtos::internal::SysTimer { +class SysTimerTest: public mbed::internal::SysTimer { private: Semaphore _sem; virtual void handler() diff --git a/rtos/TARGET_CORTEX/SysTimer.cpp b/platform/SysTimer.cpp similarity index 98% rename from rtos/TARGET_CORTEX/SysTimer.cpp rename to platform/SysTimer.cpp index c58763d451..fc56d3f9b3 100644 --- a/rtos/TARGET_CORTEX/SysTimer.cpp +++ b/platform/SysTimer.cpp @@ -19,7 +19,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#include "rtos/TARGET_CORTEX/SysTimer.h" +#include "platform/SysTimer.h" #if MBED_TICKLESS @@ -55,7 +55,7 @@ extern "C" IRQn_Type mbed_get_m0_tick_irqn(void); extern "C" IRQn_ID_t mbed_get_a9_tick_irqn(void); #endif -namespace rtos { +namespace mbed { namespace internal { SysTimer::SysTimer() : diff --git a/rtos/TARGET_CORTEX/SysTimer.h b/platform/SysTimer.h similarity index 99% rename from rtos/TARGET_CORTEX/SysTimer.h rename to platform/SysTimer.h index 653ffbe895..9e132d0e3d 100644 --- a/rtos/TARGET_CORTEX/SysTimer.h +++ b/platform/SysTimer.h @@ -27,7 +27,7 @@ #include "platform/NonCopyable.h" #include "drivers/TimerEvent.h" -namespace rtos { +namespace mbed { namespace internal { /** diff --git a/rtos/LICENSE.md b/rtos/LICENSE.md index 8cf3faca88..a99cc40e78 100644 --- a/rtos/LICENSE.md +++ b/rtos/LICENSE.md @@ -7,8 +7,6 @@ Files licensed under MIT: - TARGET_CORTEX/mbed_rtos_storage.h - TARGET_CORTEX/mbed_rtx_conf.h - TARGET_CORTEX/mbed_rtx_idle.cpp -- TARGET_CORTEX/SysTimer.h -- TARGET_CORTEX/SysTimer.cpp - ConditionVariable.cpp - ConditionVariable.h - EventFlags.cpp diff --git a/rtos/TARGET_CORTEX/mbed_rtx_idle.cpp b/rtos/TARGET_CORTEX/mbed_rtx_idle.cpp index 7504ac71b9..d602126dae 100644 --- a/rtos/TARGET_CORTEX/mbed_rtx_idle.cpp +++ b/rtos/TARGET_CORTEX/mbed_rtx_idle.cpp @@ -46,10 +46,10 @@ extern "C" { #error Low power ticker required when MBED_CONF_TARGET_TICKLESS_FROM_US_TICKER is false #endif -#include "rtos/TARGET_CORTEX/SysTimer.h" +#include "platform/SysTimer.h" - static rtos::internal::SysTimer *os_timer; - static uint64_t os_timer_data[sizeof(rtos::internal::SysTimer) / 8]; + static mbed::internal::SysTimer *os_timer; + static uint64_t os_timer_data[sizeof(mbed::internal::SysTimer) / 8]; // Enable System Timer. void OS_Tick_Enable(void) @@ -57,9 +57,9 @@ extern "C" { // Do not use SingletonPtr since this relies on the RTOS if (NULL == os_timer) { #if MBED_CONF_TARGET_TICKLESS_FROM_US_TICKER - os_timer = new (os_timer_data) rtos::internal::SysTimer(get_us_ticker_data()); + os_timer = new (os_timer_data) mbed::internal::SysTimer(get_us_ticker_data()); #else - os_timer = new (os_timer_data) rtos::internal::SysTimer(get_lp_ticker_data()); + os_timer = new (os_timer_data) mbed::internal::SysTimer(get_lp_ticker_data()); #endif os_timer->setup_irq(); } From a1e1ab61a4b5583659c9e7473058b3606f349ffa Mon Sep 17 00:00:00 2001 From: Kevin Bracey Date: Wed, 22 May 2019 12:21:33 +0300 Subject: [PATCH 03/17] Switch SysTimer license to Apache --- platform/SysTimer.cpp | 27 +++++++++++---------------- platform/SysTimer.h | 27 +++++++++++---------------- 2 files changed, 22 insertions(+), 32 deletions(-) diff --git a/platform/SysTimer.cpp b/platform/SysTimer.cpp index fc56d3f9b3..f258ef534e 100644 --- a/platform/SysTimer.cpp +++ b/platform/SysTimer.cpp @@ -1,23 +1,18 @@ /* mbed Microcontroller Library - * Copyright (c) 2006-2012 ARM Limited + * Copyright (c) 2006-2019 ARM Limited + * SPDX-License-Identifier: Apache-2.0 * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. + * http://www.apache.org/licenses/LICENSE-2.0 * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ #include "platform/SysTimer.h" diff --git a/platform/SysTimer.h b/platform/SysTimer.h index 9e132d0e3d..af712e86a7 100644 --- a/platform/SysTimer.h +++ b/platform/SysTimer.h @@ -1,23 +1,18 @@ /* mbed Microcontroller Library - * Copyright (c) 2006-2012 ARM Limited + * Copyright (c) 2006-2019 ARM Limited + * SPDX-License-Identifier: Apache-2.0 * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. + * http://www.apache.org/licenses/LICENSE-2.0 * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ #ifndef MBED_SYS_TIMER_H #define MBED_SYS_TIMER_H From 89eba7303f37565bb252bf11157100d9ffa22a21 Mon Sep 17 00:00:00 2001 From: Kevin Bracey Date: Fri, 18 Jan 2019 14:10:33 +0200 Subject: [PATCH 04/17] Timed sleep rework --- TESTS/mbedmicro-rtos-mbed/systimer/main.cpp | 107 +++--- platform/SysTimer.cpp | 369 ++++++++++++++------ platform/SysTimer.h | 190 ++++++++-- platform/mbed_os_timer.cpp | 252 +++++++++++++ platform/mbed_os_timer.h | 64 ++++ rtos/TARGET_CORTEX/mbed_rtx_idle.cpp | 101 +++--- 6 files changed, 832 insertions(+), 251 deletions(-) create mode 100644 platform/mbed_os_timer.cpp create mode 100644 platform/mbed_os_timer.h diff --git a/TESTS/mbedmicro-rtos-mbed/systimer/main.cpp b/TESTS/mbedmicro-rtos-mbed/systimer/main.cpp index b2ca9238f7..44492f1ec5 100644 --- a/TESTS/mbedmicro-rtos-mbed/systimer/main.cpp +++ b/TESTS/mbedmicro-rtos-mbed/systimer/main.cpp @@ -13,9 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef MBED_TICKLESS -#error [NOT_SUPPORTED] Tickless mode not supported for this target. -#endif #include "mbed.h" #include "greentea-client/test_env.h" @@ -28,7 +25,8 @@ extern "C" { } #include "platform/SysTimer.h" -#define TEST_TICKS 42UL +#define TEST_TICKS 42 +#define TEST_TICK_US (TEST_TICKS * 1000) #define DELAY_DELTA_US 2500ULL /* Use a specific delta value for deep sleep, as entry/exit adds up extra latency. @@ -40,29 +38,29 @@ extern "C" { #endif using namespace utest::v1; +using mbed::internal::SysTimer; -const us_timestamp_t DELAY_US = 1000000ULL * TEST_TICKS / OS_TICK_FREQ; +const us_timestamp_t DELAY_US = TEST_TICK_US; -// Override the handler() -- the SysTick interrupt must not be set as pending by the test code. -class SysTimerTest: public mbed::internal::SysTimer { +// The SysTick interrupt must not be set as pending by the test code. +template +class SysTimerTest: public SysTimer { private: Semaphore _sem; virtual void handler() { - core_util_critical_section_enter(); - _increment_tick(); - core_util_critical_section_exit(); _sem.release(); + SysTimer::handler(); } public: SysTimerTest() : - SysTimer(), _sem(0, 1) + SysTimer(), _sem(0, 1) { } SysTimerTest(const ticker_data_t *data) : - SysTimer(data), _sem(0, 1) + SysTimer(data), _sem(0, 1) { } @@ -153,7 +151,7 @@ void mock_ticker_reset() */ void test_created_with_zero_tick_count(void) { - SysTimerTest st; + SysTimerTest<1000> st; TEST_ASSERT_EQUAL_UINT32(0, st.get_tick()); } @@ -164,26 +162,27 @@ void test_created_with_zero_tick_count(void) * Then the tick count is not updated * When @a suspend and @a resume methods are called again after a delay * Then the tick count is updated - * and the number of ticks incremented is equal TEST_TICKS - 1 + * and the number of ticks incremented is equal TEST_TICKS * When @a suspend and @a resume methods are called again without a delay * Then the tick count is not updated */ void test_update_tick(void) { mock_ticker_reset(); - SysTimerTest st(&mock_ticker_data); - st.suspend(TEST_TICKS * 2); - TEST_ASSERT_EQUAL_UINT32(0, st.resume()); + SysTimerTest<1000> st(&mock_ticker_data); + st.set_wake_time(st.get_tick() + TEST_TICKS * 2); + st.cancel_wake(); TEST_ASSERT_EQUAL_UINT32(0, st.get_tick()); - st.suspend(TEST_TICKS * 2); + st.set_wake_time(st.get_tick() + TEST_TICKS * 2); mock_ticker_timestamp = DELAY_US; - TEST_ASSERT_EQUAL_UINT32(TEST_TICKS - 1, st.resume()); - TEST_ASSERT_EQUAL_UINT32(TEST_TICKS - 1, st.get_tick()); + st.cancel_wake(); + TEST_ASSERT_EQUAL_UINT32(TEST_TICKS, st.update_and_get_tick()); + TEST_ASSERT_EQUAL_UINT32(TEST_TICKS, st.get_tick()); - st.suspend(TEST_TICKS * 2); - TEST_ASSERT_EQUAL_UINT32(0, st.resume()); - TEST_ASSERT_EQUAL_UINT32(TEST_TICKS - 1, st.get_tick()); + st.set_wake_time(st.get_tick() + TEST_TICKS * 2); + st.cancel_wake(); + TEST_ASSERT_EQUAL_UINT32(TEST_TICKS, st.get_tick()); } /** Test get_time returns correct time @@ -195,7 +194,7 @@ void test_update_tick(void) void test_get_time(void) { mock_ticker_reset(); - SysTimerTest st(&mock_ticker_data); + SysTimerTest<1000> st(&mock_ticker_data); us_timestamp_t t1 = st.get_time(); mock_ticker_timestamp = DELAY_US; @@ -212,9 +211,9 @@ void test_get_time(void) */ void test_cancel_tick(void) { - SysTimerTest st; + SysTimerTest st; st.cancel_tick(); - st.schedule_tick(TEST_TICKS); + st.start_tick(); st.cancel_tick(); bool acquired = st.sem_try_acquire((DELAY_US + DELAY_DELTA_US) / 1000ULL); @@ -222,50 +221,41 @@ void test_cancel_tick(void) TEST_ASSERT_EQUAL_UINT32(0, st.get_tick()); } -/** Test schedule zero - * - * Given a SysTimer - * When a tick is scheduled with delta = 0 ticks - * Then the handler is called instantly - */ -void test_schedule_zero(void) -{ - SysTimerTest st; - - st.schedule_tick(0UL); - bool acquired = st.sem_try_acquire(0); - TEST_ASSERT_TRUE(acquired); -} - -/** Test handler called once +/** Test handler called twice * * Given a SysTimer with a tick scheduled with delta = TEST_TICKS * When the handler is called * Then the tick count is incremented by 1 * and elapsed time is equal 1000000ULL * TEST_TICKS / OS_TICK_FREQ; * When more time elapses - * Then the handler is not called again + * Repeat a second time. */ -void test_handler_called_once(void) +void test_handler_called_twice(void) { - SysTimerTest st; - st.schedule_tick(TEST_TICKS); + SysTimerTest st; us_timestamp_t t1 = st.get_time(); bool acquired = st.sem_try_acquire(0); TEST_ASSERT_FALSE(acquired); + st.start_tick(); // Wait in a busy loop to prevent entering sleep or deepsleep modes. - while (!acquired) { + do { acquired = st.sem_try_acquire(0); - } + } while (!acquired); us_timestamp_t t2 = st.get_time(); TEST_ASSERT_TRUE(acquired); TEST_ASSERT_EQUAL_UINT32(1, st.get_tick()); TEST_ASSERT_UINT64_WITHIN(DELAY_DELTA_US, DELAY_US, t2 - t1); - acquired = st.sem_try_acquire((DELAY_US + DELAY_DELTA_US) / 1000ULL); - TEST_ASSERT_FALSE(acquired); - TEST_ASSERT_EQUAL_UINT32(1, st.get_tick()); + // Wait in a busy loop to prevent entering sleep or deepsleep modes. + do { + acquired = st.sem_try_acquire(0); + } while (!acquired); + t2 = st.get_time(); + TEST_ASSERT_TRUE(acquired); + TEST_ASSERT_EQUAL_UINT32(2, st.get_tick()); + TEST_ASSERT_UINT64_WITHIN(DELAY_DELTA_US, DELAY_US * 2, t2 - t1); + st.cancel_tick(); } #if DEVICE_SLEEP @@ -281,16 +271,17 @@ void test_handler_called_once(void) void test_sleep(void) { Timer timer; - SysTimerTest st; + SysTimerTest st; sleep_manager_lock_deep_sleep(); timer.start(); - st.schedule_tick(TEST_TICKS); + st.start_tick(); TEST_ASSERT_FALSE_MESSAGE(sleep_manager_can_deep_sleep(), "Deep sleep should be disallowed"); st.sem_acquire(); timer.stop(); + st.cancel_tick(); sleep_manager_unlock_deep_sleep(); TEST_ASSERT_UINT64_WITHIN(DELAY_DELTA_US, DELAY_US, timer.read_high_resolution_us()); @@ -319,13 +310,14 @@ void test_deepsleep(void) wait_ms(10); // Regular Timer might be disabled during deepsleep. LowPowerTimer lptimer; - SysTimerTest st; + SysTimerTest st; lptimer.start(); - st.schedule_tick(TEST_TICKS); + st.start_tick(); TEST_ASSERT_TRUE_MESSAGE(sleep_manager_can_deep_sleep_test_check(), "Deep sleep should be allowed"); st.sem_acquire(); lptimer.stop(); + st.cancel_tick(); TEST_ASSERT_UINT64_WITHIN(DEEP_SLEEP_DELAY_DELTA_US, DELAY_US, lptimer.read_high_resolution_us()); } @@ -334,7 +326,7 @@ void test_deepsleep(void) utest::v1::status_t test_setup(const size_t number_of_cases) { - GREENTEA_SETUP(5, "default_auto"); + GREENTEA_SETUP(15, "default_auto"); return verbose_test_setup_handler(number_of_cases); } @@ -343,8 +335,7 @@ Case cases[] = { Case("Tick count is updated correctly", test_update_tick), Case("Time is updated correctly", test_get_time), Case("Tick can be cancelled", test_cancel_tick), - Case("Schedule zero ticks", test_schedule_zero), - Case("Handler called once", test_handler_called_once), + Case("Handler called twice", test_handler_called_twice), #if DEVICE_SLEEP Case("Wake up from sleep", test_sleep), #if DEVICE_LPTICKER && !MBED_CONF_TARGET_TICKLESS_FROM_US_TICKER diff --git a/platform/SysTimer.cpp b/platform/SysTimer.cpp index f258ef534e..63d1098f04 100644 --- a/platform/SysTimer.cpp +++ b/platform/SysTimer.cpp @@ -14,29 +14,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "platform/SysTimer.h" - -#if MBED_TICKLESS #include "hal/us_ticker_api.h" #include "hal/lp_ticker_api.h" +#include "mbed_atomic.h" #include "mbed_critical.h" #include "mbed_assert.h" -#if defined(TARGET_CORTEX_A) -#include "rtx_core_ca.h" -#else//Cortex-M -#include "rtx_core_cm.h" -#endif +#include "platform/mbed_power_mgmt.h" +#include "platform/CriticalSectionLock.h" +#include "platform/SysTimer.h" extern "C" { +#if MBED_CONF_RTOS_PRESENT #include "rtx_lib.h" -#if defined(TARGET_CORTEX_A) -#include "irq_ctrl.h" #endif } -#define US_IN_TICK (1000000 / OS_TICK_FREQ) -MBED_STATIC_ASSERT(1000000 % OS_TICK_FREQ == 0, "OS_TICK_FREQ must be a divisor of 1000000 for correct tick calculations"); - #if (defined(NO_SYSTICK)) /** * Return an IRQ number that can be used in the absence of SysTick @@ -53,125 +45,263 @@ extern "C" IRQn_ID_t mbed_get_a9_tick_irqn(void); namespace mbed { namespace internal { -SysTimer::SysTimer() : +template +SysTimer::SysTimer() : #if DEVICE_LPTICKER TimerEvent(get_lp_ticker_data()), #else TimerEvent(get_us_ticker_data()), #endif - _time_us(0), _tick(0) + _time_us(ticker_read_us(_ticker_data)), + _tick(0), + _unacknowledged_ticks(0), + _wake_time_set(false), + _wake_time_passed(false), + _ticking(false), + _deep_sleep_locked(false) { - _time_us = ticker_read_us(_ticker_data); - _suspend_time_passed = true; - _suspended = false; -} - -SysTimer::SysTimer(const ticker_data_t *data) : - TimerEvent(data), _time_us(0), _tick(0) -{ - _time_us = ticker_read_us(_ticker_data); - _suspend_time_passed = true; - _suspended = false; -} - -void SysTimer::setup_irq() -{ -#if (defined(NO_SYSTICK) && !defined (TARGET_CORTEX_A)) - NVIC_SetVector(mbed_get_m0_tick_irqn(), (uint32_t)SysTick_Handler); - NVIC_SetPriority(mbed_get_m0_tick_irqn(), 0xFF); /* RTOS requires lowest priority */ - NVIC_EnableIRQ(mbed_get_m0_tick_irqn()); -#else - // Ensure SysTick has the correct priority as it is still used - // to trigger software interrupts on each tick. The period does - // not matter since it will never start counting. - OS_Tick_Setup(osRtxConfig.tick_freq, OS_TICK_HANDLER); -#endif -} - -void SysTimer::suspend(uint32_t ticks) -{ - // Remove ensures serialized access to SysTimer by stopping timer interrupt - remove(); - - _suspend_time_passed = false; - _suspended = true; - - schedule_tick(ticks); -} - -bool SysTimer::suspend_time_passed() -{ - return _suspend_time_passed; -} - -uint32_t SysTimer::resume() -{ - // Remove ensures serialized access to SysTimer by stopping timer interrupt - remove(); - - _suspended = false; - _suspend_time_passed = true; - - uint64_t elapsed_ticks = (ticker_read_us(_ticker_data) - _time_us) / US_IN_TICK; - if (elapsed_ticks > 0) { - // Don't update to the current tick. Instead, update to the - // previous tick and let the SysTick handler increment it - // to the current value. This allows scheduling restart - // successfully after the OS is resumed. - elapsed_ticks--; + if (!_ticker_data->interface->runs_in_deep_sleep) { + sleep_manager_lock_deep_sleep(); } - _time_us += elapsed_ticks * US_IN_TICK; - _tick += elapsed_ticks; - - return elapsed_ticks; } -void SysTimer::schedule_tick(uint32_t delta) +template +SysTimer::SysTimer(const ticker_data_t *data) : + TimerEvent(data), + _time_us(ticker_read_us(_ticker_data)), + _tick(0), + _unacknowledged_ticks(0), + _wake_time_set(false), + _wake_time_passed(false), + _ticking(false), + _deep_sleep_locked(false) { - core_util_critical_section_enter(); - - insert_absolute(_time_us + delta * US_IN_TICK); - - core_util_critical_section_exit(); + if (!_ticker_data->interface->runs_in_deep_sleep) { + sleep_manager_lock_deep_sleep(); + } } -void SysTimer::cancel_tick() +template +SysTimer::~SysTimer() +{ + cancel_tick(); + cancel_wake(); + if (!_ticker_data->interface->runs_in_deep_sleep) { + sleep_manager_unlock_deep_sleep(); + } +} + +template +void SysTimer::set_wake_time(uint64_t at) +{ + // SysTimer must not be active - we must be in suspend state + MBED_ASSERT(!_ticking); + + // There is a potential race here, when called from outside + // a critical section. See function documentation for notes on + // handling it. + if (core_util_atomic_load_bool(&_wake_time_set)) { + return; + } + + // Analyse the timers + if (update_and_get_tick() >= at) { + _wake_time_passed = true; + return; + } + + uint64_t ticks_to_sleep = at - _tick; + uint64_t wake_time = at * US_IN_TICK; + + /* Set this first, before attaching the interrupt that can unset it */ + _wake_time_set = true; + _wake_time_passed = false; + + /* If deep sleep is unlocked, and we have enough time, let's go for it */ + if (MBED_CONF_TARGET_DEEP_SLEEP_LATENCY > 0 && + ticks_to_sleep > MBED_CONF_TARGET_DEEP_SLEEP_LATENCY && + sleep_manager_can_deep_sleep()) { + /* Schedule the wake up interrupt early, allowing for the deep sleep latency */ + _wake_early = true; + insert_absolute(wake_time - MBED_CONF_TARGET_DEEP_SLEEP_LATENCY * US_IN_TICK); + } else { + /* Otherwise, we'll set up for shallow sleep at the precise time. + * To make absolutely sure it's shallow so we don't incur the latency, + * take our own lock, to avoid a race on a thread unlocking it. + */ + _wake_early = false; + if (MBED_CONF_TARGET_DEEP_SLEEP_LATENCY > 0 && !_deep_sleep_locked) { + _deep_sleep_locked = true; + sleep_manager_lock_deep_sleep(); + } + insert_absolute(wake_time); + } +} + +template +void SysTimer::cancel_wake() +{ + MBED_ASSERT(!_ticking); + // Remove ensures serialized access to SysTimer by stopping timer interrupt + remove(); + + _wake_time_set = false; + _wake_time_passed = false; + + if (_deep_sleep_locked) { + _deep_sleep_locked = false; + sleep_manager_unlock_deep_sleep(); + } +} + +template +uint64_t SysTimer::_elapsed_ticks() const +{ + uint64_t elapsed_us = ticker_read_us(_ticker_data) - _time_us; + if (elapsed_us < US_IN_TICK) { + return 0; + } else if (elapsed_us < 2 * US_IN_TICK) { + return 1; + } else if (elapsed_us <= 0xFFFFFFFF) { + // Fast common case avoiding 64-bit division + return (uint32_t) elapsed_us / US_IN_TICK; + } else { + return elapsed_us / US_IN_TICK; + } +} + +template +void SysTimer::start_tick() +{ + _ticking = true; + if (_unacknowledged_ticks > 0) { + _set_irq_pending(); + } + _schedule_tick(); +} + +template +void SysTimer::_schedule_tick() +{ + insert_absolute(_time_us + US_IN_TICK); +} + +template +void SysTimer::acknowledge_tick() +{ + // Try to avoid missed ticks if OS's IRQ level is not keeping + // up with our handler. + // 8-bit counter to save space, and also make sure it we don't + // try TOO hard to resync if something goes really awry - + // resync will reset if the count hits 256. + if (core_util_atomic_decr_u8(&_unacknowledged_ticks, 1) > 0) { + _set_irq_pending(); + } +} + +template +void SysTimer::cancel_tick() { // Underlying call is interrupt safe remove(); + _ticking = false; + + _clear_irq_pending(); } -uint32_t SysTimer::get_tick() +template +uint64_t SysTimer::get_tick() const { - return _tick & 0xFFFFFFFF; + // Atomic is necessary as this can be called from any foreground context, + // while IRQ can update it. + return core_util_atomic_load_u64(&_tick); } -us_timestamp_t SysTimer::get_time() +template +uint64_t SysTimer::update_and_get_tick() +{ + MBED_ASSERT(!_ticking && !_wake_time_set); + // Can only be used when no interrupts are scheduled + // Update counters to reflect elapsed time + uint64_t elapsed_ticks = _elapsed_ticks(); + _unacknowledged_ticks = 0; + _time_us += elapsed_ticks * US_IN_TICK; + _tick += elapsed_ticks; + + return _tick; +} + +template +us_timestamp_t SysTimer::get_time() const { // Underlying call is interrupt safe return ticker_read_us(_ticker_data); } -SysTimer::~SysTimer() +template +us_timestamp_t SysTimer::get_time_since_tick() const { + // Underlying call is interrupt safe, and _time_us is not updated by IRQ + + return get_time() - _time_us; } -void SysTimer::_set_irq_pending() +#if (defined(NO_SYSTICK)) +template +IRQn_Type SysTimer::get_irq_number() +{ + return mbed_get_m0_tick_irqn(); +} +#elif (TARGET_CORTEX_M) +template +IRQn_Type SysTimer::get_irq_number() +{ + return SysTick_IRQn; +} +#elif (TARGET_CORTEX_A) +template +IRQn_ID_t SysTimer::get_irq_number() +{ + return mbed_get_a9_tick_irqn(); +} +#endif + +template +void SysTimer::_set_irq_pending() { // Protected function synchronized externally - + if (!IRQ) { + return; + } #if (defined(NO_SYSTICK)) NVIC_SetPendingIRQ(mbed_get_m0_tick_irqn()); -#elif (TARGET_CORTEX_A) - IRQ_SetPending(mbed_get_a9_tick_irqn()); -#else +#elif (TARGET_CORTEX_M) SCB->ICSR = SCB_ICSR_PENDSTSET_Msk; +#else + IRQ_SetPending(mbed_get_a9_tick_irqn()); #endif } -void SysTimer::_increment_tick() +template +void SysTimer::_clear_irq_pending() +{ + // Protected function synchronized externally + if (!IRQ) { + return; + } +#if (defined(NO_SYSTICK)) + NVIC_ClearPendingIRQ(mbed_get_m0_tick_irqn()); +#elif (TARGET_CORTEX_M) + SCB->ICSR = SCB_ICSR_PENDSTCLR_Msk; +#else + IRQ_ClearPending(mbed_get_a9_tick_irqn()); +#endif +} + +template +void SysTimer::_increment_tick() { // Protected function synchronized externally @@ -179,22 +309,49 @@ void SysTimer::_increment_tick() _time_us += US_IN_TICK; } -void SysTimer::handler() +template +void SysTimer::handler() { - core_util_critical_section_enter(); - - if (_suspended) { - _suspend_time_passed = true; - } else { + /* To reduce IRQ latency problems, we do not re-arm in the interrupt handler */ + if (_wake_time_set) { + _wake_time_set = false; + if (!_wake_early) { + _wake_time_passed = true; + } + /* If this was an early interrupt, user has the responsibility to check and + * note the combination of (!set, !passed), and re-arm the wake timer if + * necessary. + */ + } else if (_ticking) { + _unacknowledged_ticks++; _set_irq_pending(); _increment_tick(); - schedule_tick(); + // We do this now, rather than in acknowledgement, as we get it "for free" + // here - because we're in the ticker handler, the programming gets deferred + // until end of dispatch, and the ticker would likely be rescheduling + // anyway after dispatch. + + _schedule_tick(); } - - core_util_critical_section_exit(); } -} -} +#if MBED_CONF_RTOS_PRESENT +/* Whatever the OS wants (in case it isn't 1ms) */ +MBED_STATIC_ASSERT(1000000 % OS_TICK_FREQ == 0, "OS_TICK_FREQ must be a divisor of 1000000 for correct tick calculations"); +#define OS_TICK_US (1000000 / OS_TICK_FREQ) +#if OS_TICK_US != 1000 +template class SysTimer; +#endif +#endif -#endif // MBED_TICKLESS +/* Standard 1ms SysTimer */ +template class SysTimer<1000>; + +/* Standard 1ms SysTimer that doesn't set interrupts, used for Greentea tests */ +template class SysTimer<1000, false>; + +/* Slowed-down SysTimer that doesn't set interrupts, used for Greentea tests */ +template class SysTimer<42000, false>; + +} // namespace internal +} // namespace mbed diff --git a/platform/SysTimer.h b/platform/SysTimer.h index af712e86a7..b13a0a3bea 100644 --- a/platform/SysTimer.h +++ b/platform/SysTimer.h @@ -17,105 +17,223 @@ #ifndef MBED_SYS_TIMER_H #define MBED_SYS_TIMER_H -#if MBED_TICKLESS || defined(DOXYGEN_ONLY) - #include "platform/NonCopyable.h" +#include "platform/mbed_atomic.h" #include "drivers/TimerEvent.h" +#include "cmsis.h" +#if defined(TARGET_CORTEX_A) +#include "irq_ctrl.h" +#endif namespace mbed { namespace internal { /** - * @cond RTOS_INTERNAL + * @cond MBED_INTERNAL * - * @addtogroup rtos + * @addtogroup mbed * @{ * - * @defgroup rtos_SysTimer SysTimer class + * @defgroup mbed_SysTimer SysTimer class * @{ */ /** - * The SysTimer class is used exclusively by RTX idle loop in TICKLESS mode. + * The SysTimer class is used to provide timing for system suspension, and + * the idle loop in TICKLESS mode. * - * @note SysTimer is not the part of Mbed RTOS API. + * Template for speed for testing - only one instance will be used normally. + * + * @note SysTimer is not the part of Mbed API. */ -class SysTimer: private mbed::TimerEvent, private mbed::NonCopyable { +template +class SysTimer: private mbed::TimerEvent, private mbed::NonCopyable > { public: + /** + * Default constructor uses LPTICKER if available (so the timer will + * continue to run in deep sleep), else USTICKER. + */ SysTimer(); + SysTimer(const ticker_data_t *data); - virtual ~SysTimer(); + + ~SysTimer(); /** - * Enable an IRQ/SysTick with the correct priority. + * Get the interrupt number for the tick + * + * @return interrupt number */ - static void setup_irq(); +#if TARGET_CORTEX_A + static IRQn_ID_t get_irq_number(); +#elif TARGET_CORTEX_M + static IRQn_Type get_irq_number(); +#endif /** - * Set wakeup time and schedule a wakeup event after delta ticks + * Set the wake time * - * After suspend has been called the function suspend_time_passed - * can be used to determine if the suspend time has passed. + * Schedules an interrupt to cause wake-up in time for the event. Interrupt + * may be arranged early to account for latency. If the time has already + * passed, no interrupt will be scheduled. * - * @param delta Ticks to remain suspended + * This is called from outside a critical section, as it is known to be + * a slow operation. + * + * If the wake time is already set, this is a no-op. But that check is racy, + * which means wake_time_set() should be rechecked after taking a critical + * section. + * + * As a side-effect, this clears the unacknowledged tick count - the caller + * is expected to use update_and_get_tick() after the suspend operation. + * + * @param at Wake up tick + * @warning If the ticker tick is already scheduled it needs to be cancelled first! */ - void suspend(uint32_t delta); + void set_wake_time(uint64_t at); /** - * Check if the suspend time has passed + * Check whether the wake time has passed * - * @return true if the specified number of ticks has passed otherwise false + * This is a fast operation, based on checking whether the wake interrupt + * has run. + * + * @return true if the specified wake tick has passed */ - bool suspend_time_passed(); + bool wake_time_passed() const + { + return core_util_atomic_load_bool(&_wake_time_passed); + } /** - * Exit suspend mode and return elapsed ticks + * Check whether wake timer is active * - * Due to a scheduling issue, the number of ticks returned is decremented - * by 1 so that a handler can be called and update to the current value. - * This allows scheduling restart successfully after the OS is resumed. - * - * @return the number of elapsed ticks minus 1 + * @return true if the wake timer is active. */ - uint32_t resume(); + bool wake_time_set() const + { + return core_util_atomic_load_bool(&_wake_time_set); + } + + /** + * Cancel any pending wake + */ + void cancel_wake(); /** * Schedule an os tick to fire * - * @param delta Tick to fire at relative to current tick + * Ticks will be rescheduled automatically every tick until cancel_tick is called. + * + * A tick will be fired immediately if there are any unacknowledged ticks. * * @warning If a tick is already scheduled it needs to be cancelled first! */ - void schedule_tick(uint32_t delta = 1); + void start_tick(); /** - * Prevent any scheduled ticks from triggering + * Acknowledge an os tick + * + * This will queue another os tick immediately if the os is running slow + */ + void acknowledge_tick(); + + /** + * Prevent any more scheduled ticks from triggering + * + * If called from OS tick context, there may be remaining unacknowledged ticks. */ void cancel_tick(); + /** + * Check whether ticker is active + * + * Each time the tick interrupt fires, it is automatically rescheduled, + * so this will remain true once the tick is started, except during + * processing. + * + * @return true if the ticker is active. + */ + bool ticking() const + { + return core_util_atomic_load_bool(&_ticking); + } + + /** + * Check unacknowledged ticks + * + * Returns the count of how many times the OS timer has been queued minus + * the number of times is has been acknowledged. + * + * get_tick() - unacknowledged_ticks() should equal the OS's tick count, + * although such a calculation is not atomic if the ticker is currently running. + * + * @return number of unacknowledged ticks + */ + int unacknowledged_ticks() const + { + return core_util_atomic_load_u8(&_unacknowledged_ticks); + } + /** Get the current tick count * - * @return The number of ticks since timer creation. For the os_timer this - * should match RTX's tick count (the number of ticks since boot). + * This count is updated by the ticker interrupt, if the ticker interrupt + * is running. It the ticker interrupt is not running, update_and_get_tick() + * should be used instead. + * + * This indicates how many ticks have been generated by the tick interrupt. + * The os_timer should equal this number minus the number of unacknowledged ticks. + * + * @return The number of ticks since timer creation. */ - uint32_t get_tick(); + uint64_t get_tick() const; + + /** Update and get the current tick count + * + * This is a slow operation that reads the timer and adjusts for elapsed time. + * Can only be used when the ticker is not running, as there is no IRQ + * synchronization. + * + * This clears the unacknowledged tick counter - the caller is assumed to update + * their timer based on this return. + * + * @return The number of ticks since timer creation. + */ + uint64_t update_and_get_tick(); + + /** + * Returns time since last tick + * + * @return Relative time in microseconds + */ + us_timestamp_t get_time_since_tick() const; /** * Get the time * + * Returns the instantaneous precision time from underlying timer. + * This is a slow operation so should not be called from critical sections. + * * @return Current time in microseconds */ - us_timestamp_t get_time(); + us_timestamp_t get_time() const; protected: virtual void handler(); void _increment_tick(); + void _schedule_tick(); + uint64_t _elapsed_ticks() const; static void _set_irq_pending(); + static void _clear_irq_pending(); us_timestamp_t _time_us; uint64_t _tick; - bool _suspend_time_passed; - bool _suspended; + uint8_t _unacknowledged_ticks; + bool _wake_time_set; + bool _wake_time_passed; + bool _wake_early; + bool _ticking; + bool _deep_sleep_locked; }; /** @@ -128,5 +246,3 @@ protected: } #endif - -#endif diff --git a/platform/mbed_os_timer.cpp b/platform/mbed_os_timer.cpp new file mode 100644 index 0000000000..30322491de --- /dev/null +++ b/platform/mbed_os_timer.cpp @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2006-2019, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "platform/mbed_power_mgmt.h" +#include "platform/mbed_os_timer.h" +#include "platform/CriticalSectionLock.h" +#include "platform/SysTimer.h" +#include "us_ticker_api.h" +#include "lp_ticker_api.h" +#include "mbed_critical.h" +#include "mbed_assert.h" +#include + +/* This provides the marshalling point for a system global SysTimer, which + * is used to provide: + * - timed sleeps (for default idle hook in RTOS tickless mode, or non-RTOS sleeps) + * - regular ticks for RTOS + * - absolute system timing (directly for non-RTOS, or indirectly via RTOS tick count) + */ + +namespace mbed { +namespace internal { + +OsTimer *os_timer; + +namespace { +uint64_t os_timer_data[(sizeof(OsTimer) + 7) / 8]; +} + +OsTimer *init_os_timer() +{ + // Do not use SingletonPtr since this relies on the RTOS. + // Locking not required as it will be first called during + // OS init, or else we're a non-RTOS single-threaded setup. + if (!os_timer) { +#if MBED_CONF_TARGET_TICKLESS_FROM_US_TICKER && DEVICE_USTICKER + os_timer = new (os_timer_data) OsTimer(get_us_ticker_data()); +#elif !MBED_CONF_TARGET_TICKLESS_FROM_US_TICKER && DEVICE_LPTICKER + os_timer = new (os_timer_data) OsTimer(get_lp_ticker_data()); +#else + MBED_ASSERT("OS timer not available - check MBED_CONF_TARGET_TICKLESS_FROM_US_TICKER" && false); + return NULL; +#endif + //os_timer->setup_irq(); + } + + return os_timer; +} + +/* These traits classes are designed to permit chunks of code to be + * omitted - in particular eliminating timers. However, we don't want + * to cause template bloat, so don't have too many traits variants. + */ + +/* Optionally timed operation, with optional predicate */ +struct timed_predicate_op { + timed_predicate_op(uint64_t t) : wake_time(t), orig_predicate(NULL), orig_handle(NULL) + { + init_os_timer(); + } + + timed_predicate_op(uint64_t t, bool (*wake_predicate)(void *), void *wake_predicate_handle) : wake_time(t), orig_predicate(wake_predicate), orig_handle(wake_predicate_handle) + { + init_os_timer(); + } + + ~timed_predicate_op() + { + // Make sure wake timer is cancelled. (It may or may not be, depending on + // why we woke). + os_timer->cancel_wake(); + } + + bool wake_condition() const + { + return (orig_predicate && orig_predicate(orig_handle)) || os_timer->wake_time_passed(); + } + + void sleep_prepare() + { + if (wake_time != (uint64_t) -1) { + os_timer->set_wake_time(wake_time); + } + } + + bool sleep_prepared() + { + return wake_time == (uint64_t) -1 || os_timer->wake_time_set(); + } + +private: + uint64_t wake_time; + bool (*orig_predicate)(void *); + void *orig_handle; +}; + +/* Untimed operation with predicate */ +struct untimed_op { + untimed_op(bool (*wake_predicate)(void *), void *wake_predicate_handle) : orig_predicate(wake_predicate), orig_handle(wake_predicate_handle) + { + } + + bool wake_condition() const + { + return orig_predicate(orig_handle); + } + + void sleep_prepare() + { + } + + bool sleep_prepared() + { + return true; + } + +private: + bool (*orig_predicate)(void *); + void *orig_handle; +}; + +/* We require that this is called from thread context, outside a critical section, + * and the kernel already suspended if an RTOS, meaning we don't have to worry + * about any potential threading issues. + * + * The wake predicate will be called from both outside and inside a critical + * section, so appropriate atomic care must be taken. + */ +template +void do_sleep_operation(OpT &op) +{ + // We assume the ticker is not already in use - without RTOS, it + // is never used, with RTOS, it will have been disabled with OS_Tick_Disable + while (!op.wake_condition()) { + // Set (or re-set) the wake time - outside a critical section, as + // it could take long enough to cause UART data loss on some platforms. + op.sleep_prepare(); + + // If no target sleep function, nothing else to do - just keep + // rechecking the wake condition. +#if DEVICE_SLEEP + // Now we need to enter the critical section for the race-free sleep + { + CriticalSectionLock lock; + + // Recheck wake conditions before starting sleep, avoiding race + if (op.wake_condition()) { + break; + } + + // It's possible that an intermediate wake interrupt occurred + // between "set_wake_time" and the critical lock - only sleep + // if we see that the timer is armed or we don't need it. Otherwise, + // we go round to set the timer again. + if (op.sleep_prepared()) { + // Enter HAL sleep (normal or deep) + sleep(); + } + } + + // Ensure interrupts get a chance to fire, which allows new result from + // wake_predicate() and wake_time_passed() + __ISB(); +#endif + } +} + +/* We require that this is called from thread context, outside a critical section, + * and the kernel already suspended if an RTOS, meaning we don't have to worry + * about any potential threading issues. + * + * The wake predicate will be called from both outside and inside a critical + * section, so appropriate atomic care must be taken. + */ +uint64_t do_timed_sleep_absolute(uint64_t wake_time, bool (*wake_predicate)(void *), void *wake_predicate_handle) +{ + { + timed_predicate_op op(wake_time, wake_predicate, wake_predicate_handle); + do_sleep_operation(op); + } + + return os_timer->update_and_get_tick(); +} + + +#if MBED_CONF_RTOS_PRESENT +/* The 32-bit limit is part of the API - we will always wake within 2^32 ticks */ +/* This version is tuned for RTOS use, where the RTOS needs to know the time spent sleeping */ +uint32_t do_timed_sleep_relative(uint32_t wake_delay, bool (*wake_predicate)(void *), void *wake_predicate_handle) +{ + uint64_t sleep_start = init_os_timer()->get_tick(); + // When running with RTOS, the requested delay will be based on the kernel's tick count. + // If it missed a tick as entering idle, we should reflect that by moving the + // start time back to reflect its current idea of time. + // Example: OS tick count = 100, our tick count = 101, requested delay = 50 + // We need to schedule wake for tick 150, report 50 ticks back to our caller, and + // clear the unacknowledged tick count. + sleep_start -= os_timer->unacknowledged_ticks(); + + uint64_t sleep_finish = do_timed_sleep_absolute(sleep_start + wake_delay, wake_predicate, wake_predicate_handle); + + return static_cast(sleep_finish - sleep_start); +} + +#else + +void do_untimed_sleep(bool (*wake_predicate)(void *), void *wake_predicate_handle) +{ + untimed_op op(wake_predicate, wake_predicate_handle); + + do_sleep_operation(op); +} + +/* (uint32_t)-1 delay is treated as "wait forever" */ +/* This version is tuned for non-RTOS use, where we don't need to return sleep time, and waiting forever is possible */ +void do_timed_sleep_relative_or_forever(uint32_t wake_delay, bool (*wake_predicate)(void *), void *wake_predicate_handle) +{ + // Special-case 0 delay, to save multiple callers having to do it. Just call the predicate once. + if (wake_delay == 0) { + wake_predicate(wake_predicate_handle); + return; + } + + uint64_t wake_time; + if (wake_delay == (uint32_t) -1) { + wake_time = (uint64_t) -1; + } else { + wake_time = init_os_timer()->update_and_get_tick() + wake_delay; + } + /* Always use timed_predicate_op here to save pulling in two templates */ + timed_predicate_op op(wake_time, wake_predicate, wake_predicate_handle); + do_sleep_operation(op); +} + +#endif + +} // namespace internal +} // namespace mbed diff --git a/platform/mbed_os_timer.h b/platform/mbed_os_timer.h new file mode 100644 index 0000000000..639dc3fdfd --- /dev/null +++ b/platform/mbed_os_timer.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2006-2019, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBED_MBED_SLEEP_TIMER_H +#define MBED_MBED_SLEEP_TIMER_H + +#include "platform/SysTimer.h" + +#if MBED_CONF_RTOS_PRESENT +extern "C" { +#include "rtx_lib.h" +} +#endif + +namespace mbed { +namespace internal { + +#if MBED_CONF_RTOS_PRESENT +#define OS_TICK_US (1000000 / OS_TICK_FREQ) +#else +#define OS_TICK_US 1000 +#endif +typedef SysTimer OsTimer; + +/* A SysTimer is used to provide the timed sleep - this provides access to share it for + * other use, such as ticks. If accessed this way, it must not be in use when a sleep function below is called. + */ +extern OsTimer *os_timer; +OsTimer *init_os_timer(); + +/* -1 is effectively "sleep forever" */ +uint64_t do_timed_sleep_absolute(uint64_t wake_time, bool (*wake_predicate)(void *) = NULL, void *wake_predicate_handle = NULL); + +#if MBED_CONF_RTOS_PRESENT +/* Maximum sleep time is 2^32-1 ticks; timer is always set to achieve this */ +/* Assumes that ticker has been in use prior to call, so restricted to RTOS use */ +uint32_t do_timed_sleep_relative(uint32_t wake_delay, bool (*wake_predicate)(void *) = NULL, void *wake_predicate_handle = NULL); +#else + +void do_untimed_sleep(bool (*wake_predicate)(void *), void *wake_predicate_handle = NULL); + +/* (uint32_t)-1 delay is sleep forever */ + +void do_timed_sleep_relative_or_forever(uint32_t wake_delay, bool (*wake_predicate)(void *) = NULL, void *wake_predicate_handle = NULL); + +#endif + +} +} + +#endif diff --git a/rtos/TARGET_CORTEX/mbed_rtx_idle.cpp b/rtos/TARGET_CORTEX/mbed_rtx_idle.cpp index d602126dae..52b7efede9 100644 --- a/rtos/TARGET_CORTEX/mbed_rtx_idle.cpp +++ b/rtos/TARGET_CORTEX/mbed_rtx_idle.cpp @@ -22,9 +22,8 @@ #include "rtos/rtos_idle.h" #include "platform/mbed_power_mgmt.h" +#include "platform/mbed_os_timer.h" #include "TimerEvent.h" -#include "lp_ticker_api.h" -#include "us_ticker_api.h" #include "mbed_critical.h" #include "mbed_assert.h" #include @@ -34,7 +33,8 @@ extern "C" { #include "rtx_lib.h" - using namespace mbed; + using mbed::internal::os_timer; + using mbed::internal::OsTimer; #ifdef MBED_TICKLESS @@ -46,26 +46,39 @@ extern "C" { #error Low power ticker required when MBED_CONF_TARGET_TICKLESS_FROM_US_TICKER is false #endif -#include "platform/SysTimer.h" + // Setup OS Tick timer to generate periodic RTOS Kernel Ticks + int32_t OS_Tick_Setup(uint32_t freq, IRQHandler_t handler) + { + MBED_ASSERT(freq == 1000); - static mbed::internal::SysTimer *os_timer; - static uint64_t os_timer_data[sizeof(mbed::internal::SysTimer) / 8]; +#ifdef TARGET_CORTEX_A + IRQn_ID_t irq = OsTimer::get_irq_number(); + + IRQ_SetPriority(irq, 0xFF); + IRQ_SetHandler(irq, handler); + IRQ_EnableIRQ(irq); +#else + IRQn_Type irq = OsTimer::get_irq_number(); + + NVIC_SetPriority(irq, 0xFF); +#ifdef NVIC_RAM_VECTOR_ADDRESS + NVIC_SetVector(irq, (uint32_t)handler); +#else + MBED_ASSERT(handler == (IRQHandler_t)NVIC_GetVector(irq)); +#endif + if (irq >= 0) { + NVIC_EnableIRQ(irq); + } +#endif + + return 0; + } // Enable System Timer. void OS_Tick_Enable(void) { - // Do not use SingletonPtr since this relies on the RTOS - if (NULL == os_timer) { -#if MBED_CONF_TARGET_TICKLESS_FROM_US_TICKER - os_timer = new (os_timer_data) mbed::internal::SysTimer(get_us_ticker_data()); -#else - os_timer = new (os_timer_data) mbed::internal::SysTimer(get_lp_ticker_data()); -#endif - os_timer->setup_irq(); - } - // set to fire interrupt on next tick - os_timer->schedule_tick(); + mbed::internal::init_os_timer()->start_tick(); } // Disable System Timer. @@ -77,66 +90,54 @@ extern "C" { // Acknowledge System Timer IRQ. void OS_Tick_AcknowledgeIRQ(void) { - + os_timer->acknowledge_tick(); } // Get System Timer count. uint32_t OS_Tick_GetCount(void) { - return os_timer->get_time() & 0xFFFFFFFF; + return (uint32_t) os_timer->get_time_since_tick(); } // Get OS Tick IRQ number. int32_t OS_Tick_GetIRQn(void) { - return -1; + return os_timer->get_irq_number(); } // Get OS Tick overflow status. uint32_t OS_Tick_GetOverflow(void) { + // No need to indicate overflow - we let OS_Tick_GetCount overflow above + // OS_Tick_GetInterval. return 0; } + // Get OS Tick timer clock frequency + uint32_t OS_Tick_GetClock(void) + { + return 1000000; + } + // Get OS Tick interval. uint32_t OS_Tick_GetInterval(void) { return 1000; } + static bool rtos_event_pending(void *) + { + return core_util_atomic_load_u8(&osRtxInfo.kernel.pendSV); + } + static void default_idle_hook(void) { uint32_t ticks_to_sleep = osKernelSuspend(); - const bool block_deep_sleep = MBED_CONF_TARGET_TICKLESS_FROM_US_TICKER || - (ticks_to_sleep <= MBED_CONF_TARGET_DEEP_SLEEP_LATENCY); - - if (block_deep_sleep) { - sleep_manager_lock_deep_sleep(); - } else { - ticks_to_sleep -= MBED_CONF_TARGET_DEEP_SLEEP_LATENCY; - } - os_timer->suspend(ticks_to_sleep); - - bool event_pending = false; - while (!os_timer->suspend_time_passed() && !event_pending) { - - core_util_critical_section_enter(); - if (osRtxInfo.kernel.pendSV) { - event_pending = true; - } else { - sleep(); - } - core_util_critical_section_exit(); - - // Ensure interrupts get a chance to fire - __ISB(); - } - - if (block_deep_sleep) { - sleep_manager_unlock_deep_sleep(); - } - - osKernelResume(os_timer->resume()); + // osKernelSuspend will call OS_Tick_Disable, cancelling the tick, which frees + // up the os timer for the timed sleep + uint64_t ticks_slept = mbed::internal::do_timed_sleep_relative(ticks_to_sleep, rtos_event_pending); + MBED_ASSERT(ticks_slept < osWaitForever); + osKernelResume((uint32_t) ticks_slept); } From 38160035d46e5e36e92f6f18790aa599e648a7f2 Mon Sep 17 00:00:00 2001 From: Kevin Bracey Date: Wed, 8 May 2019 14:28:06 +0300 Subject: [PATCH 05/17] rtos/mbed_lib.json: Correct indents --- rtos/mbed_lib.json | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/rtos/mbed_lib.json b/rtos/mbed_lib.json index a062ce3cb6..aed253aba5 100644 --- a/rtos/mbed_lib.json +++ b/rtos/mbed_lib.json @@ -38,18 +38,18 @@ "STM32L1": { "idle-thread-stack-size-debug-extra": 512 }, - "MCU_NRF51": { - "target.boot-stack-size": "0x800" - }, - "MCU_NRF52840": { - "target.boot-stack-size": "0x800" - }, - "MCU_NRF52832": { - "target.boot-stack-size": "0x800" - }, - "MCU_NRF51_UNIFIED": { - "target.boot-stack-size": "0x800" - }, + "MCU_NRF51": { + "target.boot-stack-size": "0x800" + }, + "MCU_NRF52840": { + "target.boot-stack-size": "0x800" + }, + "MCU_NRF52832": { + "target.boot-stack-size": "0x800" + }, + "MCU_NRF51_UNIFIED": { + "target.boot-stack-size": "0x800" + }, "NUVOTON": { "idle-thread-stack-size-debug-extra": 512 } From 83b329cb71d53b3f50961c647590c6bffe36da4a Mon Sep 17 00:00:00 2001 From: Kevin Bracey Date: Thu, 14 Mar 2019 13:36:02 +0200 Subject: [PATCH 06/17] RTOS API for bare metal Provide partial RTOS API for bare metal builds - things that can be done in a single threaded environment. Allows more code to work in both RTOS and bare metal builds without change, and in particular gives easy access to the ability to efficiently wait for something occurring in interrupt. Available in bare-metal: * ThisThread * osThreadFlagsSet to set flags on main thread (can be set from IRQ) * EventFlags (can be set from IRQ) * Semaphores (can be released from IRQ) * Mutex (dummy implementation) Not useful: * ConditionVariable (could only be signalled from 2nd thread) * RtosTimer (calls in a second thread context) * Thread Unimplemented: * Mail, Queue, MemoryPool Possible future work: * ConditionVariableCS to act as IRQ signalled ConditionVariable --- UNITTESTS/CMakeLists.txt | 3 + UNITTESTS/target_h/rtos/Mutex.h | 3 +- .../target_h/{ => rtos}/mbed_rtos1_types.h | 0 .../target_h/{ => rtos}/mbed_rtos_storage.h | 0 UNITTESTS/target_h/{ => rtos}/rtos.h | 0 mbed.h | 2 +- rtos/ConditionVariable.cpp | 4 + rtos/ConditionVariable.h | 6 +- rtos/EventFlags.cpp | 37 ++++++ rtos/EventFlags.h | 10 +- rtos/Kernel.cpp | 8 +- rtos/Kernel.h | 2 +- rtos/LICENSE.md | 1 - rtos/Mail.h | 14 ++- rtos/MemoryPool.h | 8 +- rtos/Mutex.cpp | 7 +- rtos/Mutex.h | 60 +++++++++- rtos/Queue.h | 10 +- rtos/RtosTimer.cpp | 4 + rtos/RtosTimer.h | 10 +- rtos/Semaphore.cpp | 84 ++++++++++++++ rtos/Semaphore.h | 12 +- rtos/TARGET_CORTEX/mbed_lib.json | 57 +++++++++ rtos/TARGET_CORTEX/mbed_rtos1_types.h | 28 ----- ...mbed_rtos_storage.h => mbed_rtx_storage.h} | 4 +- rtos/ThisThread.cpp | 109 +++++++++++++++++- rtos/ThisThread.h | 22 ++-- rtos/Thread.cpp | 4 + rtos/Thread.h | 10 +- rtos/mbed_lib.json | 59 +--------- rtos/mbed_rtos1_types.h | 30 +++++ rtos/mbed_rtos_storage.h | 28 +++++ rtos/mbed_rtos_types.h | 76 ++++++++++++ rtos/rtos.h | 2 +- rtos/rtos_handlers.h | 2 +- 35 files changed, 580 insertions(+), 136 deletions(-) rename UNITTESTS/target_h/{ => rtos}/mbed_rtos1_types.h (100%) rename UNITTESTS/target_h/{ => rtos}/mbed_rtos_storage.h (100%) rename UNITTESTS/target_h/{ => rtos}/rtos.h (100%) create mode 100644 rtos/TARGET_CORTEX/mbed_lib.json delete mode 100644 rtos/TARGET_CORTEX/mbed_rtos1_types.h rename rtos/TARGET_CORTEX/{mbed_rtos_storage.h => mbed_rtx_storage.h} (97%) create mode 100644 rtos/mbed_rtos1_types.h create mode 100644 rtos/mbed_rtos_storage.h create mode 100644 rtos/mbed_rtos_types.h diff --git a/UNITTESTS/CMakeLists.txt b/UNITTESTS/CMakeLists.txt index 41164268f8..875f024bed 100644 --- a/UNITTESTS/CMakeLists.txt +++ b/UNITTESTS/CMakeLists.txt @@ -86,6 +86,9 @@ endif(COVERAGE) # UNIT TESTS #################### +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUNITTEST") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUNITTEST") + # Set include dirs. set(unittest-includes-base "${PROJECT_SOURCE_DIR}/target_h" diff --git a/UNITTESTS/target_h/rtos/Mutex.h b/UNITTESTS/target_h/rtos/Mutex.h index 4f38c37fe0..5a14ed47b4 100644 --- a/UNITTESTS/target_h/rtos/Mutex.h +++ b/UNITTESTS/target_h/rtos/Mutex.h @@ -18,7 +18,8 @@ #define __MUTEX_H__ #include -#include "cmsis_os2.h" +#include "mbed_rtos_types.h" +#include "mbed_rtos1_types.h" namespace rtos { diff --git a/UNITTESTS/target_h/mbed_rtos1_types.h b/UNITTESTS/target_h/rtos/mbed_rtos1_types.h similarity index 100% rename from UNITTESTS/target_h/mbed_rtos1_types.h rename to UNITTESTS/target_h/rtos/mbed_rtos1_types.h diff --git a/UNITTESTS/target_h/mbed_rtos_storage.h b/UNITTESTS/target_h/rtos/mbed_rtos_storage.h similarity index 100% rename from UNITTESTS/target_h/mbed_rtos_storage.h rename to UNITTESTS/target_h/rtos/mbed_rtos_storage.h diff --git a/UNITTESTS/target_h/rtos.h b/UNITTESTS/target_h/rtos/rtos.h similarity index 100% rename from UNITTESTS/target_h/rtos.h rename to UNITTESTS/target_h/rtos/rtos.h diff --git a/mbed.h b/mbed.h index e59813d11b..4f6f6f6024 100644 --- a/mbed.h +++ b/mbed.h @@ -18,7 +18,7 @@ #include "platform/mbed_version.h" -#if MBED_CONF_RTOS_PRESENT +#if MBED_CONF_RTOS_API_PRESENT #include "rtos/rtos.h" #endif diff --git a/rtos/ConditionVariable.cpp b/rtos/ConditionVariable.cpp index cb3bf805a0..e1087fe0a7 100644 --- a/rtos/ConditionVariable.cpp +++ b/rtos/ConditionVariable.cpp @@ -26,6 +26,8 @@ #include "mbed_error.h" #include "mbed_assert.h" +#if MBED_CONF_RTOS_PRESENT + namespace rtos { ConditionVariable::Waiter::Waiter(): sem(0), prev(NULL), next(NULL), in_list(false) @@ -150,3 +152,5 @@ ConditionVariable::~ConditionVariable() } } + +#endif diff --git a/rtos/ConditionVariable.h b/rtos/ConditionVariable.h index 543efc7eb3..35ecbf5709 100644 --- a/rtos/ConditionVariable.h +++ b/rtos/ConditionVariable.h @@ -23,12 +23,14 @@ #define CONDITIONVARIABLE_H #include -#include "cmsis_os.h" +#include "rtos/mbed_rtos_types.h" #include "rtos/Mutex.h" #include "rtos/Semaphore.h" #include "platform/NonCopyable.h" +#if MBED_CONF_RTOS_PRESENT || defined(DOXYGEN_ONLY) + namespace rtos { /** \addtogroup rtos */ /** @{*/ @@ -328,4 +330,6 @@ protected: } #endif +#endif + /** @}*/ diff --git a/rtos/EventFlags.cpp b/rtos/EventFlags.cpp index 1167d764ac..5382ff9456 100644 --- a/rtos/EventFlags.cpp +++ b/rtos/EventFlags.cpp @@ -20,6 +20,8 @@ * SOFTWARE. */ #include "rtos/EventFlags.h" +#include "rtos/ThisThread.h" +#include "mbed_os_timer.h" #include #include "mbed_error.h" #include "mbed_assert.h" @@ -38,27 +40,43 @@ EventFlags::EventFlags(const char *name) void EventFlags::constructor(const char *name) { +#if MBED_CONF_RTOS_PRESENT osEventFlagsAttr_t attr = { 0 }; attr.name = name ? name : "application_unnamed_event_flags"; attr.cb_mem = &_obj_mem; attr.cb_size = sizeof(_obj_mem); _id = osEventFlagsNew(&attr); MBED_ASSERT(_id); +#else + _flags = 0; +#endif } uint32_t EventFlags::set(uint32_t flags) { +#if MBED_CONF_RTOS_PRESENT return osEventFlagsSet(_id, flags); +#else + return core_util_atomic_fetch_or_u32(&_flags, flags) | flags; +#endif } uint32_t EventFlags::clear(uint32_t flags) { +#if MBED_CONF_RTOS_PRESENT return osEventFlagsClear(_id, flags); +#else + return core_util_atomic_fetch_and_u32(&_flags, ~flags); +#endif } uint32_t EventFlags::get() const { +#if MBED_CONF_RTOS_PRESENT return osEventFlagsGet(_id); +#else + return core_util_atomic_load_u32(&_flags); +#endif } uint32_t EventFlags::wait_all(uint32_t flags, uint32_t millisec, bool clear) @@ -73,7 +91,9 @@ uint32_t EventFlags::wait_any(uint32_t flags, uint32_t millisec, bool clear) EventFlags::~EventFlags() { +#if MBED_CONF_RTOS_PRESENT osEventFlagsDelete(_id); +#endif } uint32_t EventFlags::wait(uint32_t flags, uint32_t opt, uint32_t millisec, bool clear) @@ -82,7 +102,24 @@ uint32_t EventFlags::wait(uint32_t flags, uint32_t opt, uint32_t millisec, bool opt |= osFlagsNoClear; } +#if MBED_CONF_RTOS_PRESENT return osEventFlagsWait(_id, flags, opt, millisec); +#else + rtos::internal::flags_check_capture check; + check.flags = &_flags; + check.options = opt; + check.flags_wanted = flags; + check.result = 0; + check.match = false; + mbed::internal::do_timed_sleep_relative_or_forever(millisec, rtos::internal::non_rtos_check_flags, &check); + if (check.match) { + return check.result; + } else if (millisec == 0) { + return osErrorResource; + } else { + return osErrorTimeout; + } +#endif } } diff --git a/rtos/EventFlags.h b/rtos/EventFlags.h index bac58ea588..0c2798d4a9 100644 --- a/rtos/EventFlags.h +++ b/rtos/EventFlags.h @@ -23,9 +23,9 @@ #define EVENT_FLAG_H #include -#include "cmsis_os2.h" -#include "mbed_rtos1_types.h" -#include "mbed_rtos_storage.h" +#include "rtos/mbed_rtos_types.h" +#include "rtos/mbed_rtos1_types.h" +#include "rtos/mbed_rtos_storage.h" #include "platform/NonCopyable.h" @@ -114,8 +114,12 @@ public: private: void constructor(const char *name = NULL); uint32_t wait(uint32_t flags, uint32_t opt, uint32_t millisec, bool clear); +#if MBED_CONF_RTOS_PRESENT osEventFlagsId_t _id; mbed_rtos_storage_event_flags_t _obj_mem; +#else + uint32_t _flags; +#endif }; /** @}*/ diff --git a/rtos/Kernel.cpp b/rtos/Kernel.cpp index a620c0cf1f..4751bee053 100644 --- a/rtos/Kernel.cpp +++ b/rtos/Kernel.cpp @@ -20,16 +20,17 @@ * SOFTWARE. */ -#include "cmsis_os2.h" #include "rtos/Kernel.h" #include "rtos/rtos_idle.h" #include "rtos/rtos_handlers.h" #include "platform/mbed_critical.h" +#include "platform/mbed_os_timer.h" namespace rtos { uint64_t Kernel::get_ms_count() { +#if MBED_CONF_RTOS_PRESENT // CMSIS-RTOS 2.1.0 and 2.1.1 differ in the time type. We assume // our header at least matches the implementation, so we don't try looking // at the run-time version report. (There's no compile-time version report) @@ -61,8 +62,12 @@ uint64_t Kernel::get_ms_count() core_util_critical_section_exit(); return ret; } +#else + return mbed::internal::init_os_timer()->update_and_get_tick(); +#endif } +#if MBED_CONF_RTOS_PRESENT void Kernel::attach_idle_hook(void (*fptr)(void)) { rtos_attach_idle_hook(fptr); @@ -72,5 +77,6 @@ void Kernel::attach_thread_terminate_hook(void (*fptr)(osThreadId_t id)) { rtos_attach_thread_terminate_hook(fptr); } +#endif } diff --git a/rtos/Kernel.h b/rtos/Kernel.h index 851dfb688e..5a73aadf40 100644 --- a/rtos/Kernel.h +++ b/rtos/Kernel.h @@ -23,7 +23,7 @@ #define KERNEL_H #include -#include "cmsis_os2.h" +#include "rtos/mbed_rtos_types.h" namespace rtos { /** \addtogroup rtos */ diff --git a/rtos/LICENSE.md b/rtos/LICENSE.md index a99cc40e78..01cb36ec62 100644 --- a/rtos/LICENSE.md +++ b/rtos/LICENSE.md @@ -3,7 +3,6 @@ as can be found: LICENSE-apache-2.0.txt. Files licensed under MIT: -- TARGET_CORTEX/mbed_rtos1_types.h - TARGET_CORTEX/mbed_rtos_storage.h - TARGET_CORTEX/mbed_rtx_conf.h - TARGET_CORTEX/mbed_rtx_idle.cpp diff --git a/rtos/Mail.h b/rtos/Mail.h index dd10509681..85607dc45e 100644 --- a/rtos/Mail.h +++ b/rtos/Mail.h @@ -25,11 +25,11 @@ #include #include -#include "Queue.h" -#include "MemoryPool.h" -#include "cmsis_os2.h" -#include "mbed_rtos_storage.h" -#include "mbed_rtos1_types.h" +#include "rtos/Queue.h" +#include "rtos/MemoryPool.h" +#include "rtos/mbed_rtos_types.h" +#include "rtos/mbed_rtos_storage.h" +#include "rtos/mbed_rtos1_types.h" #include "platform/mbed_toolchain.h" #include "platform/NonCopyable.h" @@ -38,6 +38,8 @@ using namespace rtos; #endif +#if MBED_CONF_RTOS_PRESENT || defined(DOXYGEN_ONLY) + namespace rtos { /** \addtogroup rtos */ /** @{*/ @@ -238,5 +240,5 @@ private: #endif - +#endif diff --git a/rtos/MemoryPool.h b/rtos/MemoryPool.h index 431b5d6894..6764d12237 100644 --- a/rtos/MemoryPool.h +++ b/rtos/MemoryPool.h @@ -25,11 +25,12 @@ #include #include -#include "cmsis_os2.h" -#include "mbed_rtos1_types.h" -#include "mbed_rtos_storage.h" +#include "rtos/mbed_rtos_types.h" +#include "rtos/mbed_rtos1_types.h" +#include "rtos/mbed_rtos_storage.h" #include "platform/NonCopyable.h" +#if MBED_CONF_RTOS_PRESENT || defined(DOXYGEN_ONLY) namespace rtos { /** \addtogroup rtos */ /** @{*/ @@ -191,3 +192,4 @@ private: } #endif +#endif diff --git a/rtos/Mutex.cpp b/rtos/Mutex.cpp index 24f3085cb9..8316168b6c 100644 --- a/rtos/Mutex.cpp +++ b/rtos/Mutex.cpp @@ -26,9 +26,11 @@ #include "mbed_error.h" #include "mbed_assert.h" +#if MBED_CONF_RTOS_PRESENT + namespace rtos { -Mutex::Mutex(): _count(0) +Mutex::Mutex() { constructor(); } @@ -40,6 +42,7 @@ Mutex::Mutex(const char *name) void Mutex::constructor(const char *name) { + _count = 0; osMutexAttr_t attr = { 0 }; attr.name = name ? name : "application_unnamed_mutex"; @@ -147,3 +150,5 @@ Mutex::~Mutex() } } + +#endif diff --git a/rtos/Mutex.h b/rtos/Mutex.h index a4955a54c6..aeddf02924 100644 --- a/rtos/Mutex.h +++ b/rtos/Mutex.h @@ -23,9 +23,9 @@ #define MUTEX_H #include -#include "cmsis_os2.h" -#include "mbed_rtos1_types.h" -#include "mbed_rtos_storage.h" +#include "rtos/mbed_rtos_types.h" +#include "rtos/mbed_rtos1_types.h" +#include "rtos/mbed_rtos_storage.h" #include "platform/NonCopyable.h" #include "platform/ScopedLock.h" @@ -56,6 +56,8 @@ typedef mbed::ScopedLock ScopedMutexLock; /** The Mutex class is used to synchronize the execution of threads. This is, for example, used to protect access to a shared resource. + In bare-metal builds, the Mutex class is a dummy, so lock() and unlock() are no-ops. + @note You cannot use member functions of this class in ISR context. If you require Mutex functionality within ISR handler, consider using @a Semaphore. @@ -88,7 +90,11 @@ public: @note This function treats RTOS errors as fatal system errors, so it can only return osOK. Use of the return value is deprecated, as the return is expected to become void in the future. */ - osStatus lock(void); +#if MBED_CONF_RTOS_PRESENT + osStatus lock(); +#else + void lock(); // Value return backwards compatibility not required for non-RTOS +#endif /** Wait until a Mutex becomes available. @@ -150,14 +156,18 @@ public: @note This function treats RTOS errors as fatal system errors, so it can only return osOK. Use of the return value is deprecated, as the return is expected to become void in the future. */ +#if MBED_CONF_RTOS_PRESENT osStatus unlock(); +#else + void unlock(); // Value return backwards compatibility not required for non-RTOS +#endif /** Get the owner the this mutex @return the current owner of this mutex. @note You cannot call this function from ISR context. */ - osThreadId get_owner(); + osThreadId_t get_owner(); /** Mutex destructor * @@ -166,13 +176,53 @@ public: ~Mutex(); private: +#if MBED_CONF_RTOS_PRESENT void constructor(const char *name = NULL); friend class ConditionVariable; osMutexId_t _id; mbed_rtos_storage_mutex_t _obj_mem; uint32_t _count; +#endif }; + +#if !MBED_CONF_RTOS_PRESENT +inline Mutex::Mutex() +{ +} + +inline Mutex::Mutex(const char *) +{ +} + +inline Mutex::~Mutex() +{ +} + +inline void Mutex::lock() +{ +} + +inline bool Mutex::trylock() +{ + return true; +} + +inline bool Mutex::trylock_for(uint32_t) +{ + return true; +} + +inline bool Mutex::trylock_until(uint64_t) +{ + return true; +} + +inline void Mutex::unlock() +{ +} +#endif + /** @}*/ /** @}*/ } diff --git a/rtos/Queue.h b/rtos/Queue.h index e31fb619d6..1ce8eb354a 100644 --- a/rtos/Queue.h +++ b/rtos/Queue.h @@ -22,12 +22,14 @@ #ifndef QUEUE_H #define QUEUE_H -#include "cmsis_os2.h" -#include "mbed_rtos1_types.h" -#include "mbed_rtos_storage.h" +#include "rtos/mbed_rtos_types.h" +#include "rtos/mbed_rtos1_types.h" +#include "rtos/mbed_rtos_storage.h" #include "platform/mbed_error.h" #include "platform/NonCopyable.h" +#if MBED_CONF_RTOS_PRESENT || defined(DOXYGEN_ONLY) + namespace rtos { /** \addtogroup rtos */ /** @{*/ @@ -219,4 +221,6 @@ private: } // namespace rtos +#endif + #endif // QUEUE_H diff --git a/rtos/RtosTimer.cpp b/rtos/RtosTimer.cpp index 4639da035b..4779f320ce 100644 --- a/rtos/RtosTimer.cpp +++ b/rtos/RtosTimer.cpp @@ -26,6 +26,8 @@ #include +#if MBED_CONF_RTOS_PRESENT + namespace rtos { void RtosTimer::constructor(mbed::Callback func, os_timer_type type) @@ -54,3 +56,5 @@ RtosTimer::~RtosTimer() } } + +#endif diff --git a/rtos/RtosTimer.h b/rtos/RtosTimer.h index eb976cd0bd..168687281b 100644 --- a/rtos/RtosTimer.h +++ b/rtos/RtosTimer.h @@ -23,12 +23,14 @@ #define RTOS_TIMER_H #include -#include "cmsis_os2.h" -#include "mbed_rtos_storage.h" +#include "rtos/mbed_rtos_types.h" +#include "rtos/mbed_rtos_storage.h" #include "platform/Callback.h" #include "platform/NonCopyable.h" #include "platform/mbed_toolchain.h" -#include "mbed_rtos1_types.h" +#include "rtos/mbed_rtos1_types.h" + +#if MBED_CONF_RTOS_PRESENT || defined(DOXYGEN_ONLY) namespace rtos { /** \addtogroup rtos */ @@ -188,4 +190,4 @@ private: #endif - +#endif diff --git a/rtos/Semaphore.cpp b/rtos/Semaphore.cpp index 0c69c00272..6887ac247f 100644 --- a/rtos/Semaphore.cpp +++ b/rtos/Semaphore.cpp @@ -22,7 +22,9 @@ #include "rtos/Semaphore.h" #include "rtos/Kernel.h" #include "platform/mbed_assert.h" +#include "platform/mbed_critical.h" #include "platform/mbed_error.h" +#include "platform/mbed_os_timer.h" #include @@ -40,22 +42,51 @@ Semaphore::Semaphore(int32_t count, uint16_t max_count) void Semaphore::constructor(int32_t count, uint16_t max_count) { +#if MBED_CONF_RTOS_PRESENT osSemaphoreAttr_t attr = { 0 }; attr.cb_mem = &_obj_mem; attr.cb_size = sizeof(_obj_mem); _id = osSemaphoreNew(max_count, count, &attr); MBED_ASSERT(_id != NULL); +#else + _count = count; + _max_count = max_count; +#endif } +#if !MBED_CONF_RTOS_PRESENT +struct sem_wait_capture { + Semaphore *sem; + bool acquired; +}; + +bool Semaphore::semaphore_available(void *handle) +{ + sem_wait_capture *wait = static_cast(handle); + return wait->acquired = wait->sem->try_acquire(); +} +#endif + bool Semaphore::try_acquire() { +#if MBED_CONF_RTOS_PRESENT osStatus_t status = osSemaphoreAcquire(_id, 0); if (status != osOK && status != osErrorResource) { MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_KERNEL, MBED_ERROR_CODE_SEMAPHORE_LOCK_FAILED), "Semaphore acquire failed", status); } return status == osOK; +#else + int32_t old_count = core_util_atomic_load_s32(&_count); + do { + if (old_count == 0) { + return false; + } + } while (!core_util_atomic_cas_s32(&_count, &old_count, old_count - 1)); + return true; +#endif } +#if MBED_CONF_RTOS_PRESENT /* To sidestep deprecation warnings */ int32_t Semaphore::_wait(uint32_t millisec) { @@ -71,14 +102,26 @@ int32_t Semaphore::_wait(uint32_t millisec) return -1; } } +#endif int32_t Semaphore::wait(uint32_t millisec) { +#if MBED_CONF_RTOS_PRESENT return _wait(millisec); +#else + sem_wait_capture capture = { this, false }; + mbed::internal::do_timed_sleep_relative_or_forever(millisec, semaphore_available, &capture); + if (capture.acquired) { + return core_util_atomic_load_s32(&_count) + 1; + } else { + return 0; + } +#endif } int32_t Semaphore::wait_until(uint64_t millisec) { +#if MBED_CONF_RTOS_PRESENT uint64_t now = Kernel::get_ms_count(); if (now >= millisec) { @@ -89,18 +132,36 @@ int32_t Semaphore::wait_until(uint64_t millisec) } else { return _wait(millisec - now); } +#else + sem_wait_capture capture = { this, false }; + mbed::internal::do_timed_sleep_absolute(millisec, semaphore_available, &capture); + if (capture.acquired) { + return core_util_atomic_load_s32(&_count) + 1; + } else { + return 0; + } +#endif } void Semaphore::acquire() { +#if MBED_CONF_RTOS_PRESENT osStatus_t status = osSemaphoreAcquire(_id, osWaitForever); if (status != osOK) { MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_KERNEL, MBED_ERROR_CODE_SEMAPHORE_LOCK_FAILED), "Semaphore acquire failed", status); } +#else + sem_wait_capture capture = { this, false }; + mbed::internal::do_untimed_sleep(semaphore_available, &capture); + if (!capture.acquired) { + MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_KERNEL, MBED_ERROR_CODE_SEMAPHORE_LOCK_FAILED), "Semaphore acquire failed"); + } +#endif } bool Semaphore::try_acquire_for(uint32_t millisec) { +#if MBED_CONF_RTOS_PRESENT osStatus_t status = osSemaphoreAcquire(_id, millisec); if (status == osOK) { return true; @@ -113,10 +174,16 @@ bool Semaphore::try_acquire_for(uint32_t millisec) MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_KERNEL, MBED_ERROR_CODE_SEMAPHORE_LOCK_FAILED), "Semaphore acquire failed", status); } return false; +#else + sem_wait_capture capture = { this, false }; + mbed::internal::do_timed_sleep_relative_or_forever(millisec, semaphore_available, &capture); + return capture.acquired; +#endif } bool Semaphore::try_acquire_until(uint64_t millisec) { +#if MBED_CONF_RTOS_PRESENT uint64_t now = Kernel::get_ms_count(); if (now >= millisec) { @@ -127,16 +194,33 @@ bool Semaphore::try_acquire_until(uint64_t millisec) } else { return try_acquire_for(millisec - now); } +#else + sem_wait_capture capture = { this, false }; + mbed::internal::do_timed_sleep_absolute(millisec, semaphore_available, &capture); + return capture.acquired; +#endif } osStatus Semaphore::release(void) { +#if MBED_CONF_RTOS_PRESENT return osSemaphoreRelease(_id); +#else + int32_t old_count = core_util_atomic_load_s32(&_count); + do { + if (old_count == _max_count) { + return osErrorResource; + } + } while (!core_util_atomic_cas_s32(&_count, &old_count, old_count + 1)); +#endif + return osOK; } Semaphore::~Semaphore() { +#if MBED_CONF_RTOS_PRESENT osSemaphoreDelete(_id); +#endif } } diff --git a/rtos/Semaphore.h b/rtos/Semaphore.h index 9eaa116d05..8b89e7b48d 100644 --- a/rtos/Semaphore.h +++ b/rtos/Semaphore.h @@ -23,9 +23,9 @@ #define SEMAPHORE_H #include -#include "cmsis_os2.h" -#include "mbed_rtos1_types.h" -#include "mbed_rtos_storage.h" +#include "rtos/mbed_rtos_types.h" +#include "rtos/mbed_rtos1_types.h" +#include "rtos/mbed_rtos_storage.h" #include "platform/mbed_toolchain.h" #include "platform/NonCopyable.h" @@ -141,10 +141,16 @@ public: private: void constructor(int32_t count, uint16_t max_count); +#if MBED_CONF_RTOS_PRESENT int32_t _wait(uint32_t millisec); osSemaphoreId_t _id; mbed_rtos_storage_semaphore_t _obj_mem; +#else + static bool semaphore_available(void *); + int32_t _count; + uint16_t _max_count; +#endif }; /** @}*/ /** @}*/ diff --git a/rtos/TARGET_CORTEX/mbed_lib.json b/rtos/TARGET_CORTEX/mbed_lib.json new file mode 100644 index 0000000000..aed253aba5 --- /dev/null +++ b/rtos/TARGET_CORTEX/mbed_lib.json @@ -0,0 +1,57 @@ +{ + "name": "rtos", + "config": { + "present": 1, + "main-thread-stack-size": { + "help": "The size of the main thread's stack", + "value": 4096 + }, + "timer-thread-stack-size": { + "help": "The size of the timer thread's stack", + "value": 768 + }, + "idle-thread-stack-size": { + "help": "The size of the idle thread's stack", + "value": 512 + }, + "thread-stack-size": { + "help": "The default stack size of new threads", + "value": 4096 + }, + "idle-thread-stack-size-tickless-extra": { + "help": "Additional size to add to the idle thread when a specific target or application implementation requires it or in case tickless is enabled and LPTICKER_DELAY_TICKS is used", + "value": 256 + }, + "idle-thread-stack-size-debug-extra": { + "help": "Additional size to add to the idle thread when code compilation optimisation is disabled", + "value": 0 + } + }, + "macros": ["_RTE_"], + "target_overrides": { + "*": { + "target.boot-stack-size": "0x400" + }, + "STM": { + "idle-thread-stack-size-debug-extra": 128 + }, + "STM32L1": { + "idle-thread-stack-size-debug-extra": 512 + }, + "MCU_NRF51": { + "target.boot-stack-size": "0x800" + }, + "MCU_NRF52840": { + "target.boot-stack-size": "0x800" + }, + "MCU_NRF52832": { + "target.boot-stack-size": "0x800" + }, + "MCU_NRF51_UNIFIED": { + "target.boot-stack-size": "0x800" + }, + "NUVOTON": { + "idle-thread-stack-size-debug-extra": 512 + } + } +} diff --git a/rtos/TARGET_CORTEX/mbed_rtos1_types.h b/rtos/TARGET_CORTEX/mbed_rtos1_types.h deleted file mode 100644 index e44fa25edb..0000000000 --- a/rtos/TARGET_CORTEX/mbed_rtos1_types.h +++ /dev/null @@ -1,28 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2017 ARM Limited - * SPDX-License-Identifier: Apache-2.0 - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef MBED_RTOS_RTX1_TYPES_H -#define MBED_RTOS_RTX1_TYPES_H - -#include "rtx4/cmsis_os.h" - -#endif diff --git a/rtos/TARGET_CORTEX/mbed_rtos_storage.h b/rtos/TARGET_CORTEX/mbed_rtx_storage.h similarity index 97% rename from rtos/TARGET_CORTEX/mbed_rtos_storage.h rename to rtos/TARGET_CORTEX/mbed_rtx_storage.h index 2a0338baed..d14f78abc2 100644 --- a/rtos/TARGET_CORTEX/mbed_rtos_storage.h +++ b/rtos/TARGET_CORTEX/mbed_rtx_storage.h @@ -19,8 +19,8 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef MBED_RTOS_STORAGE_H -#define MBED_RTOS_STORAGE_H +#ifndef MBED_RTX_STORAGE_H +#define MBED_RTX_STORAGE_H #ifdef __cplusplus extern "C" { diff --git a/rtos/ThisThread.cpp b/rtos/ThisThread.cpp index 0e3b89d431..cd8af4eea8 100644 --- a/rtos/ThisThread.cpp +++ b/rtos/ThisThread.cpp @@ -23,39 +23,119 @@ #define __STDC_LIMIT_MACROS #include "rtos/ThisThread.h" +#include "platform/mbed_toolchain.h" #include "rtos/Kernel.h" -#include "rtos/rtos_idle.h" +#include "platform/CriticalSectionLock.h" #include "platform/mbed_assert.h" +#include "platform/mbed_critical.h" +#include "platform/mbed_os_timer.h" + +#if !MBED_CONF_RTOS_PRESENT +static uint32_t thread_flags; + +/* For the flags to be useful, need a way of setting them, but there's only the main + * thread, and that has no Thread object, so Thread class is not provided. Implement + * one CMSIS-RTOS function to provide access. + */ +extern "C" +uint32_t osThreadFlagsSet(osThreadId_t /*thread_id*/, uint32_t flags) +{ + return core_util_atomic_fetch_or_u32(&thread_flags, flags) | flags; +} +#endif namespace rtos { uint32_t ThisThread::flags_clear(uint32_t flags) { +#if MBED_CONF_RTOS_PRESENT flags = osThreadFlagsClear(flags); MBED_ASSERT(!(flags & osFlagsError)); +#else + flags = core_util_atomic_fetch_and_u32(&thread_flags, ~flags); +#endif return flags; } uint32_t ThisThread::flags_get() { +#if MBED_CONF_RTOS_PRESENT return osThreadFlagsGet(); +#else + return core_util_atomic_load_u32(&thread_flags); +#endif } +#if !MBED_CONF_RTOS_PRESENT +namespace internal { +bool non_rtos_check_flags(void *handle) +{ + flags_check_capture *check = static_cast(handle); + uint32_t cur_flags = core_util_atomic_load_u32(check->flags); + uint32_t set_flags; + do { + set_flags = cur_flags & check->flags_wanted; + check->result = set_flags; + if ((check->options & osFlagsWaitAll) ? set_flags == check->flags_wanted : set_flags != 0) { + if (check->options & osFlagsNoClear) { + break; + } + } else { + return false; + } + } while (!core_util_atomic_cas_u32(check->flags, &cur_flags, cur_flags & ~set_flags)); + check->match = true; + return true; +} +} +#endif + static uint32_t flags_wait_for(uint32_t flags, uint32_t millisec, bool clear, uint32_t options) { if (!clear) { options |= osFlagsNoClear; } +#if MBED_CONF_RTOS_PRESENT flags = osThreadFlagsWait(flags, options, millisec); if (flags & osFlagsError) { MBED_ASSERT((flags == osFlagsErrorTimeout && millisec != osWaitForever) || (flags == osFlagsErrorResource && millisec == 0)); flags = ThisThread::flags_get(); } +#else + rtos::internal::flags_check_capture check; + check.flags = &thread_flags; + check.options = options; + check.flags_wanted = flags; + check.result = 0; + mbed::internal::do_timed_sleep_relative_or_forever(millisec, rtos::internal::non_rtos_check_flags, &check); + flags = check.result; +#endif return flags; } +static uint32_t flags_wait(uint32_t flags, bool clear, uint32_t options) +{ +#if MBED_CONF_RTOS_PRESENT + return flags_wait_for(flags, osWaitForever, clear, options); +#else + /* Avoids pulling in timer if not used */ + if (!clear) { + options |= osFlagsNoClear; + } + rtos::internal::flags_check_capture check; + check.flags = &thread_flags; + check.options = options; + check.flags_wanted = flags; + check.result = 0; + mbed::internal::do_untimed_sleep(rtos::internal::non_rtos_check_flags, &check); + flags = check.result; + + return flags; +#endif +} + static uint32_t flags_wait_until(uint32_t flags, uint64_t millisec, bool clear, uint32_t options) { uint64_t now = Kernel::get_ms_count(); @@ -74,7 +154,7 @@ static uint32_t flags_wait_until(uint32_t flags, uint64_t millisec, bool clear, uint32_t ThisThread::flags_wait_all(uint32_t flags, bool clear) { - return flags_wait_for(flags, osWaitForever, clear, osFlagsWaitAll); + return flags_wait(flags, clear, osFlagsWaitAll); } uint32_t ThisThread::flags_wait_all_for(uint32_t flags, uint32_t millisec, bool clear) @@ -89,7 +169,7 @@ uint32_t ThisThread::flags_wait_all_until(uint32_t flags, uint64_t millisec, boo uint32_t ThisThread::flags_wait_any(uint32_t flags, bool clear) { - return flags_wait_for(flags, osWaitForever, clear, osFlagsWaitAny); + return flags_wait(flags, clear, osFlagsWaitAny); } uint32_t ThisThread::flags_wait_any_for(uint32_t flags, uint32_t millisec, bool clear) @@ -104,12 +184,18 @@ uint32_t ThisThread::flags_wait_any_until(uint32_t flags, uint64_t millisec, boo void ThisThread::sleep_for(uint32_t millisec) { +#if MBED_CONF_RTOS_PRESENT osStatus_t status = osDelay(millisec); MBED_ASSERT(status == osOK); +#else + // Undocumented, but osDelay(UINT32_MAX) does actually sleep forever + mbed::internal::do_timed_sleep_relative_or_forever(millisec); +#endif } void ThisThread::sleep_until(uint64_t millisec) { +#if MBED_CONF_RTOS_PRESENT // CMSIS-RTOS 2.1.0 had 64-bit time and osDelayUntil, but that's been revoked. // Limit ourselves to manual implementation assuming a >=32-bit osDelay. @@ -126,25 +212,42 @@ void ThisThread::sleep_until(uint64_t millisec) break; } } +#else + mbed::internal::do_timed_sleep_absolute(millisec); +#endif } void ThisThread::yield() { +#if MBED_CONF_RTOS_PRESENT osThreadYield(); +#else + asm("yield"); +#endif } osThreadId_t ThisThread::get_id() { +#if MBED_CONF_RTOS_PRESENT return osThreadGetId(); +#else + return (osThreadId_t) 1; // dummy non-0 value +#endif } const char *get_name() { +#if MBED_CONF_RTOS_PRESENT osThreadId_t id = osThreadGetId(); if (id == NULL) { return NULL; } return osThreadGetName(id); +#else + return NULL; +#endif } } + + diff --git a/rtos/ThisThread.h b/rtos/ThisThread.h index d566fb5397..492ad88113 100644 --- a/rtos/ThisThread.h +++ b/rtos/ThisThread.h @@ -23,14 +23,7 @@ #define THIS_THREAD_H #include -#include "cmsis_os2.h" -#include "mbed_rtos1_types.h" -#include "mbed_rtos_storage.h" -#include "platform/Callback.h" -#include "platform/mbed_toolchain.h" -#include "platform/NonCopyable.h" -#include "rtos/Semaphore.h" -#include "rtos/Mutex.h" +#include "rtos/mbed_rtos_types.h" namespace rtos { /** \addtogroup rtos */ @@ -188,6 +181,19 @@ const char *get_name(); }; /** @}*/ /** @}*/ + +namespace internal { +struct flags_check_capture { + uint32_t *flags; + uint32_t options; + uint32_t flags_wanted; + uint32_t result; + bool match; +}; + +bool non_rtos_check_flags(void *handle); + +} } #endif diff --git a/rtos/Thread.cpp b/rtos/Thread.cpp index 40154afe00..80827ab52d 100644 --- a/rtos/Thread.cpp +++ b/rtos/Thread.cpp @@ -26,6 +26,8 @@ #include "platform/mbed_assert.h" #include "platform/mbed_error.h" +#if MBED_CONF_RTOS_PRESENT + #define ALIGN_UP(pos, align) ((pos) % (align) ? (pos) + ((align) - (pos) % (align)) : (pos)) MBED_STATIC_ASSERT(ALIGN_UP(0, 8) == 0, "ALIGN_UP macro error"); MBED_STATIC_ASSERT(ALIGN_UP(1, 8) == 8, "ALIGN_UP macro error"); @@ -432,3 +434,5 @@ void Thread::_thunk(void *thread_ptr) } } + +#endif diff --git a/rtos/Thread.h b/rtos/Thread.h index 34da08aa24..f9e25d6f47 100644 --- a/rtos/Thread.h +++ b/rtos/Thread.h @@ -23,15 +23,17 @@ #define THREAD_H #include -#include "cmsis_os2.h" -#include "mbed_rtos1_types.h" -#include "mbed_rtos_storage.h" +#include "rtos/mbed_rtos_types.h" +#include "rtos/mbed_rtos1_types.h" +#include "rtos/mbed_rtos_storage.h" #include "platform/Callback.h" #include "platform/mbed_toolchain.h" #include "platform/NonCopyable.h" #include "rtos/Semaphore.h" #include "rtos/Mutex.h" +#if MBED_CONF_RTOS_PRESENT || defined(DOXYGEN_ONLY) || defined(UNITTEST) + namespace rtos { /** \addtogroup rtos */ /** @{*/ @@ -545,4 +547,4 @@ private: } #endif - +#endif diff --git a/rtos/mbed_lib.json b/rtos/mbed_lib.json index aed253aba5..43fb3abb77 100644 --- a/rtos/mbed_lib.json +++ b/rtos/mbed_lib.json @@ -1,57 +1,6 @@ { - "name": "rtos", - "config": { - "present": 1, - "main-thread-stack-size": { - "help": "The size of the main thread's stack", - "value": 4096 - }, - "timer-thread-stack-size": { - "help": "The size of the timer thread's stack", - "value": 768 - }, - "idle-thread-stack-size": { - "help": "The size of the idle thread's stack", - "value": 512 - }, - "thread-stack-size": { - "help": "The default stack size of new threads", - "value": 4096 - }, - "idle-thread-stack-size-tickless-extra": { - "help": "Additional size to add to the idle thread when a specific target or application implementation requires it or in case tickless is enabled and LPTICKER_DELAY_TICKS is used", - "value": 256 - }, - "idle-thread-stack-size-debug-extra": { - "help": "Additional size to add to the idle thread when code compilation optimisation is disabled", - "value": 0 - } - }, - "macros": ["_RTE_"], - "target_overrides": { - "*": { - "target.boot-stack-size": "0x400" - }, - "STM": { - "idle-thread-stack-size-debug-extra": 128 - }, - "STM32L1": { - "idle-thread-stack-size-debug-extra": 512 - }, - "MCU_NRF51": { - "target.boot-stack-size": "0x800" - }, - "MCU_NRF52840": { - "target.boot-stack-size": "0x800" - }, - "MCU_NRF52832": { - "target.boot-stack-size": "0x800" - }, - "MCU_NRF51_UNIFIED": { - "target.boot-stack-size": "0x800" - }, - "NUVOTON": { - "idle-thread-stack-size-debug-extra": 512 - } - } + "name": "rtos-api", + "config": { + "present": 1 + } } diff --git a/rtos/mbed_rtos1_types.h b/rtos/mbed_rtos1_types.h new file mode 100644 index 0000000000..e178b273c1 --- /dev/null +++ b/rtos/mbed_rtos1_types.h @@ -0,0 +1,30 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2019 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBED_RTOS_RTX1_TYPES_H +#define MBED_RTOS_RTX1_TYPES_H + +#if MBED_CONF_RTOS_PRESENT || defined(UNITTEST) + +#include "cmsis_os.h" + +#else + +typedef int32_t osStatus; + +#endif + +#endif diff --git a/rtos/mbed_rtos_storage.h b/rtos/mbed_rtos_storage.h new file mode 100644 index 0000000000..58eb8f4062 --- /dev/null +++ b/rtos/mbed_rtos_storage.h @@ -0,0 +1,28 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2019 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBED_RTOS_STORAGE_H +#define MBED_RTOS_STORAGE_H + +#if MBED_CONF_RTOS_PRESENT || defined(UNITTEST) + +#include "mbed_rtx_storage.h" + +#endif + +#endif + +/** @}*/ diff --git a/rtos/mbed_rtos_types.h b/rtos/mbed_rtos_types.h new file mode 100644 index 0000000000..3584b6dece --- /dev/null +++ b/rtos/mbed_rtos_types.h @@ -0,0 +1,76 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2019, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef RTOS_TYPES_H_ +#define RTOS_TYPES_H_ + +#if MBED_CONF_RTOS_PRESENT || defined(DOXYGEN_ONLY) || defined(UNITTEST) +#include "cmsis_os2.h" +#else + +#ifdef __cplusplus +extern "C" { +#endif + +/* Minimal definitions for bare metal form of RTOS */ + +// Timeout value. +#define osWaitForever 0xFFFFFFFFU ///< Wait forever timeout value. + +// Flags options (\ref osThreadFlagsWait and \ref osEventFlagsWait). +#define osFlagsWaitAny 0x00000000U ///< Wait for any flag (default). +#define osFlagsWaitAll 0x00000001U ///< Wait for all flags. +#define osFlagsNoClear 0x00000002U ///< Do not clear flags which have been specified to wait for. + +// Flags errors (returned by osThreadFlagsXxxx and osEventFlagsXxxx). +#define osFlagsError 0x80000000U ///< Error indicator. +#define osFlagsErrorUnknown 0xFFFFFFFFU ///< osError (-1). +#define osFlagsErrorTimeout 0xFFFFFFFEU ///< osErrorTimeout (-2). +#define osFlagsErrorResource 0xFFFFFFFDU ///< osErrorResource (-3). +#define osFlagsErrorParameter 0xFFFFFFFCU ///< osErrorParameter (-4). +#define osFlagsErrorISR 0xFFFFFFFAU ///< osErrorISR (-6). + +// Status code values returned by CMSIS-RTOS functions. +typedef enum { + osOK = 0, ///< Operation completed successfully. + osError = -1, ///< Unspecified RTOS error: run-time error but no other error message fits. + osErrorTimeout = -2, ///< Operation not completed within the timeout period. + osErrorResource = -3, ///< Resource not available. + osErrorParameter = -4, ///< Parameter error. + osErrorNoMemory = -5, ///< System is out of memory: it was impossible to allocate or reserve memory for the operation. + osErrorISR = -6, ///< Not allowed in ISR context: the function cannot be called from interrupt service routines. + osStatusReserved = 0x7FFFFFFF ///< Prevents enum down-size compiler optimization. +} osStatus_t; + + +// \details Thread ID identifies the thread. +typedef void *osThreadId_t; + +// Set the specified Thread Flags of a thread. +// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. +// \param[in] flags specifies the flags of the thread that shall be set. +// \return thread flags after setting or error code if highest bit set. +uint32_t osThreadFlagsSet(osThreadId_t thread_id, uint32_t flags); + +#ifdef __cplusplus +} +#endif + +#endif + + + +#endif /* RTOS_TYPES_H_ */ diff --git a/rtos/rtos.h b/rtos/rtos.h index c2d4ad5a98..b480d25dfc 100644 --- a/rtos/rtos.h +++ b/rtos/rtos.h @@ -25,7 +25,7 @@ #ifndef RTOS_H #define RTOS_H -#include "mbed_rtos_storage.h" +#include "rtos/mbed_rtos_storage.h" #include "rtos/Kernel.h" #include "rtos/Thread.h" #include "rtos/ThisThread.h" diff --git a/rtos/rtos_handlers.h b/rtos/rtos_handlers.h index e3d474300f..351682b12b 100644 --- a/rtos/rtos_handlers.h +++ b/rtos/rtos_handlers.h @@ -25,7 +25,7 @@ #ifndef RTOS_HANDLERS_H #define RTOS_HANDLERS_H -#include "cmsis_os2.h" +#include "rtos/mbed_rtos_types.h" #ifdef __cplusplus extern "C" { From 04cb39da0799d3c5bc1a837e56b93000328f1dbc Mon Sep 17 00:00:00 2001 From: Kevin Bracey Date: Thu, 14 Mar 2019 17:08:30 +0200 Subject: [PATCH 07/17] Minimal C thread API --- mbed.h | 1 + platform/mbed_thread.cpp | 59 +++++++++++++++++++++++++++++++++++ platform/mbed_thread.h | 67 ++++++++++++++++++++++++++++++++++++++++ rtos/Kernel.cpp | 8 ++++- rtos/ThisThread.cpp | 9 ++++-- 5 files changed, 140 insertions(+), 4 deletions(-) create mode 100644 platform/mbed_thread.cpp create mode 100644 platform/mbed_thread.h diff --git a/mbed.h b/mbed.h index 4f6f6f6024..3e851b4d36 100644 --- a/mbed.h +++ b/mbed.h @@ -87,6 +87,7 @@ #include "platform/LocalFileSystem.h" #include "drivers/InterruptIn.h" #include "platform/mbed_wait_api.h" +#include "platform/mbed_thread.h" #include "hal/sleep_api.h" #include "platform/Atomic.h" #include "platform/mbed_power_mgmt.h" diff --git a/platform/mbed_thread.cpp b/platform/mbed_thread.cpp new file mode 100644 index 0000000000..0cdcae1549 --- /dev/null +++ b/platform/mbed_thread.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2019, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "platform/mbed_thread.h" +#include "platform/mbed_critical.h" +#include "platform/mbed_os_timer.h" + +/* If the RTOS is present, we call the RTOS API to do the work */ +/* If the RTOS is not present, the RTOS API calls us to do the work */ +#if MBED_CONF_RTOS_PRESENT +#include "rtos/Kernel.h" +#include "rtos/ThisThread.h" +#endif + +extern "C" { + + uint64_t get_ms_count(void) + { +#if MBED_CONF_RTOS_PRESENT + return rtos::Kernel::get_ms_count(); +#else + return mbed::internal::init_os_timer()->update_and_get_tick(); +#endif + } + + void thread_sleep_for(uint32_t millisec) + { +#if MBED_CONF_RTOS_PRESENT + rtos::ThisThread::sleep_for(millisec); +#else + // Undocumented, but osDelay(UINT32_MAX) does actually sleep forever + mbed::internal::do_timed_sleep_relative_or_forever(millisec); +#endif + } + + void thread_sleep_until(uint64_t millisec) + { +#if MBED_CONF_RTOS_PRESENT + rtos::ThisThread::sleep_until(millisec); +#else + mbed::internal::do_timed_sleep_absolute(millisec); +#endif + } + +} diff --git a/platform/mbed_thread.h b/platform/mbed_thread.h new file mode 100644 index 0000000000..6968ebd62f --- /dev/null +++ b/platform/mbed_thread.h @@ -0,0 +1,67 @@ +/* mbed Microcontroller Library + * Copyright (c) 2019 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBED_THREAD_H +#define MBED_THREAD_H +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** Generic thread functions. + * + * These are C versions of functions provided in C++ via rtos::Thread and rtos::ThisThread + */ + +/** Read the current RTOS kernel millisecond tick count. + The tick count corresponds to the tick count the RTOS uses for timing + purposes. It increments monotonically from 0 at boot, so it effectively + never wraps. If the underlying RTOS only provides a 32-bit tick count, + this method expands it to 64 bits. + @return RTOS kernel current tick count + @note Mbed OS always uses millisecond RTOS ticks, and this could only wrap + after half a billion years. + @note In a non-RTOS build, this computes an equivalent time in milliseconds, + based on a HAL timer. The time may be referenced as 0 on first call. + @note You cannot call this function from ISR context. + @note The equivalent functionality is accessible in C++ via rtos::Kernel::get_ms_count. + */ +uint64_t get_ms_count(void); + +/** Sleep for a specified time period in millisec: + @param millisec time delay value + @note You cannot call this function from ISR context. + @note The equivalent functionality is accessible in C++ via rtos::ThisThread::sleep_for. +*/ +void thread_sleep_for(uint32_t millisec); + +/** Sleep until a specified time in millisec + The specified time is according to Kernel::get_ms_count(). + @param millisec absolute time in millisec + @note You cannot call this function from ISR context. + @note if millisec is equal to or lower than the current tick count, this + returns immediately. + @note The equivalent functionality is accessible in C++ via ThisThread::sleep_until. +*/ +void thread_sleep_until(uint64_t millisec); + +#ifdef __cplusplus +} +#endif + + +#endif //MBED_THREAD_H diff --git a/rtos/Kernel.cpp b/rtos/Kernel.cpp index 4751bee053..21664292a1 100644 --- a/rtos/Kernel.cpp +++ b/rtos/Kernel.cpp @@ -26,6 +26,12 @@ #include "platform/mbed_critical.h" #include "platform/mbed_os_timer.h" +#if !MBED_CONF_RTOS_PRESENT +/* If the RTOS is not present, we call mbed_thread.cpp to do the work */ +/* If the RTOS is present, mbed_thread.cpp calls us to do the work */ +#include "platform/mbed_thread.h" +#endif + namespace rtos { uint64_t Kernel::get_ms_count() @@ -63,7 +69,7 @@ uint64_t Kernel::get_ms_count() return ret; } #else - return mbed::internal::init_os_timer()->update_and_get_tick(); + return ::get_ms_count(); #endif } diff --git a/rtos/ThisThread.cpp b/rtos/ThisThread.cpp index cd8af4eea8..50286c214d 100644 --- a/rtos/ThisThread.cpp +++ b/rtos/ThisThread.cpp @@ -31,6 +31,10 @@ #include "platform/mbed_os_timer.h" #if !MBED_CONF_RTOS_PRESENT +/* If the RTOS is not present, we call mbed_thread.cpp to do the work */ +/* If the RTOS is present, mbed_thread.cpp calls us to do the work */ +#include "platform/mbed_thread.h" + static uint32_t thread_flags; /* For the flags to be useful, need a way of setting them, but there's only the main @@ -188,8 +192,7 @@ void ThisThread::sleep_for(uint32_t millisec) osStatus_t status = osDelay(millisec); MBED_ASSERT(status == osOK); #else - // Undocumented, but osDelay(UINT32_MAX) does actually sleep forever - mbed::internal::do_timed_sleep_relative_or_forever(millisec); + thread_sleep_for(millisec); #endif } @@ -213,7 +216,7 @@ void ThisThread::sleep_until(uint64_t millisec) } } #else - mbed::internal::do_timed_sleep_absolute(millisec); + thread_sleep_until(millisec); #endif } From fc8e8f67c600a46ccf17d473bd2cbf3ec4796e54 Mon Sep 17 00:00:00 2001 From: Kevin Bracey Date: Mon, 28 Jan 2019 12:49:01 +0200 Subject: [PATCH 08/17] Deprecate wait/wait_ms APIs --- .../AT/at_cellularsms/unittest.cmake | 2 +- .../framework/AT/athandler/unittest.cmake | 1 - UNITTESTS/stubs/UARTSerial_stub.cpp | 5 ---- .../COMPONENT_SPIF/SPIFBlockDevice.cpp | 4 +-- drivers/UARTSerial.cpp | 24 +++------------ drivers/UARTSerial.h | 2 -- features/cellular/framework/AT/ATHandler.cpp | 1 - platform/PlatformMutex.h | 3 +- platform/mbed_poll.cpp | 30 +++---------------- platform/mbed_wait_api.h | 21 ++++++++++++- platform/mbed_wait_api_rtos.cpp | 7 +++-- rtos/ThisThread.h | 2 ++ 12 files changed, 40 insertions(+), 62 deletions(-) diff --git a/UNITTESTS/features/cellular/framework/AT/at_cellularsms/unittest.cmake b/UNITTESTS/features/cellular/framework/AT/at_cellularsms/unittest.cmake index 616b49e49a..484235c818 100644 --- a/UNITTESTS/features/cellular/framework/AT/at_cellularsms/unittest.cmake +++ b/UNITTESTS/features/cellular/framework/AT/at_cellularsms/unittest.cmake @@ -26,5 +26,5 @@ set(unittest-test-sources stubs/CellularUtil_stub.cpp stubs/us_ticker_stub.cpp stubs/mbed_assert_stub.c - stubs/mbed_wait_api_stub.cpp + stubs/ThisThread_stub.cpp ) diff --git a/UNITTESTS/features/cellular/framework/AT/athandler/unittest.cmake b/UNITTESTS/features/cellular/framework/AT/athandler/unittest.cmake index db74d7adc7..b3e55b5260 100644 --- a/UNITTESTS/features/cellular/framework/AT/athandler/unittest.cmake +++ b/UNITTESTS/features/cellular/framework/AT/athandler/unittest.cmake @@ -23,7 +23,6 @@ set(unittest-test-sources stubs/EventQueue_stub.cpp stubs/FileHandle_stub.cpp stubs/us_ticker_stub.cpp - stubs/mbed_wait_api_stub.cpp stubs/mbed_assert_stub.c stubs/mbed_poll_stub.cpp stubs/Timer_stub.cpp diff --git a/UNITTESTS/stubs/UARTSerial_stub.cpp b/UNITTESTS/stubs/UARTSerial_stub.cpp index ebfd83d203..7b03671fe6 100644 --- a/UNITTESTS/stubs/UARTSerial_stub.cpp +++ b/UNITTESTS/stubs/UARTSerial_stub.cpp @@ -130,11 +130,6 @@ int UARTSerial::enable_output(bool enabled) return 0; } -void UARTSerial::wait_ms(uint32_t millisec) -{ - -} - void UARTSerial::set_flow_control(mbed::SerialBase::Flow, PinName, PinName) { diff --git a/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp index 0882276649..cce0957afd 100644 --- a/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp @@ -15,10 +15,10 @@ */ #include "SPIFBlockDevice.h" +#include "rtos/ThisThread.h" #include "mbed_critical.h" #include -#include "mbed_wait_api.h" #include "mbed_trace.h" #define TRACE_GROUP "SPIF" @@ -910,7 +910,7 @@ bool SPIFBlockDevice::_is_mem_ready() bool mem_ready = true; do { - wait_ms(1); + rtos::ThisThread::sleep_for(1); retries++; //Read the Status Register from device if (SPIF_BD_ERROR_OK != _spi_send_general_command(SPIF_RDSR, SPI_NO_ADDRESS_COMMAND, NULL, 0, status_value, diff --git a/drivers/UARTSerial.cpp b/drivers/UARTSerial.cpp index e9213555d7..37e992c7ff 100644 --- a/drivers/UARTSerial.cpp +++ b/drivers/UARTSerial.cpp @@ -19,12 +19,7 @@ #if (DEVICE_SERIAL && DEVICE_INTERRUPTIN) #include "platform/mbed_poll.h" - -#if MBED_CONF_RTOS_PRESENT -#include "rtos/ThisThread.h" -#else -#include "platform/mbed_wait_api.h" -#endif +#include "platform/mbed_thread.h" namespace mbed { @@ -114,7 +109,7 @@ int UARTSerial::sync() while (!_txbuf.empty()) { api_unlock(); // Doing better than wait would require TxIRQ to also do wake() when becoming empty. Worth it? - wait_ms(1); + thread_sleep_for(1); api_lock(); } @@ -178,7 +173,7 @@ ssize_t UARTSerial::write(const void *buffer, size_t length) } do { api_unlock(); - wait_ms(1); // XXX todo - proper wait, WFE for non-rtos ? + thread_sleep_for(1); // XXX todo - proper wait? api_lock(); } while (_txbuf.full()); } @@ -221,7 +216,7 @@ ssize_t UARTSerial::read(void *buffer, size_t length) return -EAGAIN; } api_unlock(); - wait_ms(1); // XXX todo - proper wait, WFE for non-rtos ? + thread_sleep_for(1); // XXX todo - proper wait? api_lock(); } @@ -407,17 +402,6 @@ int UARTSerial::enable_output(bool enabled) return 0; } -void UARTSerial::wait_ms(uint32_t millisec) -{ - /* wait_ms implementation for RTOS spins until exact microseconds - we - * want to just sleep until next tick. - */ -#if MBED_CONF_RTOS_PRESENT - rtos::ThisThread::sleep_for(millisec); -#else - ::wait_ms(millisec); -#endif -} } //namespace mbed #endif //(DEVICE_SERIAL && DEVICE_INTERRUPTIN) diff --git a/drivers/UARTSerial.h b/drivers/UARTSerial.h index 2959ce77e2..5f6d6faee6 100644 --- a/drivers/UARTSerial.h +++ b/drivers/UARTSerial.h @@ -255,8 +255,6 @@ public: private: - void wait_ms(uint32_t millisec); - /** SerialBase lock override */ virtual void lock(void); diff --git a/features/cellular/framework/AT/ATHandler.cpp b/features/cellular/framework/AT/ATHandler.cpp index d016415a96..0f599d7532 100644 --- a/features/cellular/framework/AT/ATHandler.cpp +++ b/features/cellular/framework/AT/ATHandler.cpp @@ -21,7 +21,6 @@ #include "ATHandler.h" #include "mbed_poll.h" #include "FileHandle.h" -#include "mbed_wait_api.h" #include "mbed_debug.h" #include "rtos/ThisThread.h" #include "Kernel.h" diff --git a/platform/PlatformMutex.h b/platform/PlatformMutex.h index a63672dc0c..3f751c4149 100644 --- a/platform/PlatformMutex.h +++ b/platform/PlatformMutex.h @@ -37,8 +37,9 @@ * - When the RTOS is absent, all methods are defined as noop. */ -#ifdef MBED_CONF_RTOS_PRESENT +#ifdef MBED_CONF_RTOS_API_PRESENT +// rtos::Mutex is itself a dummy class if the RTOS API is present, but not the RTOS #include "rtos/Mutex.h" typedef rtos::Mutex PlatformMutex; diff --git a/platform/mbed_poll.cpp b/platform/mbed_poll.cpp index a1e7627616..b25c8f043a 100644 --- a/platform/mbed_poll.cpp +++ b/platform/mbed_poll.cpp @@ -16,14 +16,7 @@ */ #include "mbed_poll.h" #include "FileHandle.h" -#if MBED_CONF_RTOS_PRESENT -#include "rtos/Kernel.h" -#include "rtos/ThisThread.h" -using namespace rtos; -#else -#include "drivers/Timer.h" -#include "drivers/LowPowerTimer.h" -#endif +#include "mbed_thread.h" namespace mbed { @@ -39,23 +32,10 @@ int poll(pollfh fhs[], unsigned nfhs, int timeout) * interested in. In future, his spinning behaviour will be replaced with * condition variables. */ -#if MBED_CONF_RTOS_PRESENT uint64_t start_time = 0; if (timeout > 0) { - start_time = Kernel::get_ms_count(); + start_time = get_ms_count(); } -#define TIME_ELAPSED() int64_t(Kernel::get_ms_count() - start_time) -#else -#if MBED_CONF_PLATFORM_POLL_USE_LOWPOWER_TIMER - LowPowerTimer timer; -#else - Timer timer; -#endif - if (timeout > 0) { - timer.start(); - } -#define TIME_ELAPSED() timer.read_ms() -#endif // MBED_CONF_RTOS_PRESENT int count = 0; for (;;) { @@ -78,14 +58,12 @@ int poll(pollfh fhs[], unsigned nfhs, int timeout) } /* Nothing selected - this is where timeout handling would be needed */ - if (timeout == 0 || (timeout > 0 && TIME_ELAPSED() > timeout)) { + if (timeout == 0 || (timeout > 0 && int64_t(get_ms_count() - start_time) > timeout)) { break; } -#ifdef MBED_CONF_RTOS_PRESENT // TODO - proper blocking // wait for condition variable, wait queue whatever here - rtos::ThisThread::sleep_for(1); -#endif + thread_sleep_for(1); } return count; } diff --git a/platform/mbed_wait_api.h b/platform/mbed_wait_api.h index a614212092..f6e72266a8 100644 --- a/platform/mbed_wait_api.h +++ b/platform/mbed_wait_api.h @@ -25,6 +25,7 @@ #ifndef MBED_WAIT_API_H #define MBED_WAIT_API_H +#include "platform/mbed_toolchain.h" #include "platform/mbed_atomic.h" #include "device.h" @@ -62,7 +63,16 @@ extern "C" { * If the RTOS is present, this function spins to get the exact number of microseconds for * 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`. + * + * @deprecated + * 'wait' is deprecated in favor of explicit sleep functions. To sleep, 'wait' should be replaced by + * 'ThisThread::sleep_for' (C++) or 'thread_sleep_for' (C). If you wish to wait (without sleeping), call + * 'wait_us'. 'wait_us' is safe to call from ISR context. */ +MBED_DEPRECATED_SINCE("mbed-os-5.14", + "'wait' is deprecated in favor of explicit sleep functions. To sleep, 'wait' should be replaced by " + "'ThisThread::sleep_for' (C++) or 'thread_sleep_for' (C). If you wish to wait (without sleeping), call " + "'wait_us'. 'wait_us' is safe to call from ISR context.") void wait(float s); /** Waits a number of milliseconds. @@ -72,7 +82,16 @@ void wait(float s); * @note * 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. + * + * @deprecated + * 'wait_ms' is deprecated in favor of explicit sleep functions. To sleep, 'wait_ms' should be replaced by + * 'ThisThread::sleep_for' (C++) or 'thread_sleep_for' (C). If you wish to wait (without sleeping), call + * 'wait_us'. 'wait_us' is safe to call from ISR context. */ +MBED_DEPRECATED_SINCE("mbed-os-5.14", + "'wait_ms' is deprecated in favor of explicit sleep functions. To sleep, 'wait_ms' should be replaced by " + "'ThisThread::sleep_for' (C++) or 'thread_sleep_for' (C). If you wish to wait (without sleeping), call " + "'wait_us'. 'wait_us' is safe to call from ISR context.") void wait_ms(int ms); /** Waits a number of microseconds. @@ -82,7 +101,7 @@ void wait_ms(int ms); * @note * This function always spins to get the exact number of microseconds. * This will affect power and multithread performance. Therefore, spinning for - * millisecond wait is not recommended, and wait_ms() should + * millisecond wait is not recommended, and ThisThread::sleep_for should * be used instead. * * @note You may call this function from ISR context, but large delays may diff --git a/platform/mbed_wait_api_rtos.cpp b/platform/mbed_wait_api_rtos.cpp index b4333ba45f..da2c0f464e 100644 --- a/platform/mbed_wait_api_rtos.cpp +++ b/platform/mbed_wait_api_rtos.cpp @@ -16,7 +16,10 @@ */ // This implementation of the wait functions will be compiled only -// if the RTOS is present. +// if the RTOS is present. Note that we still use these old +// bare metal versions of wait and wait_ms rather than using +// thread_sleep_for for backwards compatibility. People should +// be prompted to shift via their deprecation. #ifdef MBED_CONF_RTOS_PRESENT #include "platform/mbed_wait_api.h" @@ -30,7 +33,7 @@ void wait(float s) { if ((s >= 0.01f) && core_util_are_interrupts_enabled()) { - wait_ms(s * 1000.0f); + rtos::ThisThread::sleep_for(s * 1000.0f); return; } diff --git a/rtos/ThisThread.h b/rtos/ThisThread.h index 492ad88113..c7278c7f6c 100644 --- a/rtos/ThisThread.h +++ b/rtos/ThisThread.h @@ -147,6 +147,7 @@ uint32_t flags_wait_any_until(uint32_t flags, uint64_t millisec, bool clear = tr /** Sleep for a specified time period in millisec: @param millisec time delay value @note You cannot call this function from ISR context. + @note The equivalent functionality is accessible in C via thread_sleep_for. */ void sleep_for(uint32_t millisec); @@ -156,6 +157,7 @@ void sleep_for(uint32_t millisec); @note You cannot call this function from ISR context. @note if millisec is equal to or lower than the current tick count, this returns immediately. + @note The equivalent functionality is accessible in C via thread_sleep_until. */ void sleep_until(uint64_t millisec); From a522dcfa0acc5ab22f092abab57cc39f9b2ae87d Mon Sep 17 00:00:00 2001 From: Kevin Bracey Date: Mon, 18 Mar 2019 10:59:51 +0200 Subject: [PATCH 09/17] Replace deprecated wait calls --- TESTS/mbed_drivers/timeout/timeout_tests.h | 4 +-- TESTS/mbed_hal/rtc/main.cpp | 4 +-- TESTS/mbed_platform/error_handling/main.cpp | 2 +- .../netsocket/dns/asynchronous_dns_cancel.cpp | 2 +- .../asynchronous_dns_external_event_queue.cpp | 2 +- .../dns/asynchronous_dns_timeouts.cpp | 2 +- .../udp/udpsocket_echotest_burst.cpp | 2 +- .../netsocket/udp/udpsocket_sendto_repeat.cpp | 2 +- .../interface/networkinterface_status.cpp | 2 +- TEST_APPS/device/socket_app/cmd_socket.cpp | 2 +- .../source/NanostackRfPhyAtmel.cpp | 19 ++++++------ .../source/NanostackRfPhys2lp.cpp | 4 +-- .../STModCellular.cpp | 30 +++++++++---------- .../DataFlashBlockDevice.cpp | 4 +-- .../COMPONENT_QSPIF/QSPIFBlockDevice.cpp | 4 +-- .../SPIFReducedBlockDevice.cpp | 8 ++--- .../COMPONENT_SD/SDBlockDevice.cpp | 4 +-- .../MbedTester.cpp | 3 +- .../wifi/esp8266-driver/ESP8266Interface.cpp | 5 ++-- .../framework/AT/AT_CellularContext.cpp | 5 ++-- .../cellular/framework/AT/AT_CellularSMS.cpp | 17 ++++++----- .../UBLOX/AT/UBLOX_AT_CellularContext.cpp | 2 +- .../targets/UBLOX/AT/UBLOX_AT_CellularStack.h | 2 +- features/storage/nvstore/source/nvstore.cpp | 4 +-- rtos/RtosTimer.h | 2 +- .../TARGET_UBLOX_C027/onboard_modem_api.c | 6 ++-- .../TARGET_UBLOX_C027/ublox_low_level_api.c | 13 ++++---- .../TARGET_Realtek/TARGET_AMEBA/rtw_emac.cpp | 3 +- .../onboard_modem_api.c | 8 ++--- .../onboard_modem_api.c | 8 ++--- .../TARGET_UBLOX_C030/onboard_modem_api.c | 3 +- .../OdinWiFiInterface.cpp | 2 +- .../TARGET_WIO_3G/onboard_modem_api.c | 14 ++++----- .../TARGET_WIO_BG96/onboard_modem_api.c | 12 ++++---- .../onboard_modem_api.c | 4 +-- usb/device/USBHID/USBMouse.cpp | 7 ++--- usb/device/USBHID/USBMouseKeyboard.cpp | 6 ++-- 37 files changed, 113 insertions(+), 110 deletions(-) diff --git a/TESTS/mbed_drivers/timeout/timeout_tests.h b/TESTS/mbed_drivers/timeout/timeout_tests.h index fd71cb6a1b..534901c1fb 100644 --- a/TESTS/mbed_drivers/timeout/timeout_tests.h +++ b/TESTS/mbed_drivers/timeout/timeout_tests.h @@ -313,9 +313,9 @@ void test_deepsleep(void) * This should be replaced with a better function that checks if the * hardware buffers are empty. However, such an API does not exist now, - * so we'll use the wait_ms() function for now. + * so we'll use the ThisThread::sleep_for() function for now. */ - wait_ms(20); + ThisThread::sleep_for(20); timer.start(); timeout.attach_callback(mbed::callback(sem_callback, &sem), delay_us); diff --git a/TESTS/mbed_hal/rtc/main.cpp b/TESTS/mbed_hal/rtc/main.cpp index bd65e38cd4..f56383dcb1 100644 --- a/TESTS/mbed_hal/rtc/main.cpp +++ b/TESTS/mbed_hal/rtc/main.cpp @@ -125,7 +125,7 @@ void rtc_persist_test() rtc_write(start); rtc_free(); - wait(WAIT_TIME); + ThisThread::sleep_for(WAIT_TIME * 1000); rtc_init(); const uint32_t stop = rtc_read(); @@ -167,7 +167,7 @@ void rtc_range_test() for (uint32_t i = 0; i < sizeof(starts) / sizeof(starts[0]); i++) { const uint32_t start = starts[i]; rtc_write(start); - wait(WAIT_TIME); + ThisThread::sleep_for(WAIT_TIME * 1000); const uint32_t stop = rtc_read(); TEST_ASSERT_UINT32_WITHIN(WAIT_TOLERANCE, WAIT_TIME, stop - start); } diff --git a/TESTS/mbed_platform/error_handling/main.cpp b/TESTS/mbed_platform/error_handling/main.cpp index a72c56bb25..f961edbf76 100644 --- a/TESTS/mbed_platform/error_handling/main.cpp +++ b/TESTS/mbed_platform/error_handling/main.cpp @@ -228,7 +228,7 @@ void test_error_logging_multithread() errThread[i] = new Thread(osPriorityNormal1, THREAD_STACK_SIZE, NULL, NULL); errThread[i]->start(callback(err_thread_func, &error_status[i])); } - wait(2.0); + ThisThread::sleep_for(2000); for (i = 0; i < NUM_TEST_THREADS; i++) { errThread[i]->join(); } diff --git a/TESTS/netsocket/dns/asynchronous_dns_cancel.cpp b/TESTS/netsocket/dns/asynchronous_dns_cancel.cpp index 28e75879d6..1f9c6f8436 100644 --- a/TESTS/netsocket/dns/asynchronous_dns_cancel.cpp +++ b/TESTS/netsocket/dns/asynchronous_dns_cancel.cpp @@ -81,5 +81,5 @@ void ASYNCHRONOUS_DNS_CANCEL() delete[] data; - wait(5.0); + ThisThread::sleep_for(5000); } diff --git a/TESTS/netsocket/dns/asynchronous_dns_external_event_queue.cpp b/TESTS/netsocket/dns/asynchronous_dns_external_event_queue.cpp index 2a2493a76d..41685a1ea6 100644 --- a/TESTS/netsocket/dns/asynchronous_dns_external_event_queue.cpp +++ b/TESTS/netsocket/dns/asynchronous_dns_external_event_queue.cpp @@ -79,7 +79,7 @@ void ASYNCHRONOUS_DNS_EXTERNAL_EVENT_QUEUE() TEST_ASSERT_EQUAL(0, result_exp_timeout); // Give event queue time to finalise before destructors - wait(2.0); + ThisThread::sleep_for(2000); nsapi_dns_call_in_set(0); } diff --git a/TESTS/netsocket/dns/asynchronous_dns_timeouts.cpp b/TESTS/netsocket/dns/asynchronous_dns_timeouts.cpp index 30b1ef537a..a22fb2fcf9 100644 --- a/TESTS/netsocket/dns/asynchronous_dns_timeouts.cpp +++ b/TESTS/netsocket/dns/asynchronous_dns_timeouts.cpp @@ -74,7 +74,7 @@ void ASYNCHRONOUS_DNS_TIMEOUTS() TEST_ASSERT(result_exp_timeout > 0); // Give event queue time to finalise before destructors - wait(2.0); + ThisThread::sleep_for(2000); nsapi_dns_call_in_set(0); } diff --git a/TESTS/netsocket/udp/udpsocket_echotest_burst.cpp b/TESTS/netsocket/udp/udpsocket_echotest_burst.cpp index aee4d74854..fc5bb14d28 100644 --- a/TESTS/netsocket/udp/udpsocket_echotest_burst.cpp +++ b/TESTS/netsocket/udp/udpsocket_echotest_burst.cpp @@ -110,7 +110,7 @@ void UDPSOCKET_ECHOTEST_BURST() } else if (recvd < 0) { pkg_fail += BURST_PKTS - j; // Assume all the following packets of the burst to be lost printf("[%02d] network error %d\n", i, recvd); - wait(recv_timeout); + ThisThread::sleep_for(recv_timeout * 1000); recv_timeout *= 2; // Back off, break; } else if (temp_addr != udp_addr) { diff --git a/TESTS/netsocket/udp/udpsocket_sendto_repeat.cpp b/TESTS/netsocket/udp/udpsocket_sendto_repeat.cpp index 3983c97b0d..bd716e12ca 100644 --- a/TESTS/netsocket/udp/udpsocket_sendto_repeat.cpp +++ b/TESTS/netsocket/udp/udpsocket_sendto_repeat.cpp @@ -45,7 +45,7 @@ void UDPSOCKET_SENDTO_REPEAT() break; } oom_earlier = true; - wait(1); + ThisThread::sleep_for(1000); continue; } oom_earlier = false; diff --git a/TESTS/network/interface/networkinterface_status.cpp b/TESTS/network/interface/networkinterface_status.cpp index fbff8c551d..f4ebe5d9ad 100644 --- a/TESTS/network/interface/networkinterface_status.cpp +++ b/TESTS/network/interface/networkinterface_status.cpp @@ -153,7 +153,7 @@ void NETWORKINTERFACE_STATUS_GET() TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, err); while (net->get_connection_status() != NSAPI_STATUS_GLOBAL_UP) { - wait(0.5); + ThisThread::sleep_for(500); } err = net->disconnect(); diff --git a/TEST_APPS/device/socket_app/cmd_socket.cpp b/TEST_APPS/device/socket_app/cmd_socket.cpp index d07c4e8f00..454bab8fa2 100644 --- a/TEST_APPS/device/socket_app/cmd_socket.cpp +++ b/TEST_APPS/device/socket_app/cmd_socket.cpp @@ -944,7 +944,7 @@ static void bg_traffic_thread(SInfo *info) tr_err("Background sent: \"%s\"", sbuffer); tr_err("Background received: \"%s\"", rbuffer); } - wait_ms(10); + ThisThread::sleep_for(10); } } diff --git a/components/802.15.4_RF/atmel-rf-driver/source/NanostackRfPhyAtmel.cpp b/components/802.15.4_RF/atmel-rf-driver/source/NanostackRfPhyAtmel.cpp index ff6bc0cc10..287d5023de 100644 --- a/components/802.15.4_RF/atmel-rf-driver/source/NanostackRfPhyAtmel.cpp +++ b/components/802.15.4_RF/atmel-rf-driver/source/NanostackRfPhyAtmel.cpp @@ -525,14 +525,14 @@ static void rf_if_reset_radio(void) #endif rf->IRQ.rise(0); rf->RST = 1; - wait_ms(1); + ThisThread::sleep_for(2); rf->RST = 0; - wait_ms(10); + ThisThread::sleep_for(10); CS_RELEASE(); rf->SLP_TR = 0; - wait_ms(10); + ThisThread::sleep_for(10); rf->RST = 1; - wait_ms(10); + ThisThread::sleep_for(10); rf->IRQ.rise(&rf_if_interrupt_handler); } @@ -883,15 +883,16 @@ static uint8_t rf_if_read_rnd(void) rf_if_write_register(TRX_RPC, RX_RPC_CTRL | TRX_RPC_RSVD_1); } - wait_ms(1); + + wait_ns(1000); temp = ((rf_if_read_register(PHY_RSSI) >> 5) << 6); - wait_ms(1); + wait_ns(1000); temp |= ((rf_if_read_register(PHY_RSSI) >> 5) << 4); - wait_ms(1); + wait_ns(1000); temp |= ((rf_if_read_register(PHY_RSSI) >> 5) << 2); - wait_ms(1); + wait_ns(1000); temp |= ((rf_if_read_register(PHY_RSSI) >> 5)); - wait_ms(1); + wait_ns(1000); if (rf_part_num == PART_AT86RF233) { rf_if_write_register(TRX_RPC, tmp_rpc_val); } diff --git a/components/802.15.4_RF/stm-s2lp-rf-driver/source/NanostackRfPhys2lp.cpp b/components/802.15.4_RF/stm-s2lp-rf-driver/source/NanostackRfPhys2lp.cpp index 1d88ba052c..435df3e4ae 100644 --- a/components/802.15.4_RF/stm-s2lp-rf-driver/source/NanostackRfPhys2lp.cpp +++ b/components/802.15.4_RF/stm-s2lp-rf-driver/source/NanostackRfPhys2lp.cpp @@ -1083,10 +1083,10 @@ static void rf_reset(void) { // Shutdown rf->SDN = 1; - wait_ms(10); + ThisThread::sleep_for(10); // Wake up rf->SDN = 0; - wait_ms(10); + ThisThread::sleep_for(10); } static void rf_init(void) diff --git a/components/cellular/COMPONENT_STMOD_CELLULAR/STModCellular.cpp b/components/cellular/COMPONENT_STMOD_CELLULAR/STModCellular.cpp index 3cb9525f3e..8e5c39caf4 100644 --- a/components/cellular/COMPONENT_STMOD_CELLULAR/STModCellular.cpp +++ b/components/cellular/COMPONENT_STMOD_CELLULAR/STModCellular.cpp @@ -16,7 +16,7 @@ */ #include "STModCellular.h" -#include "mbed_wait_api.h" +#include "rtos/ThisThread.h" #include "mbed_trace.h" #define TRACE_GROUP "CELL" @@ -38,14 +38,14 @@ STModCellular::STModCellular(FileHandle *fh) : STMOD_CELLULAR_MODEM(fh), // start with modem disabled m_powerkey.write(0); m_reset.write(1); - wait_ms(200); + rtos::ThisThread::sleep_for(200); m_reset.write(0); - wait_ms(150); + rtos::ThisThread::sleep_for(150); - wait_ms(50); + rtos::ThisThread::sleep_for(50); m_simsel0.write(MBED_CONF_STMOD_CELLULAR_SIM_SELECTION & 0x01); m_simsel1.write(MBED_CONF_STMOD_CELLULAR_SIM_SELECTION & 0x02); - wait_ms(50); + rtos::ThisThread::sleep_for(50); } STModCellular::~STModCellular() @@ -59,28 +59,28 @@ nsapi_error_t STModCellular::soft_power_on() #if (MBED_CONF_STMOD_CELLULAR_TYPE == STMOD_UG96) tr_debug("Booting UG96\r\n"); m_reset.write(1); - wait_ms(200); + rtos::ThisThread::sleep_for(200); m_reset.write(0); - wait_ms(150); + rtos::ThisThread::sleep_for(150); m_powerkey.write(1); - wait_ms(150); + rtos::ThisThread::sleep_for(150); m_powerkey.write(0); /* Because modem status is not available on STMOD+ connector, * let's wait for Modem complete boot */ - wait_ms(2300); + rtos::ThisThread::sleep_for(2300); #endif #if (MBED_CONF_STMOD_CELLULAR_TYPE == STMOD_BG96) tr_debug("Booting BG96\r\n"); m_powerkey.write(1); m_reset.write(1); - wait_ms(150); + rtos::ThisThread::sleep_for(150); m_powerkey.write(0); m_reset.write(0); - wait_ms(100); + rtos::ThisThread::sleep_for(100); m_powerkey.write(1); - wait_ms(200); + rtos::ThisThread::sleep_for(200); m_powerkey.write(0); - wait_ms(5000); + rtos::ThisThread::sleep_for(5000); #endif nsapi_error_t err = STMOD_CELLULAR_MODEM::soft_power_on(); @@ -133,7 +133,7 @@ nsapi_error_t STModCellular::soft_power_on() } #endif - wait_ms(500); + rtos::ThisThread::sleep_for(500); #if MBED_CONF_CELLULAR_DEBUG_AT _at->lock(); @@ -150,7 +150,7 @@ nsapi_error_t STModCellular::soft_power_off() { _at->cmd_start("AT+QPOWD"); _at->cmd_stop(); - wait_ms(1000); + rtos::ThisThread::sleep_for(1000); // should wait for POWERED DOWN with a time out up to 65 second according to the manual. // we cannot afford such a long wait though. return STMOD_CELLULAR_MODEM::soft_power_off(); diff --git a/components/storage/blockdevice/COMPONENT_DATAFLASH/DataFlashBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_DATAFLASH/DataFlashBlockDevice.cpp index 281b9f8436..4309233fcf 100644 --- a/components/storage/blockdevice/COMPONENT_DATAFLASH/DataFlashBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_DATAFLASH/DataFlashBlockDevice.cpp @@ -661,8 +661,8 @@ int DataFlashBlockDevice::_sync(void) break; /* wait the typical write period before trying again */ } else { - DEBUG_PRINTF("wait_ms: %d\r\n", DATAFLASH_TIMING_ERASE_PROGRAM_PAGE); - wait_ms(DATAFLASH_TIMING_ERASE_PROGRAM_PAGE); + DEBUG_PRINTF("sleep_for: %d\r\n", DATAFLASH_TIMING_ERASE_PROGRAM_PAGE); + rtos::ThisThread::sleep_for(DATAFLASH_TIMING_ERASE_PROGRAM_PAGE); } } diff --git a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp index e37c4b275b..7010b22cfb 100644 --- a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp @@ -16,7 +16,7 @@ #include "QSPIFBlockDevice.h" #include -#include "mbed_wait_api.h" +#include "rtos/ThisThread.h" #ifndef MBED_CONF_MBED_TRACE_ENABLE #define MBED_CONF_MBED_TRACE_ENABLE 0 @@ -1146,7 +1146,7 @@ bool QSPIFBlockDevice::_is_mem_ready() bool mem_ready = true; do { - wait_ms(1); + rtos::ThisThread::sleep_for(1); retries++; //Read the Status Register from device memset(status_value, 0xFF, QSPI_MAX_STATUS_REGISTER_SIZE); diff --git a/components/storage/blockdevice/COMPONENT_RSPIF/SPIFReducedBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_RSPIF/SPIFReducedBlockDevice.cpp index 2092f58e1e..721965dc30 100644 --- a/components/storage/blockdevice/COMPONENT_RSPIF/SPIFReducedBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_RSPIF/SPIFReducedBlockDevice.cpp @@ -15,7 +15,7 @@ * limitations under the License. */ #include "SPIFReducedBlockDevice.h" -#include "mbed_wait_api.h" +#include "rtos/ThisThread.h" using namespace mbed; @@ -224,7 +224,7 @@ int SPIFReducedBlockDevice::_sync() return 0; } - wait_ms(1); + rtos::ThisThread::sleep_for(1); } return BD_ERROR_DEVICE_ERROR; @@ -244,7 +244,7 @@ int SPIFReducedBlockDevice::_wren() return 0; } - wait_ms(1); + rtos::ThisThread::sleep_for(1); } return BD_ERROR_DEVICE_ERROR; @@ -278,7 +278,7 @@ int SPIFReducedBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_ addr += chunk; size -= chunk; - wait_ms(1); + rtos::ThisThread::sleep_for(1); err = _sync(); if (err) { diff --git a/components/storage/blockdevice/COMPONENT_SD/SDBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_SD/SDBlockDevice.cpp index f4c73a7d35..769fcfbbe3 100644 --- a/components/storage/blockdevice/COMPONENT_SD/SDBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_SD/SDBlockDevice.cpp @@ -139,8 +139,8 @@ #if DEVICE_SPI #include "SDBlockDevice.h" +#include "rtos/ThisThread.h" #include "platform/mbed_debug.h" -#include "platform/mbed_wait_api.h" #ifndef __STDC_FORMAT_MACROS #define __STDC_FORMAT_MACROS #endif @@ -872,7 +872,7 @@ uint32_t SDBlockDevice::_go_idle_state() if (R1_IDLE_STATE == response) { break; } - wait_ms(1); + rtos::ThisThread::sleep_for(1); } return response; } diff --git a/components/testing/COMPONENT_FPGA_CI_TEST_SHIELD/MbedTester.cpp b/components/testing/COMPONENT_FPGA_CI_TEST_SHIELD/MbedTester.cpp index fe7d4c8089..d9c51ad932 100644 --- a/components/testing/COMPONENT_FPGA_CI_TEST_SHIELD/MbedTester.cpp +++ b/components/testing/COMPONENT_FPGA_CI_TEST_SHIELD/MbedTester.cpp @@ -18,6 +18,7 @@ #include "MbedTester.h" #include "fpga_config.h" #include "BlockDevice.h" +#include "rtos/ThisThread.h" #include "platform/mbed_wait_api.h" #include "platform/mbed_error.h" #include "drivers/MbedCRC.h" @@ -1733,7 +1734,7 @@ uint8_t MbedTester::get_pwm_cycles_high() uint16_t MbedTester::get_analogmuxin_measurement() { - wait_ms(1);//wait for value to stabalize + rtos::ThisThread::sleep_for(1);//wait for value to stabalize //take snapshot of conversion value to make safe for reading set_snapshot(); uint16_t an_mux_analogin_measurement = 0; diff --git a/components/wifi/esp8266-driver/ESP8266Interface.cpp b/components/wifi/esp8266-driver/ESP8266Interface.cpp index 6afa89dc54..7bb5ce7d76 100644 --- a/components/wifi/esp8266-driver/ESP8266Interface.cpp +++ b/components/wifi/esp8266-driver/ESP8266Interface.cpp @@ -28,7 +28,7 @@ #include "platform/Callback.h" #include "platform/mbed_atomic.h" #include "platform/mbed_debug.h" -#include "platform/mbed_wait_api.h" +#include "rtos/ThisThread.h" #ifndef MBED_CONF_ESP8266_DEBUG #define MBED_CONF_ESP8266_DEBUG false @@ -49,6 +49,7 @@ #define TRACE_GROUP "ESPI" // ESP8266 Interface using namespace mbed; +using namespace rtos; #if defined MBED_CONF_ESP8266_TX && defined MBED_CONF_ESP8266_RX ESP8266Interface::ESP8266Interface() @@ -459,7 +460,7 @@ nsapi_error_t ESP8266Interface::_reset() _rst_pin.rst_assert(); // If you happen to use Pin7 CH_EN as reset pin, not needed otherwise // https://www.espressif.com/sites/default/files/documentation/esp8266_hardware_design_guidelines_en.pdf - wait_ms(2); // Documentation says 200 us should have been enough, but experimentation shows that 1ms was not enough + ThisThread::sleep_for(2); // Documentation says 200 us; need 2 ticks to get minimum 1 ms. _esp.flush(); _rst_pin.rst_deassert(); } else { diff --git a/features/cellular/framework/AT/AT_CellularContext.cpp b/features/cellular/framework/AT/AT_CellularContext.cpp index e39bbada6d..51f7f7ecb5 100644 --- a/features/cellular/framework/AT/AT_CellularContext.cpp +++ b/features/cellular/framework/AT/AT_CellularContext.cpp @@ -24,7 +24,7 @@ #if (DEVICE_SERIAL && DEVICE_INTERRUPTIN) || defined(DOXYGEN_ONLY) #include "UARTSerial.h" #endif // #if DEVICE_SERIAL -#include "mbed_wait_api.h" +#include "ThisThread.h" #define NETWORK_TIMEOUT 30 * 60 * 1000 // 30 minutes #define DEVICE_TIMEOUT 5 * 60 * 1000 // 5 minutes @@ -45,6 +45,7 @@ using namespace mbed_cellular_util; using namespace mbed; +using namespace rtos; AT_CellularContext::AT_CellularContext(ATHandler &at, CellularDevice *device, const char *apn, bool cp_req, bool nonip_req) : AT_CellularBase(at), _is_connected(false), _current_op(OP_INVALID), _fh(0), _cp_req(cp_req), @@ -891,7 +892,7 @@ void AT_CellularContext::cellular_callback(nsapi_event_t ev, intptr_t ptr) _cb_data.error == NSAPI_ERROR_OK) { if (!_apn) { char imsi[MAX_IMSI_LENGTH + 1]; - wait(1); // need to wait to access SIM in some modems + ThisThread::sleep_for(1000); // need to wait to access SIM in some modems _cb_data.error = _device->open_information()->get_imsi(imsi, sizeof(imsi)); if (_cb_data.error == NSAPI_ERROR_OK) { const char *apn_config = apnconfig(imsi); diff --git a/features/cellular/framework/AT/AT_CellularSMS.cpp b/features/cellular/framework/AT/AT_CellularSMS.cpp index aae8ab57de..b0b0187982 100644 --- a/features/cellular/framework/AT/AT_CellularSMS.cpp +++ b/features/cellular/framework/AT/AT_CellularSMS.cpp @@ -18,7 +18,7 @@ #include #include #include -#include "mbed_wait_api.h" +#include "ThisThread.h" #include "AT_CellularSMS.h" #include "CellularUtil.h" #include "CellularLog.h" @@ -26,6 +26,7 @@ using namespace mbed_cellular_util; using namespace mbed; using namespace std; +using namespace rtos; #define CTRL_Z "\x1a" #define ESC "\x1b" @@ -406,12 +407,12 @@ nsapi_size_or_error_t AT_CellularSMS::send_sms(const char *phone_number, const c int write_size = 0; int remove_plus_sign = (phone_number[0] == '+') ? 1 : 0; - wait_ms(_sim_wait_time); + ThisThread::sleep_for(_sim_wait_time); if (_mode == CellularSMSMmodeText) { _at.cmd_start_stop("+CMGS", "=", "%s", phone_number + remove_plus_sign); - wait_ms(_sim_wait_time); + ThisThread::sleep_for(_sim_wait_time); _at.resp_start("> ", true); if (_at.get_last_error() == NSAPI_ERROR_OK) { @@ -474,7 +475,7 @@ nsapi_size_or_error_t AT_CellularSMS::send_sms(const char *phone_number, const c _at.cmd_start_stop("+CMGS", "=", "%d", (pdu_len - 2) / 2); - wait_ms(_sim_wait_time); + ThisThread::sleep_for(_sim_wait_time); _at.resp_start("> ", true); if (_at.get_last_error() == NSAPI_ERROR_OK) { @@ -564,7 +565,7 @@ nsapi_size_or_error_t AT_CellularSMS::read_sms_from_index(int msg_index, char *b /* * +CMGR: ,,,[,,,,,,,]OK */ - wait_ms(_sim_wait_time); + ThisThread::sleep_for(_sim_wait_time); _at.cmd_start_stop("+CMGR", "=", "%d", msg_index); // TODO: NOTE: If the selected can contain different types of SMs (e.g. SMS-DELIVERs, SMS-SUBMITs, SMS-STATUS-REPORTs and SMS-COMMANDs), @@ -621,7 +622,7 @@ nsapi_size_or_error_t AT_CellularSMS::read_sms(sms_info_t *sms, char *buf, char int pduSize; for (int i = 0; i < sms->parts; i++) { - wait_ms(_sim_wait_time); + ThisThread::sleep_for(_sim_wait_time); _at.cmd_start_stop("+CMGR", "=", "%d", sms->msg_index[i]); _at.resp_start("+CMGR:"); @@ -744,7 +745,7 @@ nsapi_size_or_error_t AT_CellularSMS::get_data_from_pdu(const char *pdu, sms_inf // read first the lower part of first octet as there is message type index++; tmp = hex_str_to_int(pdu + index, 1); - //wait_ms(200); + //ThisThread::sleep_for(200); if ((tmp & 0x03) == 0) {// SMS-DELIVER type, last two bits should be zero // UDH present? Check from first octets higher part tmp = hex_str_to_int(pdu + (--index), 1); @@ -1071,7 +1072,7 @@ AT_CellularSMS::sms_info_t *AT_CellularSMS::get_oldest_sms_index() nsapi_size_or_error_t err = 0; while (current) { if (_mode == CellularSMSMmodeText) { - wait_ms(_sim_wait_time); + ThisThread::sleep_for(_sim_wait_time); err = read_sms_from_index(current->msg_index[0], NULL, 0, NULL, current->date); if (err != 0) { return NULL; diff --git a/features/cellular/framework/targets/UBLOX/AT/UBLOX_AT_CellularContext.cpp b/features/cellular/framework/targets/UBLOX/AT/UBLOX_AT_CellularContext.cpp index 32448fcf70..c2498e3d23 100644 --- a/features/cellular/framework/targets/UBLOX/AT/UBLOX_AT_CellularContext.cpp +++ b/features/cellular/framework/targets/UBLOX/AT/UBLOX_AT_CellularContext.cpp @@ -211,7 +211,7 @@ bool UBLOX_AT_CellularContext::activate_profile(const char *apn, if (activated) { //If context is activated, exit while loop and return status break; } - wait_ms(5000); //Wait for 5 seconds and then try again + rtos::ThisThread::sleep_for(5000); //Wait for 5 seconds and then try again } t1.stop(); } diff --git a/features/cellular/framework/targets/UBLOX/AT/UBLOX_AT_CellularStack.h b/features/cellular/framework/targets/UBLOX/AT/UBLOX_AT_CellularStack.h index 3638559670..e7da23100b 100644 --- a/features/cellular/framework/targets/UBLOX/AT/UBLOX_AT_CellularStack.h +++ b/features/cellular/framework/targets/UBLOX/AT/UBLOX_AT_CellularStack.h @@ -19,7 +19,7 @@ #include "AT_CellularStack.h" #include "CellularUtil.h" -#include "mbed_wait_api.h" +#include "rtos/ThisThread.h" #include "drivers/Timer.h" diff --git a/features/storage/nvstore/source/nvstore.cpp b/features/storage/nvstore/source/nvstore.cpp index 2e14109df3..5dc20fbb0b 100644 --- a/features/storage/nvstore/source/nvstore.cpp +++ b/features/storage/nvstore/source/nvstore.cpp @@ -25,7 +25,7 @@ #include "mbed_atomic.h" #include "mbed_assert.h" #include "mbed_error.h" -#include "mbed_wait_api.h" +#include "ThisThread.h" #include #include #include @@ -836,7 +836,7 @@ int NVStore::init() init_attempts_val = core_util_atomic_incr_u32(&_init_attempts, 1); if (init_attempts_val != 1) { while (!_init_done) { - wait_ms(1); + rtos::ThisThread::sleep_for(1); } return NVSTORE_SUCCESS; } diff --git a/rtos/RtosTimer.h b/rtos/RtosTimer.h index 168687281b..74e7c7ef86 100644 --- a/rtos/RtosTimer.h +++ b/rtos/RtosTimer.h @@ -62,7 +62,7 @@ namespace rtos { RtosTimer timer(&blink); int main() { timer.start(1000); // call blink every 1s - wait_ms(5000); + ThisThread::sleep_for(5000); timer.stop(); // stop after 5s } @endcode diff --git a/targets/TARGET_NXP/TARGET_LPC176X/TARGET_UBLOX_C027/onboard_modem_api.c b/targets/TARGET_NXP/TARGET_LPC176X/TARGET_UBLOX_C027/onboard_modem_api.c index 7849f78737..a4ef32a17c 100644 --- a/targets/TARGET_NXP/TARGET_LPC176X/TARGET_UBLOX_C027/onboard_modem_api.c +++ b/targets/TARGET_NXP/TARGET_LPC176X/TARGET_UBLOX_C027/onboard_modem_api.c @@ -19,7 +19,7 @@ #include "cellular/onboard_modem_api.h" #include "ublox_low_level_api.h" #include "gpio_api.h" -#include "platform/mbed_wait_api.h" +#include "platform/mbed_thread.h" #include "PinNames.h" #if MODEM_ON_BOARD @@ -29,7 +29,7 @@ static void press_power_button(int time_ms) gpio_t gpio; gpio_init_out_ex(&gpio, MDMPWRON, 0); - wait_ms(time_ms); + thread_sleep_for(time_ms); gpio_write(&gpio, 1); } @@ -50,7 +50,7 @@ void onboard_modem_power_up() /* keep the power line low for 150 milisecond */ press_power_button(150); /* give modem a little time to respond */ - wait_ms(100); + thread_sleep_for(100); } void onboard_modem_power_down() diff --git a/targets/TARGET_NXP/TARGET_LPC176X/TARGET_UBLOX_C027/ublox_low_level_api.c b/targets/TARGET_NXP/TARGET_LPC176X/TARGET_UBLOX_C027/ublox_low_level_api.c index 7c623206a7..96ce54b7c3 100644 --- a/targets/TARGET_NXP/TARGET_LPC176X/TARGET_UBLOX_C027/ublox_low_level_api.c +++ b/targets/TARGET_NXP/TARGET_LPC176X/TARGET_UBLOX_C027/ublox_low_level_api.c @@ -16,6 +16,7 @@ #include #include "hal/us_ticker_api.h" #include "platform/mbed_wait_api.h" +#include "platform/mbed_thread.h" #include "gpio_api.h" #include "ublox_low_level_api.h" @@ -39,12 +40,10 @@ void ublox_mdm_init(void) // led should be off gpio_init_out_ex(&gpio, LED, 0); - // Can't use wait_ms() as RTOS isn't initialised yet - //wait_ms(50); // when USB cable is inserted the interface chip issues + // Can't use thread_sleep_for() as RTOS isn't initialised yet + //thread_sleep_for(50); // when USB cable is inserted the interface chip issues // Here's the code from the non-RTOS version - us_ticker_init(); - uint32_t start = us_ticker_read(); - while ((us_ticker_read() - start) < 50000); + wait_us(50000); } // For forwards compatibility @@ -61,7 +60,7 @@ void ublox_mdm_powerOn(int usb) if (!modemOn) { // enable modem modemOn = true; gpio_init_out_ex(&gpio, MDMEN, 1); // LDOEN: 1=on - wait_ms(1); // wait until supply switched off + thread_sleep_for(1); // wait until supply switched off // now we can safely enable the level shifters gpio_init_out_ex(&gpio, MDMLVLOE, 0); // LVLEN: 0=enabled (uart/gpio) if (gpsOn) { @@ -97,7 +96,7 @@ void ublox_gps_powerOn(void) gpsOn = true; // switch on power supply gpio_init_out_ex(&gpio, GPSEN, 1); // LDOEN: 1=on - wait_ms(1); // wait until supply switched off + thread_sleep_for(1); // wait until supply switched off if (modemOn) { gpio_init_out_ex(&gpio, MDMILVLOE, 1); // ILVLEN: 1=enabled (i2c) } diff --git a/targets/TARGET_Realtek/TARGET_AMEBA/rtw_emac.cpp b/targets/TARGET_Realtek/TARGET_AMEBA/rtw_emac.cpp index 2ec69ccdbe..c3474191d5 100644 --- a/targets/TARGET_Realtek/TARGET_AMEBA/rtw_emac.cpp +++ b/targets/TARGET_Realtek/TARGET_AMEBA/rtw_emac.cpp @@ -19,7 +19,6 @@ #include #include "mbed_assert.h" #include "mbed_events.h" -#include "mbed_wait_api.h" #include "rtw_emac.h" #include "EMACMemoryManager.h" @@ -123,7 +122,7 @@ bool RTW_EMAC::link_out(emac_mem_buf_t *buf) bool RTW_EMAC::power_up() { wifi_on(RTW_MODE_STA); - wait_ms(1000); + rtos::ThisThread::sleep_for(1000); wlan_emac_link_change(true); return true; } diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_MTB_MTS_DRAGONFLY/onboard_modem_api.c b/targets/TARGET_STM/TARGET_STM32F4/TARGET_MTB_MTS_DRAGONFLY/onboard_modem_api.c index 82e623e28e..a7e359d0ca 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_MTB_MTS_DRAGONFLY/onboard_modem_api.c +++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_MTB_MTS_DRAGONFLY/onboard_modem_api.c @@ -18,7 +18,7 @@ #include "cellular/onboard_modem_api.h" #include "gpio_api.h" -#include "platform/mbed_wait_api.h" +#include "platform/mbed_thread.h" #include "PinNames.h" #if MODEM_ON_BOARD @@ -29,7 +29,7 @@ static void press_power_button(int time_ms) gpio_init_out_ex(&gpio, MDMPWRON, 1); gpio_write(&gpio, 0); - wait_ms(time_ms); + thread_sleep_for(time_ms); gpio_write(&gpio, 1); } @@ -47,7 +47,7 @@ void onboard_modem_power_up() /* keep the power line low for 200 milisecond */ press_power_button(200); /* give modem a little time to respond */ - wait_ms(100); + thread_sleep_for(100); } void onboard_modem_power_down() @@ -59,7 +59,7 @@ void onboard_modem_power_down() * If 3G_ON_OFF pin is kept low for more than a second, a controlled disconnect and shutdown takes * place, Due to the network disconnect, shut-off can take up to 30 seconds. However, we wait for 10 * seconds only */ - wait_ms(10 * 1000); + thread_sleep_for(10 * 1000); } #endif //MODEM_ON_BOARD #endif //MBED_CONF_NSAPI_PRESENT diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_MTS_DRAGONFLY_F411RE/onboard_modem_api.c b/targets/TARGET_STM/TARGET_STM32F4/TARGET_MTS_DRAGONFLY_F411RE/onboard_modem_api.c index 82e623e28e..a7e359d0ca 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_MTS_DRAGONFLY_F411RE/onboard_modem_api.c +++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_MTS_DRAGONFLY_F411RE/onboard_modem_api.c @@ -18,7 +18,7 @@ #include "cellular/onboard_modem_api.h" #include "gpio_api.h" -#include "platform/mbed_wait_api.h" +#include "platform/mbed_thread.h" #include "PinNames.h" #if MODEM_ON_BOARD @@ -29,7 +29,7 @@ static void press_power_button(int time_ms) gpio_init_out_ex(&gpio, MDMPWRON, 1); gpio_write(&gpio, 0); - wait_ms(time_ms); + thread_sleep_for(time_ms); gpio_write(&gpio, 1); } @@ -47,7 +47,7 @@ void onboard_modem_power_up() /* keep the power line low for 200 milisecond */ press_power_button(200); /* give modem a little time to respond */ - wait_ms(100); + thread_sleep_for(100); } void onboard_modem_power_down() @@ -59,7 +59,7 @@ void onboard_modem_power_down() * If 3G_ON_OFF pin is kept low for more than a second, a controlled disconnect and shutdown takes * place, Due to the network disconnect, shut-off can take up to 30 seconds. However, we wait for 10 * seconds only */ - wait_ms(10 * 1000); + thread_sleep_for(10 * 1000); } #endif //MODEM_ON_BOARD #endif //MBED_CONF_NSAPI_PRESENT diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F437xG/TARGET_UBLOX_C030/onboard_modem_api.c b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F437xG/TARGET_UBLOX_C030/onboard_modem_api.c index bdc475d7ab..6a0a89913d 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F437xG/TARGET_UBLOX_C030/onboard_modem_api.c +++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F437xG/TARGET_UBLOX_C030/onboard_modem_api.c @@ -19,6 +19,7 @@ #include "onboard_modem_api.h" #include "gpio_api.h" #include "platform/mbed_wait_api.h" +#include "platform/mbed_thread.h" #include "PinNames.h" #if MODEM_ON_BOARD @@ -71,7 +72,7 @@ void onboard_modem_power_up() #endif /* give modem a little time to respond */ - wait_ms(100); + thread_sleep_for(100); } void onboard_modem_power_down() diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F439xI/TARGET_MODULE_UBLOX_ODIN_W2/sdk/ublox-odin-w2-drivers/OdinWiFiInterface.cpp b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F439xI/TARGET_MODULE_UBLOX_ODIN_W2/sdk/ublox-odin-w2-drivers/OdinWiFiInterface.cpp index 43ba87f768..36a0688ee3 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F439xI/TARGET_MODULE_UBLOX_ODIN_W2/sdk/ublox-odin-w2-drivers/OdinWiFiInterface.cpp +++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F439xI/TARGET_MODULE_UBLOX_ODIN_W2/sdk/ublox-odin-w2-drivers/OdinWiFiInterface.cpp @@ -1081,7 +1081,7 @@ void OdinWiFiInterface::handle_user_scan(user_scan_s *user_scan) cbRTSL_Status status = cbSTATUS_ERROR; for(int i = 0; (i < 10) && (status != cbSTATUS_OK); i++) { if(i > 0) { - wait_ms(500); + rtos::ThisThread::sleep_for(500); } cbMAIN_driverLock(); diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F439xI/TARGET_WIO_3G/onboard_modem_api.c b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F439xI/TARGET_WIO_3G/onboard_modem_api.c index c103ad0602..0b6eeff1c2 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F439xI/TARGET_WIO_3G/onboard_modem_api.c +++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F439xI/TARGET_WIO_3G/onboard_modem_api.c @@ -20,7 +20,7 @@ #include "cellular/onboard_modem_api.h" #include "gpio_api.h" -#include "platform/mbed_wait_api.h" +#include "platform/mbed_thread.h" #include "PinNames.h" #define WAIT_AFTER_POWR_CHANGED (1000) // [msec.] @@ -32,7 +32,7 @@ static void press_power_button(int time_ms) gpio_t gpio; gpio_init_out_ex(&gpio, PWRKEY, 1); - wait_ms(time_ms); + thread_sleep_for(time_ms); gpio_write(&gpio, 0); } @@ -50,7 +50,7 @@ void onboard_modem_init() // Main UART Interface gpio_init_out_ex(&gpio, MDMDTR, 0); - wait_ms(WAIT_AFTER_POWR_CHANGED); + thread_sleep_for(WAIT_AFTER_POWR_CHANGED); } void onboard_modem_deinit() @@ -59,7 +59,7 @@ void onboard_modem_deinit() // Power supply OFF gpio_init_out_ex(&gpio, M_POWR, 0); - wait_ms(WAIT_AFTER_POWR_CHANGED); + thread_sleep_for(WAIT_AFTER_POWR_CHANGED); } void onboard_modem_power_up() @@ -68,10 +68,10 @@ void onboard_modem_power_up() // Power supply ON gpio_init_out_ex(&gpio, M_POWR, 1); - wait_ms(WAIT_AFTER_POWR_CHANGED); + thread_sleep_for(WAIT_AFTER_POWR_CHANGED); // Turn on - wait_ms(100); + thread_sleep_for(100); press_power_button(200); } @@ -81,7 +81,7 @@ void onboard_modem_power_down() // Power supply OFF gpio_init_out_ex(&gpio, M_POWR, 0); - wait_ms(WAIT_AFTER_POWR_CHANGED); + thread_sleep_for(WAIT_AFTER_POWR_CHANGED); } #endif //MODEM_ON_BOARD diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F439xI/TARGET_WIO_BG96/onboard_modem_api.c b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F439xI/TARGET_WIO_BG96/onboard_modem_api.c index fa10e622e6..53d83ec2a6 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F439xI/TARGET_WIO_BG96/onboard_modem_api.c +++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F439xI/TARGET_WIO_BG96/onboard_modem_api.c @@ -20,7 +20,7 @@ #include "cellular/onboard_modem_api.h" #include "gpio_api.h" -#include "platform/mbed_wait_api.h" +#include "platform/mbed_thread.h" #include "PinNames.h" #define WAIT_AFTER_POWR_CHANGED (1000) // [msec.] @@ -32,7 +32,7 @@ static void press_power_button(int time_ms) gpio_t gpio; gpio_init_out_ex(&gpio, PWRKEY, 1); - wait_ms(time_ms); + thread_sleep_for(time_ms); gpio_write(&gpio, 0); } @@ -50,7 +50,7 @@ void onboard_modem_init() // Main UART Interface gpio_init_out_ex(&gpio, MDMDTR, 0); - wait_ms(WAIT_AFTER_POWR_CHANGED); + thread_sleep_for(WAIT_AFTER_POWR_CHANGED); } void onboard_modem_deinit() @@ -64,10 +64,10 @@ void onboard_modem_power_up() // Power supply ON gpio_init_out_ex(&gpio, M_POWR, 1); - wait_ms(WAIT_AFTER_POWR_CHANGED); + thread_sleep_for(WAIT_AFTER_POWR_CHANGED); // Turn on - wait_ms(100); + thread_sleep_for(100); press_power_button(200); } @@ -77,7 +77,7 @@ void onboard_modem_power_down() // Power supply OFF gpio_init_out_ex(&gpio, M_POWR, 0); - wait_ms(WAIT_AFTER_POWR_CHANGED); + thread_sleep_for(WAIT_AFTER_POWR_CHANGED); } #endif //MODEM_ON_BOARD diff --git a/targets/TARGET_STM/TARGET_STM32L4/TARGET_MTS_DRAGONFLY_L471QG/onboard_modem_api.c b/targets/TARGET_STM/TARGET_STM32L4/TARGET_MTS_DRAGONFLY_L471QG/onboard_modem_api.c index 9edf48ffd9..24a3c5ad08 100755 --- a/targets/TARGET_STM/TARGET_STM32L4/TARGET_MTS_DRAGONFLY_L471QG/onboard_modem_api.c +++ b/targets/TARGET_STM/TARGET_STM32L4/TARGET_MTS_DRAGONFLY_L471QG/onboard_modem_api.c @@ -18,7 +18,7 @@ #include "onboard_modem_api.h" #include "gpio_api.h" -#include "platform/mbed_wait_api.h" +#include "platform/mbed_thread.h" #include "PinNames.h" #if MODEM_ON_BOARD @@ -69,7 +69,7 @@ void onboard_modem_power_up() while(i < 3) { press_power_button(150000); - wait_ms(250); + thread_sleep_for(250); if(gpio_read(&gpio)) { diff --git a/usb/device/USBHID/USBMouse.cpp b/usb/device/USBHID/USBMouse.cpp index 9240ffd5d6..bb60625ab5 100644 --- a/usb/device/USBHID/USBMouse.cpp +++ b/usb/device/USBHID/USBMouse.cpp @@ -17,9 +17,8 @@ #include "stdint.h" #include "USBMouse.h" -#include "PlatformMutex.h" +#include "ThisThread.h" #include "usb_phy_api.h" -#include "mbed_wait_api.h" USBMouse::USBMouse(bool connect_blocking, MOUSE_TYPE mouse_type, uint16_t vendor_id, uint16_t product_id, uint16_t product_release): @@ -157,7 +156,7 @@ bool USBMouse::double_click() _mutex.unlock(); return false; } - wait(0.1); + rtos::ThisThread::sleep_for(100); bool ret = click(MOUSE_LEFT); _mutex.unlock(); @@ -172,7 +171,7 @@ bool USBMouse::click(uint8_t button) _mutex.unlock(); return false; } - wait(0.01); + rtos::ThisThread::sleep_for(10); bool ret = update(0, 0, 0, 0); _mutex.unlock(); diff --git a/usb/device/USBHID/USBMouseKeyboard.cpp b/usb/device/USBHID/USBMouseKeyboard.cpp index b236e30753..acd540479b 100644 --- a/usb/device/USBHID/USBMouseKeyboard.cpp +++ b/usb/device/USBHID/USBMouseKeyboard.cpp @@ -18,7 +18,7 @@ #include "stdint.h" #include "USBMouseKeyboard.h" #include "usb_phy_api.h" -#include "mbed_wait_api.h" +#include "ThisThread.h" typedef struct { unsigned char usage; @@ -709,7 +709,7 @@ bool USBMouseKeyboard::doubleClick() _mutex.unlock(); return false; } - wait(0.1); + rtos::ThisThread::sleep_for(100); bool ret = click(MOUSE_LEFT); _mutex.unlock(); @@ -724,7 +724,7 @@ bool USBMouseKeyboard::click(uint8_t button) _mutex.unlock(); return false; } - wait(0.01); + rtos::ThisThread::sleep_for(10); bool ret = update(0, 0, 0, 0); _mutex.unlock(); From c94d6a8cc7ef2a7599c76f156fc6ac646501f9a3 Mon Sep 17 00:00:00 2001 From: Kevin Bracey Date: Fri, 15 Mar 2019 12:23:16 +0200 Subject: [PATCH 10/17] Make events use RTOS API Switch from CMSIS-RTOS to mbed C++ API, which are available in bare metal build. Other minor tidies, like removing unnecessary volatile. --- events/equeue/equeue_mbed.cpp | 45 ++++++++++++++++++--------------- events/equeue/equeue_platform.h | 15 ++++++++--- rtos/EventFlags.cpp | 4 +-- 3 files changed, 37 insertions(+), 27 deletions(-) diff --git a/events/equeue/equeue_mbed.cpp b/events/equeue/equeue_mbed.cpp index ca337df21f..24f4fafdc3 100644 --- a/events/equeue/equeue_mbed.cpp +++ b/events/equeue/equeue_mbed.cpp @@ -22,6 +22,7 @@ #include #include +#include "cmsis.h" #include "platform/mbed_critical.h" #include "drivers/Timer.h" #include "drivers/Ticker.h" @@ -33,11 +34,13 @@ using namespace mbed; // Ticker operations -#if MBED_CONF_RTOS_PRESENT +#if MBED_CONF_RTOS_API_PRESENT + +#include "rtos/Kernel.h" unsigned equeue_tick() { - return osKernelGetTickCount(); + return rtos::Kernel::get_ms_count(); } #else @@ -120,27 +123,28 @@ void equeue_mutex_unlock(equeue_mutex_t *m) // Semaphore operations -#ifdef MBED_CONF_RTOS_PRESENT +#ifdef MBED_CONF_RTOS_API_PRESENT + +#include "rtos/EventFlags.h" + +MBED_STATIC_ASSERT(sizeof(equeue_sema_t) == sizeof(rtos::EventFlags), "equeue_sema_t / rtos::EventFlags mismatch"); int equeue_sema_create(equeue_sema_t *s) { - osEventFlagsAttr_t attr; - memset(&attr, 0, sizeof(attr)); - attr.cb_mem = &s->mem; - attr.cb_size = sizeof(s->mem); - - s->id = osEventFlagsNew(&attr); - return !s->id ? -1 : 0; + new (s) rtos::EventFlags("equeue"); + return 0; } void equeue_sema_destroy(equeue_sema_t *s) { - osEventFlagsDelete(s->id); + rtos::EventFlags *ef = reinterpret_cast(s); + ef->~EventFlags(); } void equeue_sema_signal(equeue_sema_t *s) { - osEventFlagsSet(s->id, 1); + rtos::EventFlags *ef = reinterpret_cast(s); + ef->set(1); } bool equeue_sema_wait(equeue_sema_t *s, int ms) @@ -149,7 +153,8 @@ bool equeue_sema_wait(equeue_sema_t *s, int ms) ms = osWaitForever; } - return (osEventFlagsWait(s->id, 1, osFlagsWaitAny, ms) == 1); + rtos::EventFlags *ef = reinterpret_cast(s); + return ef->wait_any(1, ms) == 1; } #else @@ -157,7 +162,7 @@ bool equeue_sema_wait(equeue_sema_t *s, int ms) // Semaphore operations int equeue_sema_create(equeue_sema_t *s) { - *s = false; + *s = 0; return 0; } @@ -177,23 +182,21 @@ static void equeue_sema_timeout(equeue_sema_t *s) bool equeue_sema_wait(equeue_sema_t *s, int ms) { - int signal = 0; ALIAS_TIMEOUT timeout; - if (ms == 0) { - return false; - } else if (ms > 0) { + if (ms > 0) { timeout.attach_us(callback(equeue_sema_timeout, s), (us_timestamp_t)ms * 1000); } core_util_critical_section_enter(); - while (!*s) { + while (!*s && ms != 0) { sleep(); core_util_critical_section_exit(); + __ISB(); core_util_critical_section_enter(); } - signal = *s; - *s = false; + int signal = *s; + *s = 0; core_util_critical_section_exit(); return (signal > 0); diff --git a/events/equeue/equeue_platform.h b/events/equeue/equeue_platform.h index a63243ed9f..5bef6da559 100644 --- a/events/equeue/equeue_platform.h +++ b/events/equeue/equeue_platform.h @@ -26,6 +26,7 @@ extern "C" { #endif #include +#include // Currently supported platforms // @@ -114,13 +115,19 @@ typedef struct equeue_sema { pthread_cond_t cond; bool signal; } equeue_sema_t; -#elif defined(EQUEUE_PLATFORM_MBED) && defined(MBED_CONF_RTOS_PRESENT) +#elif defined(EQUEUE_PLATFORM_MBED) && MBED_CONF_RTOS_API_PRESENT typedef struct equeue_sema { - osEventFlagsId_t id; - mbed_rtos_storage_event_flags_t mem; + // We will actually store a C++ rtos:EventQueue in here; + // attempt to match layout for storage, and assert size in equeue_mbed.cpp +#if MBED_CONF_RTOS_PRESENT + osEventFlagsId_t _id; + mbed_rtos_storage_event_flags_t _obj_mem; +#else + uint32_t _flags; +#endif } equeue_sema_t; #elif defined(EQUEUE_PLATFORM_MBED) -typedef volatile int equeue_sema_t; +typedef int equeue_sema_t; #endif // Platform semaphore operations diff --git a/rtos/EventFlags.cpp b/rtos/EventFlags.cpp index 5382ff9456..df4a273e26 100644 --- a/rtos/EventFlags.cpp +++ b/rtos/EventFlags.cpp @@ -30,7 +30,7 @@ namespace rtos { EventFlags::EventFlags() { - constructor(); + constructor("application_unnamed_event_flags"); } EventFlags::EventFlags(const char *name) @@ -42,7 +42,7 @@ void EventFlags::constructor(const char *name) { #if MBED_CONF_RTOS_PRESENT osEventFlagsAttr_t attr = { 0 }; - attr.name = name ? name : "application_unnamed_event_flags"; + attr.name = name; attr.cb_mem = &_obj_mem; attr.cb_size = sizeof(_obj_mem); _id = osEventFlagsNew(&attr); From 77321ca79e45ed847e69f7e935b6348aac368a32 Mon Sep 17 00:00:00 2001 From: Kevin Bracey Date: Fri, 15 Mar 2019 13:01:39 +0200 Subject: [PATCH 11/17] CPU stats don't require low power ticker --- platform/mbed_stats.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/platform/mbed_stats.c b/platform/mbed_stats.c index c46f344b36..e2d0a6bf00 100644 --- a/platform/mbed_stats.c +++ b/platform/mbed_stats.c @@ -8,13 +8,12 @@ #include "device.h" #ifdef MBED_CONF_RTOS_PRESENT #include "cmsis_os2.h" -#include "rtos_idle.h" -#elif defined(MBED_STACK_STATS_ENABLED) || defined(MBED_THREAD_STATS_ENABLED) || defined(MBED_CPU_STATS_ENABLED) +#elif defined(MBED_STACK_STATS_ENABLED) || defined(MBED_THREAD_STATS_ENABLED) #warning Statistics are currently not supported without the rtos. #endif -#if defined(MBED_CPU_STATS_ENABLED) && (!DEVICE_LPTICKER || !DEVICE_SLEEP) -#warning CPU statistics are not supported without low power timer support. +#if defined(MBED_CPU_STATS_ENABLED) && (!DEVICE_SLEEP) +#warning CPU statistics are not supported without sleep support. #endif void mbed_stats_cpu_get(mbed_stats_cpu_t *stats) From ccf59f8e814655fddfeeae1c8990489c1c971e98 Mon Sep 17 00:00:00 2001 From: Kevin Bracey Date: Wed, 29 May 2019 15:33:15 +0300 Subject: [PATCH 12/17] SysTimer: don't always hold deep sleep lock Revert back to older behaviour where we hold deep sleep lock only while timing a sleep. Previous version was a speed optimisation, but broke some tests. --- platform/SysTimer.cpp | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/platform/SysTimer.cpp b/platform/SysTimer.cpp index 63d1098f04..a79a4b8bd6 100644 --- a/platform/SysTimer.cpp +++ b/platform/SysTimer.cpp @@ -60,9 +60,6 @@ SysTimer::SysTimer() : _ticking(false), _deep_sleep_locked(false) { - if (!_ticker_data->interface->runs_in_deep_sleep) { - sleep_manager_lock_deep_sleep(); - } } template @@ -76,9 +73,6 @@ SysTimer::SysTimer(const ticker_data_t *data) : _ticking(false), _deep_sleep_locked(false) { - if (!_ticker_data->interface->runs_in_deep_sleep) { - sleep_manager_lock_deep_sleep(); - } } template @@ -86,9 +80,6 @@ SysTimer::~SysTimer() { cancel_tick(); cancel_wake(); - if (!_ticker_data->interface->runs_in_deep_sleep) { - sleep_manager_unlock_deep_sleep(); - } } template @@ -117,6 +108,11 @@ void SysTimer::set_wake_time(uint64_t at) _wake_time_set = true; _wake_time_passed = false; + if (!_deep_sleep_locked && !_ticker_data->interface->runs_in_deep_sleep) { + _deep_sleep_locked = true; + sleep_manager_lock_deep_sleep(); + } + /* If deep sleep is unlocked, and we have enough time, let's go for it */ if (MBED_CONF_TARGET_DEEP_SLEEP_LATENCY > 0 && ticks_to_sleep > MBED_CONF_TARGET_DEEP_SLEEP_LATENCY && From 3f0a5281e096ecddae86bb36075f04271f5c850a Mon Sep 17 00:00:00 2001 From: Martin Kojtal Date: Wed, 29 May 2019 14:40:53 +0100 Subject: [PATCH 13/17] SysTimer: irq Cortex A fix C linkage --- platform/SysTimer.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/platform/SysTimer.h b/platform/SysTimer.h index b13a0a3bea..f6e3b2ad40 100644 --- a/platform/SysTimer.h +++ b/platform/SysTimer.h @@ -21,9 +21,12 @@ #include "platform/mbed_atomic.h" #include "drivers/TimerEvent.h" #include "cmsis.h" + +extern "C" { #if defined(TARGET_CORTEX_A) #include "irq_ctrl.h" #endif +} namespace mbed { namespace internal { From c98b0d0b03bd111d47cbe0ae8d6545103a42b9e1 Mon Sep 17 00:00:00 2001 From: Martin Kojtal Date: Tue, 28 May 2019 10:26:39 +0100 Subject: [PATCH 14/17] VK_RZ_A1H: add mbed_get_a9_tick_irqn --- .../TARGET_RZ_A1XX/TARGET_VK_RZ_A1H/device/os_tick_ostm.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/targets/TARGET_RENESAS/TARGET_RZ_A1XX/TARGET_VK_RZ_A1H/device/os_tick_ostm.c b/targets/TARGET_RENESAS/TARGET_RZ_A1XX/TARGET_VK_RZ_A1H/device/os_tick_ostm.c index 85540192b3..e974310cea 100644 --- a/targets/TARGET_RENESAS/TARGET_RZ_A1XX/TARGET_VK_RZ_A1H/device/os_tick_ostm.c +++ b/targets/TARGET_RENESAS/TARGET_RZ_A1XX/TARGET_VK_RZ_A1H/device/os_tick_ostm.c @@ -191,5 +191,10 @@ uint32_t OS_Tick_GetOverflow (void) return (IRQ_GetPending(OSTM_IRQn)); } +// Get Cortex-A9 OS Timer interrupt number +IRQn_ID_t mbed_get_a9_tick_irqn(){ + return OSTM_IRQn; +} + #endif From 7442da30f9137f5382090e0a955ac1541acce802 Mon Sep 17 00:00:00 2001 From: Kevin Bracey Date: Wed, 10 Jul 2019 10:25:40 +0300 Subject: [PATCH 15/17] equeue - avoid Kernel::get_ms_count from IRQ Kernel::get_ms_count is documented as not working from IRQ. In RTOS builds it can return misleading answers - see https://github.com/ARM-software/CMSIS_5/issues/625 In non-RTOS builds, it can trigger an assert, as it upsets the sleep logic. Modified code is still not ideal - could be improved further if there was a fast path for "post now" that didn't bother looking at timers (both at post time and dispatch time). --- events/equeue/equeue_mbed.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/events/equeue/equeue_mbed.cpp b/events/equeue/equeue_mbed.cpp index 24f4fafdc3..e4836051fa 100644 --- a/events/equeue/equeue_mbed.cpp +++ b/events/equeue/equeue_mbed.cpp @@ -37,10 +37,24 @@ using namespace mbed; #if MBED_CONF_RTOS_API_PRESENT #include "rtos/Kernel.h" +#include "platform/mbed_os_timer.h" unsigned equeue_tick() { - return rtos::Kernel::get_ms_count(); + // It is not safe to call get_ms_count from ISRs, both + // because documentation says so, and because it will give + // a stale value from the RTOS if the interrupt has woken + // us out of sleep - the RTOS will not have updated its + // ticks yet. + if (core_util_is_isr_active()) { + // And the documentation further says that this + // should not be called from critical sections, for + // performance reasons, but I don't have a good + // current alternative! + return mbed::internal::os_timer->get_time() / 1000; + } else { + return rtos::Kernel::get_ms_count(); + } } #else From ed4bf5220e836adac7a26a5ac15136bc7c9dc6dc Mon Sep 17 00:00:00 2001 From: Kevin Bracey Date: Thu, 4 Jul 2019 15:37:47 +0300 Subject: [PATCH 16/17] rtos: NULL -> nullptr Some build errors seen with NULL not being defined. Rather than add cstddef includes, switch to C++11 nullptr. --- rtos/ConditionVariable.cpp | 18 +++++----- rtos/EventFlags.h | 2 +- rtos/Mail.h | 12 +++---- rtos/MemoryPool.h | 20 +++++------ rtos/Mutex.h | 2 +- rtos/Queue.h | 4 +-- rtos/RtosTimer.h | 4 +-- rtos/Semaphore.cpp | 2 +- rtos/TARGET_CORTEX/mbed_rtx_idle.cpp | 4 +-- rtos/ThisThread.cpp | 6 ++-- rtos/ThisThread.h | 4 +-- rtos/Thread.cpp | 34 +++++++++--------- rtos/Thread.h | 52 ++++++++++++++-------------- 13 files changed, 82 insertions(+), 82 deletions(-) diff --git a/rtos/ConditionVariable.cpp b/rtos/ConditionVariable.cpp index e1087fe0a7..f4e03701d5 100644 --- a/rtos/ConditionVariable.cpp +++ b/rtos/ConditionVariable.cpp @@ -30,12 +30,12 @@ namespace rtos { -ConditionVariable::Waiter::Waiter(): sem(0), prev(NULL), next(NULL), in_list(false) +ConditionVariable::Waiter::Waiter(): sem(0), prev(nullptr), next(nullptr), in_list(false) { // No initialization to do } -ConditionVariable::ConditionVariable(Mutex &mutex): _mutex(mutex), _wait_list(NULL) +ConditionVariable::ConditionVariable(Mutex &mutex): _mutex(mutex), _wait_list(nullptr) { // No initialization to do } @@ -86,7 +86,7 @@ bool ConditionVariable::wait_until(uint64_t millisec) void ConditionVariable::notify_one() { MBED_ASSERT(_mutex.get_owner() == ThisThread::get_id()); - if (_wait_list != NULL) { + if (_wait_list != nullptr) { _wait_list->sem.release(); _remove_wait_list(&_wait_list, _wait_list); } @@ -95,7 +95,7 @@ void ConditionVariable::notify_one() void ConditionVariable::notify_all() { MBED_ASSERT(_mutex.get_owner() == ThisThread::get_id()); - while (_wait_list != NULL) { + while (_wait_list != nullptr) { _wait_list->sem.release(); _remove_wait_list(&_wait_list, _wait_list); } @@ -103,7 +103,7 @@ void ConditionVariable::notify_all() void ConditionVariable::_add_wait_list(Waiter **wait_list, Waiter *waiter) { - if (NULL == *wait_list) { + if (nullptr == *wait_list) { // Nothing in the list so add it directly. // Update prev and next pointer to reference self *wait_list = waiter; @@ -137,18 +137,18 @@ void ConditionVariable::_remove_wait_list(Waiter **wait_list, Waiter *waiter) if (*wait_list == waiter) { // This was the last element in the list - *wait_list = NULL; + *wait_list = nullptr; } // Invalidate pointers - waiter->next = NULL; - waiter->prev = NULL; + waiter->next = nullptr; + waiter->prev = nullptr; waiter->in_list = false; } ConditionVariable::~ConditionVariable() { - MBED_ASSERT(NULL == _wait_list); + MBED_ASSERT(nullptr == _wait_list); } } diff --git a/rtos/EventFlags.h b/rtos/EventFlags.h index 0c2798d4a9..2ac7c1ee2f 100644 --- a/rtos/EventFlags.h +++ b/rtos/EventFlags.h @@ -112,7 +112,7 @@ public: ~EventFlags(); private: - void constructor(const char *name = NULL); + void constructor(const char *name = nullptr); uint32_t wait(uint32_t flags, uint32_t opt, uint32_t millisec, bool clear); #if MBED_CONF_RTOS_PRESENT osEventFlagsId_t _id; diff --git a/rtos/Mail.h b/rtos/Mail.h index 85607dc45e..67b6b0212a 100644 --- a/rtos/Mail.h +++ b/rtos/Mail.h @@ -97,7 +97,7 @@ public: * * @param millisec Not used (see note). * - * @return Pointer to memory block that you can fill with mail or NULL in case error. + * @return Pointer to memory block that you can fill with mail or nullptr in case error. * * @note You may call this function from ISR context. * @note If blocking is required, use Mail::alloc_for or Mail::alloc_until @@ -111,7 +111,7 @@ public: * * @param millisec Timeout value, or osWaitForever. * - * @return Pointer to memory block that you can fill with mail or NULL in case error. + * @return Pointer to memory block that you can fill with mail or nullptr in case error. * * @note You may call this function from ISR context if the millisec parameter is set to 0. */ @@ -124,7 +124,7 @@ public: * * @param millisec Absolute timeout time, referenced to Kernel::get_ms_count(). * - * @return Pointer to memory block that you can fill with mail or NULL in case error. + * @return Pointer to memory block that you can fill with mail or nullptr in case error. * * @note You cannot call this function from ISR context. * @note the underlying RTOS may have a limit to the maximum wait time @@ -141,7 +141,7 @@ public: * * @param millisec Not used (see note). * - * @return Pointer to memory block that you can fill with mail or NULL in case error. + * @return Pointer to memory block that you can fill with mail or nullptr in case error. * * @note You may call this function from ISR context if the millisec parameter is set to 0. * @note If blocking is required, use Mail::calloc_for or Mail::calloc_until @@ -155,7 +155,7 @@ public: * * @param millisec Timeout value, or osWaitForever. * - * @return Pointer to memory block that you can fill with mail or NULL in case error. + * @return Pointer to memory block that you can fill with mail or nullptr in case error. * * @note You may call this function from ISR context if the millisec parameter is set to 0. */ @@ -168,7 +168,7 @@ public: * * @param millisec Absolute timeout time, referenced to Kernel::get_ms_count(). * - * @return Pointer to memory block that you can fill with mail or NULL in case error. + * @return Pointer to memory block that you can fill with mail or nullptr in case error. * * @note You cannot call this function from ISR context. * @note the underlying RTOS may have a limit to the maximum wait time diff --git a/rtos/MemoryPool.h b/rtos/MemoryPool.h index 6764d12237..6196096a84 100644 --- a/rtos/MemoryPool.h +++ b/rtos/MemoryPool.h @@ -77,7 +77,7 @@ public: } /** Allocate a memory block from a memory pool, without blocking. - @return address of the allocated memory block or NULL in case of no memory available. + @return address of the allocated memory block or nullptr in case of no memory available. @note You may call this function from ISR context. */ @@ -88,7 +88,7 @@ public: /** Allocate a memory block from a memory pool, optionally blocking. @param millisec timeout value (osWaitForever to wait forever) - @return address of the allocated memory block or NULL in case of no memory available. + @return address of the allocated memory block or nullptr in case of no memory available. @note You may call this function from ISR context if the millisec parameter is set to 0. */ @@ -99,7 +99,7 @@ public: /** Allocate a memory block from a memory pool, blocking. @param millisec absolute timeout time, referenced to Kernel::get_ms_count(). - @return address of the allocated memory block or NULL in case of no memory available. + @return address of the allocated memory block or nullptr in case of no memory available. @note You cannot call this function from ISR context. @note the underlying RTOS may have a limit to the maximum wait time @@ -122,14 +122,14 @@ public: } /** Allocate a memory block from a memory pool, without blocking, and set memory block to zero. - @return address of the allocated memory block or NULL in case of no memory available. + @return address of the allocated memory block or nullptr in case of no memory available. @note You may call this function from ISR context. */ T *calloc(void) { T *item = alloc(); - if (item != NULL) { + if (item != nullptr) { memset(item, 0, sizeof(T)); } return item; @@ -137,14 +137,14 @@ public: /** Allocate a memory block from a memory pool, optionally blocking, and set memory block to zero. @param millisec timeout value (osWaitForever to wait forever) - @return address of the allocated memory block or NULL in case of no memory available. + @return address of the allocated memory block or nullptr in case of no memory available. @note You may call this function from ISR context if the millisec parameter is set to 0. */ T *calloc_for(uint32_t millisec) { T *item = alloc_for(millisec); - if (item != NULL) { + if (item != nullptr) { memset(item, 0, sizeof(T)); } return item; @@ -152,7 +152,7 @@ public: /** Allocate a memory block from a memory pool, blocking, and set memory block to zero. @param millisec absolute timeout time, referenced to Kernel::get_ms_count(). - @return address of the allocated memory block or NULL in case of no memory available. + @return address of the allocated memory block or nullptr in case of no memory available. @note You cannot call this function from ISR context. @note the underlying RTOS may have a limit to the maximum wait time @@ -163,7 +163,7 @@ public: T *calloc_until(uint64_t millisec) { T *item = alloc_until(millisec); - if (item != NULL) { + if (item != nullptr) { memset(item, 0, sizeof(T)); } return item; @@ -172,7 +172,7 @@ public: /** Free a memory block. @param block address of the allocated memory block to be freed. @return osOK on successful deallocation, osErrorParameter if given memory block id - is NULL or invalid, or osErrorResource if given memory block is in an + is nullptr or invalid, or osErrorResource if given memory block is in an invalid memory pool state. @note You may call this function from ISR context. diff --git a/rtos/Mutex.h b/rtos/Mutex.h index aeddf02924..2a48e2dec2 100644 --- a/rtos/Mutex.h +++ b/rtos/Mutex.h @@ -177,7 +177,7 @@ public: private: #if MBED_CONF_RTOS_PRESENT - void constructor(const char *name = NULL); + void constructor(const char *name = nullptr); friend class ConditionVariable; osMutexId_t _id; diff --git a/rtos/Queue.h b/rtos/Queue.h index 1ce8eb354a..7e0149634f 100644 --- a/rtos/Queue.h +++ b/rtos/Queue.h @@ -187,8 +187,8 @@ public: osEvent get(uint32_t millisec = osWaitForever) { osEvent event; - T *data = NULL; - osStatus_t res = osMessageQueueGet(_id, &data, NULL, millisec); + T *data = nullptr; + osStatus_t res = osMessageQueueGet(_id, &data, nullptr, millisec); switch (res) { case osOK: diff --git a/rtos/RtosTimer.h b/rtos/RtosTimer.h index 74e7c7ef86..dfff795574 100644 --- a/rtos/RtosTimer.h +++ b/rtos/RtosTimer.h @@ -91,7 +91,7 @@ public: /** Create timer. @param func function to be executed by this timer. @param type osTimerOnce for one-shot or osTimerPeriodic for periodic behavior. (default: osTimerPeriodic) - @param argument argument to the timer call back function. (default: NULL) + @param argument argument to the timer call back function. (default: nullptr) @deprecated Replaced with RtosTimer(Callback, os_timer_type) @deprecated The RtosTimer has been superseded by the EventQueue. See RtosTimer.h for more details @@ -102,7 +102,7 @@ public: "Replaced with RtosTimer(Callback, os_timer_type)") MBED_DEPRECATED_SINCE("mbed-os-5.2", "The RtosTimer has been superseded by the EventQueue. See RtosTimer.h for more details") - RtosTimer(void (*func)(void const *argument), os_timer_type type = osTimerPeriodic, void *argument = NULL) + RtosTimer(void (*func)(void const *argument), os_timer_type type = osTimerPeriodic, void *argument = nullptr) { constructor(mbed::callback((void (*)(void *))func, argument), type); } diff --git a/rtos/Semaphore.cpp b/rtos/Semaphore.cpp index 6887ac247f..8ae83c9f69 100644 --- a/rtos/Semaphore.cpp +++ b/rtos/Semaphore.cpp @@ -47,7 +47,7 @@ void Semaphore::constructor(int32_t count, uint16_t max_count) attr.cb_mem = &_obj_mem; attr.cb_size = sizeof(_obj_mem); _id = osSemaphoreNew(max_count, count, &attr); - MBED_ASSERT(_id != NULL); + MBED_ASSERT(_id != nullptr); #else _count = count; _max_count = max_count; diff --git a/rtos/TARGET_CORTEX/mbed_rtx_idle.cpp b/rtos/TARGET_CORTEX/mbed_rtx_idle.cpp index 52b7efede9..6d4431d8d9 100644 --- a/rtos/TARGET_CORTEX/mbed_rtx_idle.cpp +++ b/rtos/TARGET_CORTEX/mbed_rtx_idle.cpp @@ -159,8 +159,8 @@ extern "C" { void rtos_attach_idle_hook(void (*fptr)(void)) { - //Attach the specified idle hook, or the default idle hook in case of a NULL pointer - if (fptr != NULL) { + //Attach the specified idle hook, or the default idle hook in case of a null pointer + if (fptr != nullptr) { idle_hook_fptr = fptr; } else { idle_hook_fptr = default_idle_hook; diff --git a/rtos/ThisThread.cpp b/rtos/ThisThread.cpp index 50286c214d..4d7fb052e3 100644 --- a/rtos/ThisThread.cpp +++ b/rtos/ThisThread.cpp @@ -242,12 +242,12 @@ const char *get_name() { #if MBED_CONF_RTOS_PRESENT osThreadId_t id = osThreadGetId(); - if (id == NULL) { - return NULL; + if (id == nullptr) { + return nullptr; } return osThreadGetName(id); #else - return NULL; + return nullptr; #endif } diff --git a/rtos/ThisThread.h b/rtos/ThisThread.h index c7278c7f6c..b3a67a62f2 100644 --- a/rtos/ThisThread.h +++ b/rtos/ThisThread.h @@ -169,13 +169,13 @@ void sleep_until(uint64_t millisec); void yield(); /** Get the thread id of the current running thread. - @return thread ID for reference by other functions or NULL in case of error or in ISR context. + @return thread ID for reference by other functions or nullptr in case of error or in ISR context. @note You may call this function from ISR context. */ osThreadId_t get_id(); /** Get the thread name of the current running thread. - @return thread name pointer or NULL if thread has no name or in case of error. + @return thread name pointer or nullptr if thread has no name or in case of error. @note You cannot call this function from ISR context. */ const char *get_name(); diff --git a/rtos/Thread.cpp b/rtos/Thread.cpp index 80827ab52d..c3eb83dd50 100644 --- a/rtos/Thread.cpp +++ b/rtos/Thread.cpp @@ -52,7 +52,7 @@ void Thread::constructor(uint32_t tz_module, osPriority priority, const uint32_t aligned_size = ALIGN_DOWN(stack_size - offset, 8); _tid = 0; - _dynamic_stack = (stack_mem == NULL); + _dynamic_stack = (stack_mem == nullptr); _finished = false; memset(&_attr, 0, sizeof(_attr)); _attr.priority = priority; @@ -96,9 +96,9 @@ osStatus Thread::start(mbed::Callback task) return osErrorParameter; } - if (_attr.stack_mem == NULL) { + if (_attr.stack_mem == nullptr) { _attr.stack_mem = new uint32_t[_attr.stack_size / sizeof(uint32_t)]; - MBED_ASSERT(_attr.stack_mem != NULL); + MBED_ASSERT(_attr.stack_mem != nullptr); } //Fill the stack with a magic word for maximum usage checking @@ -111,10 +111,10 @@ osStatus Thread::start(mbed::Callback task) _attr.cb_mem = &_obj_mem; _task = task; _tid = osThreadNew(Thread::_thunk, this, &_attr); - if (_tid == NULL) { + if (_tid == nullptr) { if (_dynamic_stack) { - delete[](uint32_t *)(_attr.stack_mem); - _attr.stack_mem = (uint32_t *)NULL; + delete[] _attr.stack_mem; + _attr.stack_mem = nullptr; } _mutex.unlock(); _join_sem.release(); @@ -130,12 +130,12 @@ osStatus Thread::terminate() osStatus_t ret = osOK; _mutex.lock(); - // Set the Thread's tid to NULL and + // Set the Thread's tid to nullptr and // release the semaphore before terminating // since this thread could be terminating itself osThreadId_t local_id = _tid; _join_sem.release(); - _tid = (osThreadId_t)NULL; + _tid = nullptr; if (!_finished) { _finished = true; // if local_id == 0 Thread was not started in first place @@ -156,7 +156,7 @@ osStatus Thread::join() // terminated or has been terminated. Once the mutex has // been locked it is ensured that the thread is deleted. _mutex.lock(); - MBED_ASSERT(NULL == _tid); + MBED_ASSERT(nullptr == _tid); _mutex.unlock(); // Release sem so any other threads joining this thread wake up @@ -204,7 +204,7 @@ Thread::State Thread::get_state() const _mutex.lock(); - if (_tid != NULL) { + if (_tid != nullptr) { #if defined(MBED_OS_BACKEND_RTX5) state = _obj_mem.state; #else @@ -269,7 +269,7 @@ uint32_t Thread::stack_size() const uint32_t size = 0; _mutex.lock(); - if (_tid != NULL) { + if (_tid != nullptr) { size = osThreadGetStackSize(_tid); } @@ -283,7 +283,7 @@ uint32_t Thread::free_stack() const _mutex.lock(); #if defined(MBED_OS_BACKEND_RTX5) - if (_tid != NULL) { + if (_tid != nullptr) { mbed_rtos_storage_thread_t *thread = (mbed_rtos_storage_thread_t *)_tid; size = (uint32_t)thread->sp - (uint32_t)thread->stack_mem; } @@ -299,7 +299,7 @@ uint32_t Thread::used_stack() const _mutex.lock(); #if defined(MBED_OS_BACKEND_RTX5) - if (_tid != NULL) { + if (_tid != nullptr) { mbed_rtos_storage_thread_t *thread = (mbed_rtos_storage_thread_t *)_tid; size = ((uint32_t)thread->stack_mem + thread->stack_size) - thread->sp; } @@ -314,7 +314,7 @@ uint32_t Thread::max_stack() const uint32_t size = 0; _mutex.lock(); - if (_tid != NULL) { + if (_tid != nullptr) { #if defined(MBED_OS_BACKEND_RTX5) mbed_rtos_storage_thread_t *thread = (mbed_rtos_storage_thread_t *)_tid; uint32_t high_mark = 0; @@ -417,8 +417,8 @@ Thread::~Thread() // terminate is thread safe terminate(); if (_dynamic_stack) { - delete[](uint32_t *)(_attr.stack_mem); - _attr.stack_mem = (uint32_t *)NULL; + delete[] _attr.stack_mem; + _attr.stack_mem = nullptr; } } @@ -427,7 +427,7 @@ void Thread::_thunk(void *thread_ptr) Thread *t = (Thread *)thread_ptr; t->_task(); t->_mutex.lock(); - t->_tid = (osThreadId)NULL; + t->_tid = nullptr; t->_finished = true; t->_join_sem.release(); // rtos will release the mutex automatically diff --git a/rtos/Thread.h b/rtos/Thread.h index f9e25d6f47..f272a5d600 100644 --- a/rtos/Thread.h +++ b/rtos/Thread.h @@ -89,8 +89,8 @@ public: /** Allocate a new thread without starting execution @param priority initial priority of the thread function. (default: osPriorityNormal). @param stack_size stack size (in bytes) requirements for the thread function. (default: OS_STACK_SIZE). - @param stack_mem pointer to the stack area to be used by this thread (default: NULL). - @param name name to be used for this thread. It has to stay allocated for the lifetime of the thread (default: NULL) + @param stack_mem pointer to the stack area to be used by this thread (default: nullptr). + @param name name to be used for this thread. It has to stay allocated for the lifetime of the thread (default: nullptr) @note Default value of tz_module will be MBED_TZ_DEFAULT_ACCESS @note You cannot call this function from ISR context. @@ -98,7 +98,7 @@ public: Thread(osPriority priority = osPriorityNormal, uint32_t stack_size = OS_STACK_SIZE, - unsigned char *stack_mem = NULL, const char *name = NULL) + unsigned char *stack_mem = nullptr, const char *name = nullptr) { constructor(priority, stack_size, stack_mem, name); } @@ -110,15 +110,15 @@ public: threads not using secure calls at all. See "TrustZone RTOS Context Management" for more details. @param priority initial priority of the thread function. (default: osPriorityNormal). @param stack_size stack size (in bytes) requirements for the thread function. (default: OS_STACK_SIZE). - @param stack_mem pointer to the stack area to be used by this thread (default: NULL). - @param name name to be used for this thread. It has to stay allocated for the lifetime of the thread (default: NULL) + @param stack_mem pointer to the stack area to be used by this thread (default: nullptr). + @param name name to be used for this thread. It has to stay allocated for the lifetime of the thread (default: nullptr) @note You cannot call this function from ISR context. */ Thread(uint32_t tz_module, osPriority priority = osPriorityNormal, uint32_t stack_size = OS_STACK_SIZE, - unsigned char *stack_mem = NULL, const char *name = NULL) + unsigned char *stack_mem = nullptr, const char *name = nullptr) { constructor(tz_module, priority, stack_size, stack_mem, name); } @@ -128,7 +128,7 @@ public: @param task function to be executed by this thread. @param priority initial priority of the thread function. (default: osPriorityNormal). @param stack_size stack size (in bytes) requirements for the thread function. (default: OS_STACK_SIZE). - @param stack_mem pointer to the stack area to be used by this thread (default: NULL). + @param stack_mem pointer to the stack area to be used by this thread (default: nullptr). @deprecated Thread-spawning constructors hide errors. Replaced by thread.start(task). @@ -149,17 +149,17 @@ public: Thread(mbed::Callback task, osPriority priority = osPriorityNormal, uint32_t stack_size = OS_STACK_SIZE, - unsigned char *stack_mem = NULL) + unsigned char *stack_mem = nullptr) { constructor(task, priority, stack_size, stack_mem); } /** Create a new thread, and start it executing the specified function. - @param argument pointer that is passed to the thread function as start argument. (default: NULL). + @param argument pointer that is passed to the thread function as start argument. (default: nullptr). @param task argument to task. @param priority initial priority of the thread function. (default: osPriorityNormal). @param stack_size stack size (in bytes) requirements for the thread function. (default: OS_STACK_SIZE). - @param stack_mem pointer to the stack area to be used by this thread (default: NULL). + @param stack_mem pointer to the stack area to be used by this thread (default: nullptr). @deprecated Thread-spawning constructors hide errors. Replaced by thread.start(callback(task, argument)). @@ -181,18 +181,18 @@ public: Thread(T *argument, void (T::*task)(), osPriority priority = osPriorityNormal, uint32_t stack_size = OS_STACK_SIZE, - unsigned char *stack_mem = NULL) + unsigned char *stack_mem = nullptr) { constructor(mbed::callback(task, argument), priority, stack_size, stack_mem); } /** Create a new thread, and start it executing the specified function. - @param argument pointer that is passed to the thread function as start argument. (default: NULL). + @param argument pointer that is passed to the thread function as start argument. (default: nullptr). @param task argument to task. @param priority initial priority of the thread function. (default: osPriorityNormal). @param stack_size stack size (in bytes) requirements for the thread function. (default: OS_STACK_SIZE). - @param stack_mem pointer to the stack area to be used by this thread (default: NULL). + @param stack_mem pointer to the stack area to be used by this thread (default: nullptr). @deprecated Thread-spawning constructors hide errors. Replaced by thread.start(callback(task, argument)). @@ -214,7 +214,7 @@ public: Thread(T *argument, void (*task)(T *), osPriority priority = osPriorityNormal, uint32_t stack_size = OS_STACK_SIZE, - unsigned char *stack_mem = NULL) + unsigned char *stack_mem = nullptr) { constructor(mbed::callback(task, argument), priority, stack_size, stack_mem); @@ -223,10 +223,10 @@ public: /** Create a new thread, and start it executing the specified function. Provided for backwards compatibility @param task function to be executed by this thread. - @param argument pointer that is passed to the thread function as start argument. (default: NULL). + @param argument pointer that is passed to the thread function as start argument. (default: nullptr). @param priority initial priority of the thread function. (default: osPriorityNormal). @param stack_size stack size (in bytes) requirements for the thread function. (default: OS_STACK_SIZE). - @param stack_mem pointer to the stack area to be used by this thread (default: NULL). + @param stack_mem pointer to the stack area to be used by this thread (default: nullptr). @deprecated Thread-spawning constructors hide errors. Replaced by thread.start(callback(task, argument)). @@ -244,10 +244,10 @@ public: MBED_DEPRECATED_SINCE("mbed-os-5.1", "Thread-spawning constructors hide errors. " "Replaced by thread.start(callback(task, argument)).") - Thread(void (*task)(void const *argument), void *argument = NULL, + Thread(void (*task)(void const *argument), void *argument = nullptr, osPriority priority = osPriorityNormal, uint32_t stack_size = OS_STACK_SIZE, - unsigned char *stack_mem = NULL) + unsigned char *stack_mem = nullptr) { constructor(mbed::callback((void (*)(void *))task, argument), priority, stack_size, stack_mem); @@ -389,7 +389,7 @@ public: uint32_t max_stack() const; /** Get thread name - @return thread name or NULL if the name was not set. + @return thread name or nullptr if the name was not set. @note You may call this function from ISR context. */ @@ -475,7 +475,7 @@ public: static osStatus yield(); /** Get the thread id of the current running thread. - @return thread ID for reference by other functions or NULL in case of error. + @return thread ID for reference by other functions or nullptr in case of error. @note You may call this function from ISR context. @deprecated Static methods only affecting current thread cause confusion. Replaced by ThisThread::get_id. @@ -519,18 +519,18 @@ private: // delegated constructors void constructor(osPriority priority = osPriorityNormal, uint32_t stack_size = OS_STACK_SIZE, - unsigned char *stack_mem = NULL, - const char *name = NULL); + unsigned char *stack_mem = nullptr, + const char *name = nullptr); void constructor(mbed::Callback task, osPriority priority = osPriorityNormal, uint32_t stack_size = OS_STACK_SIZE, - unsigned char *stack_mem = NULL, - const char *name = NULL); + unsigned char *stack_mem = nullptr, + const char *name = nullptr); void constructor(uint32_t tz_module, osPriority priority = osPriorityNormal, uint32_t stack_size = OS_STACK_SIZE, - unsigned char *stack_mem = NULL, - const char *name = NULL); + unsigned char *stack_mem = nullptr, + const char *name = nullptr); static void _thunk(void *thread_ptr); mbed::Callback _task; From 163fb19d97b1a72b00de937f791a909fdd2ae122 Mon Sep 17 00:00:00 2001 From: Kevin Bracey Date: Tue, 16 Jul 2019 14:38:08 +0300 Subject: [PATCH 17/17] events: Don't use OsTimer in SysTick builds Previous fix assumed OsTimer is in use - it is for tickless RTOS builds and non-RTOS builds, but non-tickless RTOS builds avoid it altogether and use the SysTick peripheral. Restore previous behaviour for those builds, and just always read the tick count - there is no downside to this when ticking. While in the code, make equeue_tick initialisation explicit. This was problem if the OsTimer is not yet initialised when th done while debugging - turns out not to be part of the fix, but it speeds up the runtime code. --- events/equeue/equeue.c | 1 + events/equeue/equeue_mbed.cpp | 25 +++++++++++++++++-------- events/equeue/equeue_platform.h | 1 + events/equeue/equeue_posix.c | 4 ++++ 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/events/equeue/equeue.c b/events/equeue/equeue.c index 3d55f3a050..3c89b5cfb9 100644 --- a/events/equeue/equeue.c +++ b/events/equeue/equeue.c @@ -80,6 +80,7 @@ int equeue_create_inplace(equeue_t *q, size_t size, void *buffer) q->slab.data = q->buffer; q->queue = 0; + equeue_tick_init(); q->tick = equeue_tick(); q->generation = 0; q->break_requested = false; diff --git a/events/equeue/equeue_mbed.cpp b/events/equeue/equeue_mbed.cpp index e4836051fa..8f2e5f3f7a 100644 --- a/events/equeue/equeue_mbed.cpp +++ b/events/equeue/equeue_mbed.cpp @@ -39,8 +39,16 @@ using namespace mbed; #include "rtos/Kernel.h" #include "platform/mbed_os_timer.h" +void equeue_tick_init() +{ +#if defined MBED_TICKLESS || !MBED_CONF_RTOS_PRESENT + mbed::internal::init_os_timer(); +#endif +} + unsigned equeue_tick() { +#if defined MBED_TICKLESS || !MBED_CONF_RTOS_PRESENT // It is not safe to call get_ms_count from ISRs, both // because documentation says so, and because it will give // a stale value from the RTOS if the interrupt has woken @@ -55,6 +63,14 @@ unsigned equeue_tick() } else { return rtos::Kernel::get_ms_count(); } +#else + // And this is the legacy behaviour - if running in + // non-tickless mode, this works fine, despite Mbed OS + // documentation saying no. (Most recent CMSIS-RTOS + // permits `ososKernelGetTickCount` from IRQ, and our + // `rtos::Kernel` wrapper copes too). + return rtos::Kernel::get_ms_count(); +#endif } #else @@ -70,7 +86,6 @@ unsigned equeue_tick() #define ALIAS_TIMEOUT Timeout #endif -static bool equeue_tick_inited = false; static volatile unsigned equeue_minutes = 0; static unsigned equeue_timer[ (sizeof(ALIAS_TIMER) + sizeof(unsigned) - 1) / sizeof(unsigned)]; @@ -83,7 +98,7 @@ static void equeue_tick_update() reinterpret_cast(equeue_timer)->reset(); } -static void equeue_tick_init() +void equeue_tick_init() { MBED_STATIC_ASSERT(sizeof(equeue_timer) >= sizeof(ALIAS_TIMER), "The equeue_timer buffer must fit the class Timer"); @@ -95,16 +110,10 @@ static void equeue_tick_init() equeue_minutes = 0; timer->start(); ticker->attach_us(equeue_tick_update, 1000 << 16); - - equeue_tick_inited = true; } unsigned equeue_tick() { - if (!equeue_tick_inited) { - equeue_tick_init(); - } - unsigned minutes; unsigned ms; diff --git a/events/equeue/equeue_platform.h b/events/equeue/equeue_platform.h index 5bef6da559..a63a7400e9 100644 --- a/events/equeue/equeue_platform.h +++ b/events/equeue/equeue_platform.h @@ -64,6 +64,7 @@ extern "C" { // limited by the accuracy of this tick. // // Must intentionally overflow to 0 after 2^32-1 +void equeue_tick_init(void); unsigned equeue_tick(void); diff --git a/events/equeue/equeue_posix.c b/events/equeue/equeue_posix.c index 02ebad794b..a39b1e1193 100644 --- a/events/equeue/equeue_posix.c +++ b/events/equeue/equeue_posix.c @@ -25,6 +25,10 @@ // Tick operations +void equeue_tick_init(void) +{ +} + unsigned equeue_tick(void) { struct timeval tv;