CMake: Add support for rtos dir

pull/13566/head
Hugues Kamba 2020-07-20 17:59:56 +01:00
parent 929adbe936
commit 5c453e5d46
20 changed files with 3184 additions and 0 deletions

22
rtos/CMakeLists.txt Normal file
View File

@ -0,0 +1,22 @@
# Copyright (c) 2020 ARM Limited. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
target_sources(mbed-os
PRIVATE
source/ConditionVariable.cpp
source/EventFlags.cpp
source/Kernel.cpp
source/Mutex.cpp
source/Semaphore.cpp
source/ThisThread.cpp
source/Thread.cpp
)
add_subdirectory(source/TARGET_CORTEX)
target_include_directories(mbed-os
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
source
)

550
rtos/ConditionVariable.h Normal file
View File

@ -0,0 +1,550 @@
/* Mbed Microcontroller Library
* Copyright (c) 2017-2019 ARM Limited
* SPDX-License-Identifier: MIT
*
* 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 CONDITIONVARIABLE_H
#define CONDITIONVARIABLE_H
#include <stdint.h>
#include <utility>
#include "rtos/mbed_rtos_types.h"
#include "rtos/Mutex.h"
#include "rtos/Semaphore.h"
#include "rtos/Kernel.h"
#include "platform/NonCopyable.h"
#if MBED_CONF_RTOS_PRESENT || defined(DOXYGEN_ONLY)
namespace rtos {
/** \addtogroup rtos-public-api */
/** @{*/
enum class cv_status {
no_timeout,
timeout
};
struct Waiter;
/**
* \defgroup rtos_ConditionVariable ConditionVariable class
* @{
*/
/** The ConditionVariable class is a synchronization primitive that allows
* threads to wait until a particular condition occurs.
*
* Use the condition variable in conjunction with a mutex to safely wait for
* or notify waiters of condition changes to a resource accessible by multiple
* threads.
*
* The thread that intends to wait on a ConditionVariable must:
* - Acquire a lock on a mutex.
* - Execute `wait`, `wait_for` or `wait_until`. While the thread is waiting,
* the mutex is unlocked.
* - When the condition variable has been notified, or in the case of `wait_for`
* and `wait_until` the timeout expires, the thread is awakened.
*
* The thread that intends to notify a ConditionVariable must:
* - Acquire a lock on the mutex used to construct the condition variable.
* - Execute `notify_one` or `notify_all` on the condition variable.
*
* All threads waiting on the condition variable wake when
* `ConditionVariable::notify_all` is called.
* At least one thread waiting on the condition variable wakes
* when `ConditionVariable::notify_one` is called.
*
* While a thread is waiting for notification of a
* ConditionVariable, it releases the lock held on the mutex.
* The ConditionVariable reacquires the mutex lock before exiting the wait
* function.
*
* #### Unspecified behavior
* - The thread that is unblocked on `ConditionVariable::notify_one` is
* unspecified if there are multiple waiters.
* - When `ConditionVariable::notify_one` or `ConditionVariable::notify_all` is
* called and there are one or more waiters, and one or more threads
* attempting to acquire the condition variable's mutex, the order in which the mutex is
* acquired is unspecified.
* - Spurious notifications (not triggered by the application) can occur.
*
* #### Undefined behavior
* - Calling wait if the mutex is not locked by the current thread is undefined
* behavior.
* - The order in which waiting threads acquire the condition variable's
* mutex after `ConditionVariable::notify_all` is called is undefined.
* - The behavior of `ConditionVariable::wait` and `ConditionVariable::wait_for`
* is undefined if the condition variable's mutex is locked more than once by
* the calling thread.
*
* @note Synchronization level: Thread safe
*
* @note Bare metal profile: This class is not supported.
*
* Example:
*
* @code
* #include "mbed.h"
*
* Mutex mutex;
* ConditionVariable cv(mutex);
*
* // These variables are protected by locking the mutex.
* uint32_t work_count = 0;
* bool done = false;
*
* void worker_thread()
* {
* // Acquire lock on mutex before accessing protected variables and waiting.
* mutex.lock();
*
* while (done == false) {
* printf("Worker thread: Count: %lu\r\n", work_count);
*
* // Wait for main thread to notify the condition variable.
* printf("Worker thread: Waiting\r\n");
* cv.wait();
* }
*
* printf("Worker: Exiting\r\n");
*
* // The condition variable acquires the lock when exiting the `wait` function.
* // Unlock mutex when exiting the thread.
* mutex.unlock();
* }
*
* int main()
* {
* Thread thread;
* thread.start(worker_thread);
*
* for (int i = 0; i < 5; i++) {
* // Acquire lock on mutex before modifying variables and notifying.
* mutex.lock();
*
* // Change count and notify waiters.
* work_count++;
* printf("Main thread: Set count to: %lu\r\n", work_count);
* printf("Main thread: Notifying worker thread\r\n");
* cv.notify_all();
*
* // Mutex must be unlocked before the worker thread can acquire it.
* mutex.unlock();
*
* ThisThread::sleep_for(1000);
* }
*
* // Change done and notify waiters of this.
* mutex.lock();
* done = true;
* cv.notify_all();
* mutex.unlock();
*
* thread.join();
*
* printf("Main: Exiting\r\n");
* }
* @endcode
*/
class ConditionVariable : private mbed::NonCopyable<ConditionVariable> {
public:
/** Create and initialize a ConditionVariable object.
*
* @note You cannot call this function from ISR context.
*/
ConditionVariable(Mutex &mutex);
/** Wait for a notification.
*
* Wait causes the current thread to block until the condition variable
* receives a notification from another thread.
*
* @note - The thread calling this function must be the owner of the
* ConditionVariable's mutex, and it must be locked exactly once.
*
* @note - Spurious notifications can occur, so the caller of this API
* should check to make sure the condition the caller is waiting on has
* been met.
*
* @note - The current thread releases the mutex while inside the wait
* function and reacquires it upon exiting the function.
*
* Example:
* @code
* mutex.lock();
*
* while (!condition_met) {
* cond.wait();
* }
*
* function_to_handle_condition();
*
* mutex.unlock();
* @endcode
*
* @note You cannot call this function from ISR context.
*/
void wait();
/** Wait for a predicate.
*
* Wait causes the current thread to block until the predicate is
* true.
*
* @param pred A function-like object such that `pred()` is convertible to bool
*
* @note - The thread calling this function must be the owner of the
* ConditionVariable's mutex, and it must be locked exactly once.
*
* @note - The current thread releases the mutex while inside the wait
* function and reacquires it upon exiting the function.
*
* Example:
* @code
* extern bool data_available();
*
* mutex.lock();
*
* cond.wait(data_available);
*
* function_to_handle_data();
*
* mutex.unlock();
* @endcode
*
* @note You cannot call this function from ISR context.
*/
template <typename Predicate>
void wait(Predicate pred)
{
while (!pred()) {
wait();
}
}
/** Wait for a notification until the specified time.
*
* Wait until causes the current thread to block until the condition
* variable is notified, or a specific time given by millisec parameter is
* reached.
*
* @param millisec Absolute end time referenced to `Kernel::get_ms_count()`
* @return `true` if a timeout occurred, `false` otherwise.
*
* @note - The thread calling this function must be the owner of the
* ConditionVariable's mutex, and it must be locked exactly once.
*
* @note - Spurious notifications can occur, so the caller of this API
* should check to make sure the condition the caller is waiting on has
* been met.
*
* @note - The current thread releases the lock while inside the wait
* function and reacquires it upon exiting the function.
*
* Example:
* @code
* mutex.lock();
* uint64_t end_time = Kernel::get_ms_count() + COND_WAIT_TIMEOUT;
*
* while (!condition_met) {
* if (cond.wait_until(end_time)) {
* break;
* }
* }
*
* if (condition_met) {
* function_to_handle_condition();
* }
*
* mutex.unlock();
* @endcode
*
* @note You cannot call this function from ISR context.
* @deprecated Pass a chrono time_point, not an integer millisecond count. For example use `Kernel::Clock::now() + 5s`
* rather than `Kernel::get_ms_count() + 5000`.
*/
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono time_point, not an integer millisecond count. For example use `Kernel::Clock::now() + 5s` rather than `Kernel::get_ms_count() + 5000`.")
bool wait_until(uint64_t millisec);
/** Wait for a notification until the specified time.
*
* Wait until causes the current thread to block until the condition
* variable is notified, or a specific time given by millisec parameter is
* reached.
*
* @param abs_time Absolute end time referenced to `Kernel::Clock`
* @return `cv_status::timeout` if a timeout occurred, `cv_status::no_timeout` otherwise.
*
* @note - The thread calling this function must be the owner of the
* ConditionVariable's mutex, and it must be locked exactly once.
*
* @note - Spurious notifications can occur, so the caller of this API
* should check to make sure the condition the caller is waiting on has
* been met.
*
* @note - The current thread releases the lock while inside the wait
* function and reacquires it upon exiting the function.
*
* Example:
* @code
* mutex.lock();
* Kernel::Clock::time_point end_time = Kernel::Clock::now() + 2s;
*
* while (!condition_met) {
* if (cond.wait_until(end_time) == cv_status::timeout) {
* break;
* }
* }
*
* if (condition_met) {
* function_to_handle_condition();
* }
*
* mutex.unlock();
* @endcode
*
* @note You cannot call this function from ISR context.
*/
cv_status wait_until(Kernel::Clock::time_point abs_time);
/** Wait for a predicate until the specified time.
*
* Wait until causes the current thread to block until the predicate is true,
* or a specific time given by abs_time parameter is reached.
*
* @param abs_time Absolute end time referenced to `Kernel::Clock`
* @param pred A function-like object such that `pred()` is convertible to bool
* @return The state of the predicate
*
* @note - The thread calling this function must be the owner of the
* ConditionVariable's mutex, and it must be locked exactly once.
*
* @note - The current thread releases the mutex while inside the wait
* function and reacquires it upon exiting the function.
*
* Example:
* @code
* extern bool data_available();
*
* mutex.lock();
*
* if (cond.wait_until(Kernel::Clock::now() + 2s, data_available)) {
* function_to_handle_data();
* }
*
* mutex.unlock();
* @endcode
*
* @note You cannot call this function from ISR context.
*/
template <class Predicate>
bool wait_until(Kernel::Clock::time_point abs_time, Predicate pred)
{
while (!pred()) {
if (wait_until(abs_time) == cv_status::timeout) {
return pred();
}
}
return true;
}
/** Wait for a notification or timeout.
*
* `Wait for` causes the current thread to block until the condition
* variable receives a notification from another thread, or the timeout
* specified by the millisec parameter is reached.
*
* @param millisec Timeout value or osWaitForever in case of no timeout.
* @return `true` if a timeout occurred, `false` otherwise.
*
* @note - The thread calling this function must be the owner of the
* ConditionVariable's mutex, and it must be locked exactly once.
*
* @note - Spurious notifications can occur, so the caller of this API
* should check to make sure the condition the caller is waiting on has
* been met.
*
* @note - The current thread releases the lock while inside the wait
* function and reacquire it upon exiting the function.
*
* Example:
* @code
* mutex.lock();
*
* while (!condition_met) {
* cond.wait_for(MAX_SLEEP_TIME);
* if (!condition_met) {
* do_other_work_while_condition_false();
* }
* }
*
* if (condition_met) {
* function_to_handle_condition();
* }
*
* mutex.unlock();
* @endcode
*
* @note You cannot call this function from ISR context.
* @deprecated Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.
*/
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.")
bool wait_for(uint32_t millisec);
/** Wait for a notification or timeout.
*
* `Wait for` causes the current thread to block until the condition
* variable receives a notification from another thread, or the timeout
* specified by the millisec parameter is reached.
*
* @param rel_time Timeout value.
* @return `cv_status::timeout` if a timeout occurred, `cv_status::no_timeout` otherwise.
*
* @note - The thread calling this function must be the owner of the
* ConditionVariable's mutex, and it must be locked exactly once.
*
* @note - Spurious notifications can occur, so the caller of this API
* should check to make sure the condition the caller is waiting on has
* been met.
*
* @note - The current thread releases the lock while inside the wait
* function and reacquire it upon exiting the function.
*
* Example:
* @code
* mutex.lock();
*
* while (!condition_met) {
* cond.wait_for(MAX_SLEEP_TIME);
* if (!condition_met) {
* do_other_work_while_condition_false();
* }
* }
*
* if (condition_met) {
* function_to_handle_condition();
* }
*
* mutex.unlock();
* @endcode
*
* @note You cannot call this function from ISR context.
*/
cv_status wait_for(Kernel::Clock::duration_u32 rel_time);
/** Wait for a predicate or timeout.
*
* `Wait for` causes the current thread to block until the predicate
* is true, or the timeout specified by the rel_time parameter is reached.
*
* @param rel_time Timeout value.
* @param pred a function-like object such that `pred()` is convertible to bool
* @return The state of the predicate
*
* @note - The thread calling this function must be the owner of the
* ConditionVariable's mutex, and it must be locked exactly once.
*
* @note - The current thread releases the mutex while inside the wait
* function and reacquire it upon exiting the function.
*
* Example:
* @code
* extern bool data_available();
*
* mutex.lock();
*
* if (cond.wait_for(2s, data_available)) {
* function_to_handle_data();
* }
*
* mutex.unlock();
* @endcode
*
* @note You cannot call this function from ISR context.
*/
template <class Predicate>
bool wait_for(Kernel::Clock::duration rel_time, Predicate pred)
{
return wait_until(Kernel::Clock::now() + rel_time, std::move(pred));
}
/** Notify one waiter on this condition variable that a condition changed.
*
* This function unblocks one of the threads waiting for the condition
* variable.
*
* @note - The thread calling this function must be the owner of the
* ConditionVariable's mutex.
*
* @note - The thread that is unblocked on ConditionVariable::notify_one is
* undefined if there are multiple waiters.
*
* @note You cannot call this function from ISR context.
*/
void notify_one();
/** Notify all waiters on this condition variable that a condition changed.
*
* This function unblocks all of the threads waiting for the condition
* variable.
*
* @note - The thread calling this function must be the owner of the
* ConditionVariable's mutex.
*
* @note - If there are one or more waiters and one or more threads
* attempting to acquire the condition variable's mutex the order in which
* the mutex is acquired is undefined.
*
* @note You cannot call this function from ISR context.
*/
void notify_all();
/** ConditionVariable destructor.
*
* @note You cannot call this function from ISR context.
*/
~ConditionVariable();
#if !defined(DOXYGEN_ONLY)
protected:
struct Waiter {
Waiter();
Semaphore sem;
Waiter *prev;
Waiter *next;
bool in_list;
};
static void _add_wait_list(Waiter **wait_list, Waiter *waiter);
static void _remove_wait_list(Waiter **wait_list, Waiter *waiter);
Mutex &_mutex;
Waiter *_wait_list;
#endif // !defined(DOXYGEN_ONLY)
};
/** @}*/
/** @}*/
} // namespace rtos
#endif
#endif

175
rtos/EventFlags.h Normal file
View File

@ -0,0 +1,175 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2019 ARM Limited
* SPDX-License-Identifier: MIT
*
* 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 EVENT_FLAG_H
#define EVENT_FLAG_H
#include <cstddef>
#include <stdint.h>
#include "rtos/Kernel.h"
#include "rtos/mbed_rtos_types.h"
#include "rtos/mbed_rtos1_types.h"
#include "rtos/mbed_rtos_storage.h"
#include "platform/NonCopyable.h"
namespace rtos {
/** \addtogroup rtos-public-api */
/** @{*/
/**
* \defgroup rtos_EventFlags EventFlags class
* @{
*/
/** The EventFlags class is used to control event flags or wait for event flags other threads control.
@note
EventFlags support 31 flags. The MSB flag is ignored. It is used to return an error code (@a osFlagsError).
@note
Memory considerations: The EventFlags control structures will be created on the current thread's stack, both for the Mbed OS
and underlying RTOS objects (static or dynamic RTOS memory pools are not being used).
*/
class EventFlags : private mbed::NonCopyable<EventFlags> {
public:
/** Create and initialize an EventFlags object.
*
* @note You cannot call this function from ISR context.
*/
EventFlags();
/** Create and initialize an EventFlags object.
@param name name to be used for this EventFlags. It has to stay allocated for the lifetime of the thread.
@note You cannot call this function from ISR context.
*/
EventFlags(const char *name);
/** Set the specified event flags.
@param flags the flags that will be set.
@return event flags after setting or error code if highest bit set (see @a osFlagsError for details).
@note This function may be called from ISR context.
*/
uint32_t set(uint32_t flags);
/** Clear the specified event flags.
@param flags the flags that will be cleared (default: 0x7fffffff -- all flags).
@return event flags before clearing or error code if highest bit set (see @a osFlagsError for details).
@note You may call this function from ISR context.
*/
uint32_t clear(uint32_t flags = 0x7fffffff);
/** Get the currently set event flags.
@return current event flags.
@note You may call this function from ISR context.
*/
uint32_t get() const;
/** Wait for all of the specified event flags to become signaled.
@param flags the flags to wait for (default: 0 -- no flags).
@param millisec timeout value (default: osWaitForever).
@param clear clear specified event flags after waiting for them (default: true).
@return event flags before clearing or error code if highest bit set (see @a osFlagsError for details).
@note You may call this function from ISR context if the millisec parameter is set to 0.
*/
uint32_t wait_all(uint32_t flags = 0, uint32_t millisec = osWaitForever, bool clear = true);
/** Wait for all of the specified event flags to become signaled.
@param flags the flags to wait for.
@param rel_time timeout value.
@param clear clear specified event flags after waiting for them (default: true).
@return event flags before clearing or error code if highest bit set (see @a osFlagsError for details).
@note You may call this function from ISR context if the rel_time parameter is set to 0.
*/
uint32_t wait_all_for(uint32_t flags, Kernel::Clock::duration_u32 rel_time, bool clear = true);
/** Wait for all of the specified event flags to become signaled.
@param flags the flags to wait for.
@param abs_time timeout value.
@param clear clear specified event flags after waiting for them (default: true).
@return event flags before clearing or error code if highest bit set (see @a osFlagsError for details).
@note You cannot call this function from ISR context.
*/
uint32_t wait_all_until(uint32_t flags, Kernel::Clock::time_point abs_time, bool clear = true);
/** Wait for any of the specified event flags to become signaled.
@param flags the flags to wait for (default: 0 -- no flags).
@param millisec timeout value (default: osWaitForever).
@param clear clear specified event flags after waiting for them (default: true).
@return event flags before clearing or error code if highest bit set (see @a osFlagsError for details).
@note This function may be called from ISR context if the millisec parameter is set to 0.
*/
uint32_t wait_any(uint32_t flags = 0, uint32_t millisec = osWaitForever, bool clear = true);
/** Wait for any of the specified event flags to become signaled.
@param flags the flags to wait for.
@param rel_time timeout value.
@param clear clear specified event flags after waiting for them (default: true).
@return event flags before clearing or error code if highest bit set (see @a osFlagsError for details).
@note This function may be called from ISR context if the millisec parameter is set to 0.
*/
uint32_t wait_any_for(uint32_t flags, Kernel::Clock::duration_u32 rel_time, bool clear = true);
/** Wait for any of the specified event flags to become signaled.
@param flags the flags to wait for.
@param abs_time timeout value.
@param clear clear specified event flags after waiting for them (default: true).
@return event flags before clearing or error code if highest bit set (see @a osFlagsError for details).
@note You cannot call this function from ISR context.
*/
uint32_t wait_any_until(uint32_t flags, Kernel::Clock::time_point abs_time, bool clear = true);
/** EventFlags destructor.
@note You cannot call this function from ISR context.
*/
~EventFlags();
private:
void constructor(const char *name = nullptr);
uint32_t wait_for(uint32_t flags, uint32_t opt, Kernel::Clock::duration_u32 rel_time, bool clear);
uint32_t wait_until(uint32_t flags, uint32_t opt, Kernel::Clock::time_point abs_time, bool clear);
#if MBED_CONF_RTOS_PRESENT
osEventFlagsId_t _id;
mbed_rtos_storage_event_flags_t _obj_mem;
#else
uint32_t _flags;
#endif
};
/** @}*/
/** @}*/
}
#endif

143
rtos/Kernel.h Normal file
View File

@ -0,0 +1,143 @@
/* mbed Microcontroller Library
* Copyright (c) 2017-2019 ARM Limited
* SPDX-License-Identifier: MIT
*
* 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 KERNEL_H
#define KERNEL_H
#include <stdint.h>
#include <chrono>
#include "rtos/mbed_rtos_types.h"
#include "platform/mbed_toolchain.h"
#if !MBED_CONF_RTOS_PRESENT
#include "platform/source/mbed_os_timer.h"
#endif
namespace rtos {
/** \addtogroup rtos-public-api */
/** @{*/
/** Functions in the Kernel namespace control RTOS kernel information. */
namespace Kernel {
namespace impl {
/* Internal integer-returning function.
*
* ARM EABI means that `time_point`s do not get returned in registers, so
* it's worth having the actual exteernal definition return an integer, and only
* convert to `time_point` via the inline function `now()`.
*/
uint64_t get_tick_count();
}
/** 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 You cannot call this function from ISR context.
@deprecated Use `Kernel::Clock::now()` to get a chrono time_point instead of an integer millisecond count.
*/
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Use `Kernel::Clock::now()` to get a chrono time_point instead of an integer millisecond count.")
uint64_t get_ms_count();
/** A C++11 chrono TrivialClock for the kernel millisecond tick count
*
* @note To fit better into the chrono framework, Kernel::Clock uses
* std::chrono::milliseconds as its representation, which makes it signed
* and at least 45 bits (so it will be int64_t or equivalent).
*/
struct Clock {
Clock() = delete;
/* Standard TrivialClock fields */
using duration = std::chrono::milliseconds;
using rep = duration::rep;
using period = duration::period;
#if MBED_CONF_RTOS_PRESENT
using time_point = std::chrono::time_point<Clock>;
#else
/* In non-RTOS builds, the clock maps directly to the underlying clock, and must
* indicate that here, so we can do implicit conversion internally.
*/
using time_point = std::chrono::time_point<mbed::internal::OsClock, duration>;
#endif
static constexpr bool is_steady = true;
static time_point now()
{
return time_point(duration(impl::get_tick_count()));
}
/* Extension to make it easy to use 32-bit durations for some APIs, as we historically have,
* for efficiency.
*/
using duration_u32 = std::chrono::duration<uint32_t, period>;
/** Lock the clock to ensure it stays running; dummy for API compatibility with HighResClock */
static void lock()
{
}
/** Unlock the clock, allowing it to stop during power saving; dummy for API compatibility with HighResClock */
static void unlock()
{
}
};
/** Maximum duration for Kernel::Clock::duration_u32-based APIs
*
* @note As duration_u32-based APIs pass through straight to CMSIS-RTOS, they will
* interpret duration_u32(0xFFFFFFFF) as "wait forever". Indicate maximum
* wait time of 0xFFFFFFFE for these calls (which is ~49 days).
*/
constexpr Clock::duration_u32 wait_for_u32_max{osWaitForever - 1};
/** Magic "wait forever" constant for Kernel::Clock::duration_u32-based APIs
*
* Many duration_u32-based APIs treat duration_u32(0xFFFFFFFF) as "wait forever".
*/
constexpr Clock::duration_u32 wait_for_u32_forever{osWaitForever};
/** Attach a function to be called by the RTOS idle task.
@param fptr pointer to the function to be called
@note You may call this function from ISR context.
@note Bare metal profile: This API is not supported.
*/
void attach_idle_hook(void (*fptr)(void));
/** Attach a function to be called when a thread terminates.
@param fptr pointer to the function to be called
@note You may call this function from ISR context.
@note Bare metal profile: This API is not supported.
*/
void attach_thread_terminate_hook(void (*fptr)(osThreadId_t id));
} // namespace Kernel
/** @}*/
} // namespace rtos
#endif

385
rtos/Mail.h Normal file
View File

@ -0,0 +1,385 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2019 ARM Limited
* SPDX-License-Identifier: MIT
*
* 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 MAIL_H
#define MAIL_H
#include <stdint.h>
#include <string.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/mbed_assert.h"
#include "platform/NonCopyable.h"
#ifndef MBED_NO_GLOBAL_USING_DIRECTIVE
using namespace rtos;
#endif
#if MBED_CONF_RTOS_PRESENT || defined(DOXYGEN_ONLY)
namespace rtos {
/** \addtogroup rtos-public-api */
/** @{*/
/**
* \defgroup rtos_Mail Mail class
* @{
*/
/** The Mail class allows you to control, send, receive or wait for mail.
* A mail is a memory block that is sent to a thread or interrupt service routine (ISR).
* @tparam T Data type of a single mail message element.
* @tparam queue_sz Maximum number of mail messages in queue.
*
* @note
* Memory considerations: The mail data store and control structures are part of this class - they do not (themselves)
* allocate memory on the heap, both for the Mbed OS and underlying RTOS objects (static or dynamic RTOS memory
* pools are not being used).
*
* @note
* Bare metal profile: This class is not supported.
*/
template<typename T, uint32_t queue_sz>
class Mail : private mbed::NonCopyable<Mail<T, queue_sz> > {
public:
/** Create and initialize Mail queue.
*
* @note You cannot call this function from ISR context.
*/
Mail() = default;
/** Check if the mail queue is empty.
*
* @return State of queue.
* @retval true Mail queue is empty.
* @retval false Mail queue contains mail.
*
* @note You may call this function from ISR context.
*/
bool empty() const
{
return _queue.empty();
}
/** Check if the mail queue is full.
*
* @return State of queue.
* @retval true Mail queue is full.
* @retval false Mail queue is not full.
*
* @note You may call this function from ISR context.
*/
bool full() const
{
return _queue.full();
}
/** Allocate a memory block of type T, without blocking.
*
* @param millisec Not used (see note).
*
* @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::try_alloc_for or Mail::try_alloc_until
* @deprecated Replaced with try_alloc. In future alloc() will be an untimed blocking call.
*/
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Replaced with try_alloc. In future alloc() will be an untimed blocking call.")
T *alloc(MBED_UNUSED uint32_t millisec = 0)
{
return try_alloc();
}
/** Allocate a memory block of type T, without blocking.
*
* @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::try_alloc_for or Mail::try_alloc_until
*/
T *try_alloc()
{
return _pool.try_alloc();
}
/** Allocate a memory block of type T, optionally blocking.
*
* @param rel_time Timeout value, or Kernel::wait_for_u32_forever.
*
* @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.
*/
T *try_alloc_for(Kernel::Clock::duration_u32 rel_time)
{
return _pool.try_alloc_for(rel_time);
}
/** Allocate a memory block of type T, optionally blocking.
*
* @param millisec Timeout value, or osWaitForever.
*
* @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.
* @deprecated Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.
*/
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.")
T *alloc_for(uint32_t millisec)
{
return try_alloc_for(std::chrono::duration<uint32_t, std::milli>(millisec));
}
/** Allocate a memory block of type T, blocking.
*
* @param abs_time Absolute timeout time, referenced to Kernel::Clock.
*
* @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
* due to internal 32-bit computations, but this is guaranteed to work if the
* wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
* the wait will time out earlier than specified.
*/
T *try_alloc_until(Kernel::Clock::time_point abs_time)
{
return _pool.try_alloc_until(abs_time);
}
/** Allocate a memory block of type T, blocking.
*
* @param millisec Absolute timeout time, referenced to Kernel::get_ms_count().
*
* @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
* due to internal 32-bit computations, but this is guaranteed to work if the
* wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
* the wait will time out earlier than specified.
* @deprecated Pass a chrono time_point, not an integer millisecond count. For example use `Kernel::Clock::now() + 5s`
* rather than `Kernel::get_ms_count() + 5000`.
*/
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono time_point, not an integer millisecond count. For example use `Kernel::Clock::now() + 5s` rather than `Kernel::get_ms_count() + 5000`.")
T *alloc_until(uint64_t millisec)
{
return try_alloc_until(Kernel::Clock::time_point(std::chrono::duration<uint64_t, std::milli>(millisec)));
}
/** Allocate a memory block of type T, and set memory block to zero.
*
* @param millisec Not used (see note).
*
* @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::try_calloc_for or Mail::try_calloc_until
* @deprecated Replaced with try_calloc. In future calloc() will be an untimed blocking call.
*/
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Replaced with try_calloc. In future calloc() will be an untimed blocking call.")
T *calloc(MBED_UNUSED uint32_t millisec = 0)
{
return try_calloc();
}
/** Allocate a memory block of type T, and set memory block to zero.
*
* @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::try_calloc_for or Mail::try_calloc_until
*/
T *try_calloc()
{
return _pool.try_calloc();
}
/** Allocate a memory block of type T, optionally blocking, and set memory block to zero.
*
* @param rel_time Timeout value, or Kernel::wait_for_u32_forever.
*
* @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 rel_time parameter is set to 0.
*/
T *try_calloc_for(Kernel::Clock::duration_u32 rel_time)
{
return _pool.try_calloc_for(rel_time);
}
/** Allocate a memory block of type T, optionally blocking, and set memory block to zero.
*
* @param millisec Timeout value, or osWaitForever.
*
* @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.
* @deprecated Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.
*/
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.")
T *calloc_for(uint32_t millisec)
{
return try_calloc_for(std::chrono::duration<uint32_t, std::milli>(millisec));
}
/** Allocate a memory block of type T, blocking, and set memory block to zero.
*
* @param abs_time Absolute timeout time, referenced to Kernel::Clock.
*
* @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
* due to internal 32-bit computations, but this is guaranteed to work if the
* wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
* the wait will time out earlier than specified.
*/
T *try_calloc_until(Kernel::Clock::time_point abs_time)
{
return _pool.try_calloc_until(abs_time);
}
/** Allocate a memory block of type T, blocking, and set memory block to zero.
*
* @param millisec Absolute timeout time, referenced to Kernel::get_ms_count().
*
* @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
* due to internal 32-bit computations, but this is guaranteed to work if the
* wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
* the wait will time out earlier than specified.
* @deprecated Pass a chrono time_point, not an integer millisecond count. For example use `Kernel::Clock::now() + 5s`
* rather than `Kernel::get_ms_count() + 5000`.
*/
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono time_point, not an integer millisecond count. For example use `Kernel::Clock::now() + 5s` rather than `Kernel::get_ms_count() + 5000`.")
T *calloc_until(uint64_t millisec)
{
return try_calloc_until(Kernel::Clock::time_point(std::chrono::duration<uint64_t, std::milli>(millisec)));
}
/** Put a mail in the queue.
*
* @param mptr Memory block previously allocated with Mail::alloc or Mail::calloc.
*
* @return Status code that indicates the execution status of the function (osOK on success).
* See note.
*
* @note You may call this function from ISR context.
* @note As the mail should have already been allocated, and the memory pool is the same size
* as the queue, the put operation should always succeed, despite being implemented with
* Queue::try_put - there is room in the queue for every mail from the pool. Therefore
* use of the return value is deprecated, and the function will return void in future.
*/
osStatus put(T *mptr)
{
bool ok = _queue.try_put(mptr);
MBED_ASSERT(ok);
return ok ? osOK : osErrorResource;
}
/** Get a mail from the queue.
*
* @param rel_time Timeout value (default: Kernel::wait_for_u32_forever).
*
* @return Event that contains mail information and status code. The status code
* is stored in the status member:
* @a osEventMail Mail successfully received.
* @a osOK No mail is available (and no timeout was specified).
* @a osEventTimeout No mail has arrived during the given timeout period.
* @a osErrorParameter A parameter is invalid or outside of a permitted range.
*
* @note You may call this function from ISR context if the millisec parameter is set to 0.
* @deprecated Replaced with try_get and try_get_for. In future get will be an untimed blocking call.
*/
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Replaced with try_get and try_get_for. In future get will be an untimed blocking call.")
osEvent get(uint32_t millisec = osWaitForever)
{
osEvent evt = _queue.get(millisec);
if (evt.status == osEventMessage) {
evt.status = osEventMail;
}
return evt;
}
/** Get a mail from the queue.
*
* @return Pointer to received mail, or nullptr if none was received.
*
* @note You may call this function from ISR context.
*/
T *try_get()
{
T *mptr = nullptr;
_queue.try_get(&mptr);
return mptr;
}
/** Get a mail from the queue.
*
* @param rel_time Timeout value or Kernel::wait_for_u32_forever.
*
* @return Pointer to received mail, or nullptr if none was received.
*
* @note You may call this function from ISR context if the millisec parameter is set to 0.
*/
T *try_get_for(Kernel::Clock::duration_u32 rel_time)
{
T *mptr = nullptr;
_queue.try_get_for(rel_time, &mptr);
return mptr;
}
/** Free a memory block from a mail.
*
* @param mptr Pointer to the memory block that was obtained with Mail::get.
*
* @return Status code that indicates the execution status of the function (osOK on success).
*
* @note You may call this function from ISR context.
*/
osStatus free(T *mptr)
{
return _pool.free(mptr);
}
private:
Queue<T, queue_sz> _queue;
MemoryPool<T, queue_sz> _pool;
};
/** @}*/
/** @}*/
}
#endif
#endif

288
rtos/MemoryPool.h Normal file
View File

@ -0,0 +1,288 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2019 ARM Limited
* SPDX-License-Identifier: MIT
*
* 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 MEMORYPOOL_H
#define MEMORYPOOL_H
#include <stdint.h>
#include <string.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/mbed_assert.h"
#include "Kernel.h"
#if MBED_CONF_RTOS_PRESENT || defined(DOXYGEN_ONLY)
namespace rtos {
/** \addtogroup rtos-public-api */
/** @{*/
/**
* \defgroup rtos_MemoryPool MemoryPool class
* @{
*/
/** Define and manage fixed-size memory pools of objects of a given type.
@tparam T data type of a single object (element).
@tparam queue_sz maximum number of objects (elements) in the memory pool.
@note
Memory considerations: The memory pool data store and control structures will be created on current thread's stack,
both for the mbed OS and underlying RTOS objects (static or dynamic RTOS memory pools are not being used).
@note
Bare metal profile: This class is not supported.
*/
template<typename T, uint32_t pool_sz>
class MemoryPool : private mbed::NonCopyable<MemoryPool<T, pool_sz> > {
MBED_STATIC_ASSERT(pool_sz > 0, "Invalid memory pool size. Must be greater than 0.");
public:
/** Create and Initialize a memory pool.
*
* @note You cannot call this function from ISR context.
*/
MemoryPool()
{
memset(_pool_mem, 0, sizeof(_pool_mem));
osMemoryPoolAttr_t attr = { 0 };
attr.mp_mem = _pool_mem;
attr.mp_size = sizeof(_pool_mem);
attr.cb_mem = &_obj_mem;
attr.cb_size = sizeof(_obj_mem);
_id = osMemoryPoolNew(pool_sz, sizeof(T), &attr);
MBED_ASSERT(_id);
}
/** Destroy a memory pool
*
* @note You cannot call this function from ISR context.
*/
~MemoryPool()
{
osMemoryPoolDelete(_id);
}
/** Allocate a memory block from a memory pool, without blocking.
@return address of the allocated memory block or nullptr in case of no memory available.
@note You may call this function from ISR context.
@deprecated Replaced with try_alloc. In future alloc() will be an untimed blocking call.
*/
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Replaced with try_alloc. In future alloc() will be an untimed blocking call.")
T *alloc()
{
return try_alloc();
}
/** Allocate a memory block from a memory pool, without blocking.
@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 *try_alloc()
{
return (T *)osMemoryPoolAlloc(_id, 0);
}
/** 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 nullptr in case of no memory available.
@note You may call this function from ISR context if the millisec parameter is set to 0.
@deprecated Replaced with `try_alloc_for`. For example use `try_alloc_for(5s)` rather than `alloc_for(5000)`.
*/
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Replaced with `try_alloc_for`. For example use `try_alloc_for(5s)` rather than `alloc_for(5000)`.")
T *alloc_for(uint32_t millisec)
{
return try_alloc_for(std::chrono::duration<uint32_t, std::milli>(millisec));
}
/** Allocate a memory block from a memory pool, optionally blocking.
@param rel_time timeout value (Kernel::wait_for_u32_forever to wait forever)
@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 rel_time parameter is set to 0.
*/
T *try_alloc_for(Kernel::Clock::duration_u32 rel_time)
{
return (T *)osMemoryPoolAlloc(_id, rel_time.count());
}
/** 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 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
due to internal 32-bit computations, but this is guaranteed to work if the
wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
the wait will time out earlier than specified.
@deprecated Replaced with `try_alloc_until`. For example use `try_alloc_until(Kernel::Clock::now() + 5s)`
rather than `alloc_until(Kernel::get_ms_count() + 5000)`.
*/
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Replaced with `try_alloc_until`. For example use `try_alloc_until(Kernel::Clock::now() + 5s)` rather than `alloc_until(Kernel::get_ms_count() + 5000)`.")
T *alloc_until(uint64_t millisec)
{
return try_alloc_until(Kernel::Clock::time_point(std::chrono::duration<uint64_t, std::milli>(millisec)));
}
/** Allocate a memory block from a memory pool, blocking.
@param abs_time absolute timeout time, referenced to Kernel::Clock.
@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
due to internal 32-bit computations, but this is guaranteed to work if the
wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
the wait will time out earlier than specified.
*/
T *try_alloc_until(Kernel::Clock::time_point abs_time)
{
Kernel::Clock::time_point now = Kernel::Clock::now();
Kernel::Clock::duration_u32 rel_time;
if (now >= abs_time) {
rel_time = rel_time.zero();
} else if (abs_time - now > Kernel::wait_for_u32_max) {
rel_time = Kernel::wait_for_u32_max;
} else {
rel_time = abs_time - now;
}
return try_alloc_for(rel_time);
}
/** Allocate a memory block from a memory pool, without blocking, and set memory block to zero.
@return address of the allocated memory block or nullptr in case of no memory available.
@note You may call this function from ISR context.
@deprecated Replaced with try_calloc. In future calloc() will be an untimed blocking call.
*/
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Replaced with try_calloc. In future calloc() will be an untimed blocking call.")
T *calloc()
{
return try_calloc();
}
/** Allocate a memory block from a memory pool, without blocking, and set memory block to zero.
@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 *try_calloc()
{
T *item = try_alloc();
if (item != nullptr) {
memset(item, 0, sizeof(T));
}
return item;
}
/** 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 nullptr in case of no memory available.
@note You may call this function from ISR context if the millisec parameter is set to 0.
@deprecated Replaced with `try_calloc_for`. For example use `try_calloc_for(5s)` rather than `calloc_for(5000)`.
*/
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Replaced with `try_calloc_for`. For example use `try_calloc_for(5s)` rather than `calloc_for(5000)`.")
T *calloc_for(uint32_t millisec)
{
return try_calloc_for(std::chrono::duration<uint32_t, std::milli>(millisec));
}
/** Allocate a memory block from a memory pool, optionally blocking, and set memory block to zero.
@param rel_time timeout value (Kernel::wait_for_u32_forever to wait forever)
@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 rel_time parameter is set to 0.
*/
T *try_calloc_for(Kernel::Clock::duration_u32 rel_time)
{
T *item = try_alloc_for(rel_time);
if (item != nullptr) {
memset(item, 0, sizeof(T));
}
return item;
}
/** 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 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
due to internal 32-bit computations, but this is guaranteed to work if the
wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
the wait will time out earlier than specified.
@deprecated Replaced with `try_calloc_until`. For example use `try_calloc_until(Kernel::Clock::now() + 5s)`
rather than `calloc_until(Kernel::get_ms_count() + 5000)`.
*/
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Replaced with `try_calloc_until`. For example use `try_calloc_until(Kernel::Clock::now() + 5s)` rather than `calloc_until(Kernel::get_ms_count() + 5000)`.")
T *calloc_until(uint64_t millisec)
{
return try_calloc_until(Kernel::Clock::time_point(std::chrono::duration<uint64_t, std::milli>(millisec)));
}
/** Allocate a memory block from a memory pool, blocking, and set memory block to zero.
@param abs_time absolute timeout time, referenced to Kernel::Clock.
@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
due to internal 32-bit computations, but this is guaranteed to work if the
wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
the wait will time out earlier than specified.
*/
T *try_calloc_until(Kernel::Clock::time_point abs_time)
{
T *item = try_alloc_until(abs_time);
if (item != nullptr) {
memset(item, 0, sizeof(T));
}
return item;
}
/** 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 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.
*/
osStatus free(T *block)
{
return osMemoryPoolFree(_id, block);
}
private:
osMemoryPoolId_t _id;
char _pool_mem[MBED_RTOS_STORAGE_MEM_POOL_MEM_SIZE(pool_sz, sizeof(T))];
mbed_rtos_storage_mem_pool_t _obj_mem;
};
/** @}*/
/** @}*/
}
#endif
#endif

234
rtos/Mutex.h Normal file
View File

@ -0,0 +1,234 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2019 ARM Limited
* SPDX-License-Identifier: MIT
*
* 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 MUTEX_H
#define MUTEX_H
#include <stdint.h>
#include "rtos/mbed_rtos_types.h"
#include "rtos/mbed_rtos1_types.h"
#include "rtos/mbed_rtos_storage.h"
#include "rtos/Kernel.h"
#include "platform/NonCopyable.h"
#include "platform/ScopedLock.h"
#include "platform/mbed_toolchain.h"
namespace rtos {
/** \addtogroup rtos-public-api */
/** @{*/
class Mutex;
/** Typedef for the mutex lock
*
* Usage:
* @code
* void foo(Mutex &m) {
* ScopedMutexLock lock(m);
* // Mutex lock protects code in this block
* }
* @endcode
*/
typedef mbed::ScopedLock<Mutex> ScopedMutexLock;
/**
* \defgroup rtos_Mutex Mutex class
* @{
*/
/** 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.
@note
Memory considerations: The mutex control structures are created on the current thread's stack, both for the Mbed OS
and underlying RTOS objects (static or dynamic RTOS memory pools are not being used).
*/
class Mutex : private mbed::NonCopyable<Mutex> {
public:
/** Create and Initialize a Mutex object
*
* @note You cannot call this function from ISR context.
*/
Mutex();
/** Create and Initialize a Mutex object
@param name name to be used for this mutex. It has to stay allocated for the lifetime of the thread.
@note You cannot call this function from ISR context.
*/
Mutex(const char *name);
/**
Wait until a Mutex becomes available.
@note You cannot call this function from ISR context.
*/
void lock();
/** Try to lock the mutex, and return immediately
@return true if the mutex was acquired, false otherwise.
@note equivalent to trylock_for(0)
@note You cannot call this function from ISR context.
*/
bool trylock();
/** Try to lock the mutex for a specified time
@param millisec timeout value.
@return true if the mutex was acquired, false otherwise.
@note the underlying RTOS may have a limit to the maximum wait time
due to internal 32-bit computations, but this is guaranteed to work if the
wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
the lock attempt will time out earlier than specified.
@note You cannot call this function from ISR context.
@deprecated Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.
*/
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.")
bool trylock_for(uint32_t millisec);
/** Try to lock the mutex for a specified time
@param rel_time timeout value.
@return true if the mutex was acquired, false otherwise.
@note the underlying RTOS may have a limit to the maximum wait time
due to internal 32-bit computations, but this is guaranteed to work if the
wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
the lock attempt will time out earlier than specified.
@note You cannot call this function from ISR context.
*/
bool trylock_for(Kernel::Clock::duration_u32 rel_time);
/** Try to lock the mutex until specified time
@param millisec absolute timeout time, referenced to Kernel::get_ms_count()
@return true if the mutex was acquired, false otherwise.
@note the underlying RTOS may have a limit to the maximum wait time
due to internal 32-bit computations, but this is guaranteed to work if the
wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
the lock attempt will time out earlier than specified.
@note You cannot call this function from ISR context.
@deprecated Pass a chrono time_point, not an integer millisecond count. For example use
`Kernel::Clock::now() + 5s` rather than `Kernel::get_ms_count() + 5000`.
*/
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono time_point, not an integer millisecond count. For example use `Kernel::Clock::now() + 5s` rather than `Kernel::get_ms_count() + 5000`.")
bool trylock_until(uint64_t millisec);
/** Try to lock the mutex until specified time
@param abs_time absolute timeout time, referenced to Kernel::get_ms_count()
@return true if the mutex was acquired, false otherwise.
@note the underlying RTOS may have a limit to the maximum wait time
due to internal 32-bit computations, but this is guaranteed to work if the
wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
the lock attempt will time out earlier than specified.
@note You cannot call this function from ISR context.
*/
bool trylock_until(Kernel::Clock::time_point abs_time);
/**
Unlock the mutex that has previously been locked by the same thread
@note You cannot call this function from ISR context.
*/
void unlock();
/** Get the owner the this mutex
@return the current owner of this mutex.
@note You cannot call this function from ISR context.
*/
osThreadId_t get_owner();
/** Mutex destructor
*
* @note You cannot call this function from ISR context.
*/
~Mutex();
private:
#if MBED_CONF_RTOS_PRESENT
void constructor(const char *name = nullptr);
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_for(Kernel::Clock::duration_u32)
{
return true;
}
inline bool Mutex::trylock_until(uint64_t)
{
return true;
}
inline bool Mutex::trylock_until(Kernel::Clock::time_point)
{
return true;
}
inline void Mutex::unlock()
{
}
#endif
/** @}*/
/** @}*/
}
#endif

348
rtos/Queue.h Normal file
View File

@ -0,0 +1,348 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2019 ARM Limited
* SPDX-License-Identifier: MIT
*
* 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 QUEUE_H
#define QUEUE_H
#include "rtos/mbed_rtos_types.h"
#include "rtos/mbed_rtos1_types.h"
#include "rtos/mbed_rtos_storage.h"
#include "rtos/Kernel.h"
#include "platform/mbed_error.h"
#include "platform/NonCopyable.h"
#if MBED_CONF_RTOS_PRESENT || defined(DOXYGEN_ONLY)
namespace rtos {
/** \addtogroup rtos-public-api */
/** @{*/
/**
* \defgroup rtos_Queue Queue class
* @{
*/
/** The Queue class represents a collection of objects that are stored first by
* order of priority, and then in first-in, first-out (FIFO) order.
*
* You can use a queue when you need to store data and then access it in the same
* order that it has been stored. The order in which you retrieve the data is in
* order of descending priority. If multiple elements have the same priority,
* they are retrieved in FIFO order.
*
* The object type stored in the queue can be an integer, pointer or a generic
* type given by the template parameter T.
*
* @tparam T Specifies the type of elements stored in the queue.
* @tparam queue_sz Maximum number of messages that you can store in the queue.
*
* @note Memory considerations: The queue control structures are created on the
* current thread's stack, both for the Mbed OS and underlying RTOS
* objects (static or dynamic RTOS memory pools are not being used).
*
* @note Bare metal profile: This class is not supported.
*/
template<typename T, uint32_t queue_sz>
class Queue : private mbed::NonCopyable<Queue<T, queue_sz> > {
public:
/** Create and initialize a message Queue of objects of the parameterized
* type `T` and maximum capacity specified by `queue_sz`.
*
* @note You cannot call this function from ISR context.
*/
Queue()
{
osMessageQueueAttr_t attr = { 0 };
attr.mq_mem = _queue_mem;
attr.mq_size = sizeof(_queue_mem);
attr.cb_mem = &_obj_mem;
attr.cb_size = sizeof(_obj_mem);
_id = osMessageQueueNew(queue_sz, sizeof(T *), &attr);
MBED_ASSERT(_id);
}
/** Queue destructor
*
* @note You cannot call this function from ISR context.
*/
~Queue()
{
osMessageQueueDelete(_id);
}
/** Check if the queue is empty.
*
* @return True if the queue is empty, false if not
*
* @note You may call this function from ISR context.
*/
bool empty() const
{
return osMessageQueueGetCount(_id) == 0;
}
/** Check if the queue is full.
*
* @return True if the queue is full, false if not
*
* @note You may call this function from ISR context.
*/
bool full() const
{
return osMessageQueueGetSpace(_id) == 0;
}
/** Get number of queued messages in the queue.
*
* @return Number of items in the queue
*
* @note You may call this function from ISR context.
*/
uint32_t count() const
{
return osMessageQueueGetCount(_id);
}
/** Inserts the given element to the end of the queue.
*
* This function puts the message pointed to by `data` into the queue. The
* parameter `prio` is used to sort the message according to their priority
* (higher numbers indicate higher priority) on insertion.
*
* The function does not block, and returns immediately if the queue is full.
*
* @param data Pointer to the element to insert into the queue.
* @param prio Priority of the operation or 0 in case of default.
* (default: 0)
*
* @return true if the element was inserted, false otherwise.
*
* @note You may call this function from ISR context.
*/
bool try_put(T *data, uint8_t prio = 0)
{
return try_put_for(Kernel::Clock::duration_u32::zero(), data, prio);
}
/** Inserts the given element to the end of the queue.
*
* This function puts the message pointed to by `data` into the queue. The
* parameter `prio` is used to sort the message according to their priority
* (higher numbers indicate higher priority) on insertion.
*
* The timeout indicated by the parameter `rel_time` specifies how long the
* function blocks waiting for the message to be inserted into the
* queue.
*
* The parameter `rel_time` can have the following values:
* - When the duration is 0, the function returns instantly. You could use
* `try_put` instead.
* - When the duration is Kernel::wait_for_u32_forever, the function waits for an
* infinite time.
* - For all other values, the function waits for the given duration.
*
* @param rel_time Timeout for the operation to be executed.
* @param data Pointer to the element to insert into the queue.
* @param prio Priority of the operation or 0 in case of default.
* (default: 0)
*
* @return true if the element was inserted, false otherwise.
*
* @note You may call this function from ISR context if the rel_time
* parameter is set to 0.
*
*/
bool try_put_for(Kernel::Clock::duration_u32 rel_time, T *data, uint8_t prio = 0)
{
osStatus status = osMessageQueuePut(_id, &data, prio, rel_time.count());
return status == osOK;
}
/** Inserts the given element to the end of the queue.
*
* This function puts the message pointed to by `data` into the queue. The
* parameter `prio` is used to sort the message according to their priority
* (higher numbers indicate higher priority) on insertion.
*
* The timeout indicated by the parameter `millisec` specifies how long the
* function blocks waiting for the message to be inserted into the
* queue.
*
* The parameter `millisec` can have the following values:
* - When the timeout is 0, the function returns instantly.
* - When the timeout is osWaitForever, the function waits for an
* infinite time.
* - For all other values, the function waits for the given number of
* milliseconds.
*
* @param data Pointer to the element to insert into the queue.
* @param millisec Timeout for the operation to be executed, or 0 in case
* of no timeout.
* @param prio Priority of the operation or 0 in case of default.
* (default: 0)
*
* @return Status code that indicates the execution status of the function:
* @a osOK The message has been successfully inserted
* into the queue.
* @a osErrorTimeout The message could not be inserted into the
* queue in the given time.
* @a osErrorResource The message could not be inserted because
* the queue is full.
* @a osErrorParameter Internal error or nonzero timeout specified
* in an ISR.
*
* @note You may call this function from ISR context if the millisec
* parameter is set to 0.
* @deprecated Replaced with try_put and try_put_for. In future put will be an untimed blocking call.
*/
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Replaced with try_put and try_put_for. In future put will be an untimed blocking call.")
osStatus put(T *data, uint32_t millisec = 0, uint8_t prio = 0)
{
return osMessageQueuePut(_id, &data, prio, millisec);
}
/** Get a message from the queue.
*
* This function retrieves a message from the queue. The message is stored
* in the location pointed to be the parameter `data_out`.
*
* The function does not block, and returns immediately if the queue is empty.
*
* @param[out] data_out Pointer to location to write the element retrieved from the queue.
*
* @return true if an element was received and written to data_out.
*
* @note You may call this function from ISR context.
*/
bool try_get(T **data_out)
{
return try_get_for(Kernel::Clock::duration_u32::zero(), data_out);
}
/** Get a message or wait for a message from the queue.
*
* This function retrieves a message from the queue. The message is stored
* in the location pointed to be the parameter `data_out`.
*
* The timeout specified by the parameter `rel_time` specifies how long the
* function waits to retrieve the message from the queue.
*
* The timeout parameter can have the following values:
* - When the timeout is 0, the function returns instantly.
* - When the timeout is Kernel::wait_for_u32_forever, the function waits
* infinite time until the message is retrieved.
* - When the timeout is any other value, the function waits for the
* specified time before returning a timeout error.
*
* Messages are retrieved in descending priority order. If two messages
* share the same priority level, they are retrieved in first-in, first-out
* (FIFO) order.
*
* @param rel_time Timeout value.
* @param[out] data_out Pointer to location to write the element retrieved from the queue.
*
* @return true if an element was received and written to data_out.
*
* @note You may call this function from ISR context if the rel_time
* parameter is set to 0.
*/
bool try_get_for(Kernel::Clock::duration_u32 rel_time, T **data_out)
{
osStatus status = osMessageQueueGet(_id, data_out, nullptr, rel_time.count());
return status == osOK;
}
/** Get a message or wait for a message from the queue.
*
* This function retrieves a message from the queue. The message is stored
* in the value field of the returned `osEvent` object.
*
* The timeout specified by the parameter `millisec` specifies how long the
* function waits to retrieve the message from the queue.
*
* The timeout parameter can have the following values:
* - When the timeout is 0, the function returns instantly.
* - When the timeout is osWaitForever (default), the function waits
* infinite time until the message is retrieved.
* - When the timeout is any other value, the function waits for the
* specified time before returning a timeout error.
*
* Messages are retrieved in descending priority order. If two messages
* share the same priority level, they are retrieved in first-in, first-out
* (FIFO) order.
*
* @param millisec Timeout value.
*
* @return Event information that includes the message in event. Message
* value and the status code in event.status:
* @a osEventMessage Message successfully received.
* @a osOK No message is available in the queue, and no
* timeout was specified.
* @a osEventTimeout No message was received before a timeout
* event occurred.
* @a osErrorParameter A parameter is invalid or outside of a
* permitted range.
*
* @note You may call this function from ISR context if the millisec
* parameter is set to 0.
* @deprecated Replaced with try_get and try_get_for. In future get will be an untimed blocking call.
*/
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Replaced with try_get and try_get_for. In future get will be an untimed blocking call.")
osEvent get(uint32_t millisec = osWaitForever)
{
osEvent event;
T *data = nullptr;
osStatus_t res = osMessageQueueGet(_id, &data, nullptr, millisec);
switch (res) {
case osOK:
event.status = (osStatus)osEventMessage;
event.value.p = data;
break;
case osErrorResource:
event.status = osOK;
break;
case osErrorTimeout:
event.status = (osStatus)osEventTimeout;
break;
case osErrorParameter:
default:
event.status = osErrorParameter;
break;
}
event.def.message_id = _id;
return event;
}
private:
osMessageQueueId_t _id;
char _queue_mem[queue_sz * (sizeof(T *) + sizeof(mbed_rtos_storage_message_t))];
mbed_rtos_storage_msg_queue_t _obj_mem;
};
/** @}*/
/** @}*/
} // namespace rtos
#endif
#endif // QUEUE_H

159
rtos/Semaphore.h Normal file
View File

@ -0,0 +1,159 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2019 ARM Limited
* SPDX-License-Identifier: MIT
*
* 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 SEMAPHORE_H
#define SEMAPHORE_H
#include <stdint.h>
#include <chrono>
#include "rtos/mbed_rtos_types.h"
#include "rtos/mbed_rtos1_types.h"
#include "rtos/mbed_rtos_storage.h"
#include "rtos/Kernel.h"
#include "platform/mbed_toolchain.h"
#include "platform/NonCopyable.h"
namespace rtos {
/** \addtogroup rtos-public-api */
/** @{*/
/**
* \defgroup rtos_Semaphore Semaphore class
* @{
*/
/** The Semaphore class is used to manage and protect access to a set of shared resources.
*
* @note
* Memory considerations: The semaphore control structures will be created on current thread's stack, both for the mbed OS
* and underlying RTOS objects (static or dynamic RTOS memory pools are not being used).
*/
class Semaphore : private mbed::NonCopyable<Semaphore> {
public:
/** Create and Initialize a Semaphore object used for managing resources.
@param count number of available resources; maximum index value is (count-1). (default: 0).
@note You cannot call this function from ISR context.
*/
Semaphore(int32_t count = 0);
/** Create and Initialize a Semaphore object used for managing resources.
@param count number of available resources
@param max_count maximum number of available resources
@note You cannot call this function from ISR context.
*/
Semaphore(int32_t count, uint16_t max_count);
/** Wait until a Semaphore resource becomes available.
@note You cannot call this function from ISR context.
*/
void acquire();
/** Try to acquire a Semaphore resource, and return immediately
@return true if a resource was acquired, false otherwise.
@note equivalent to try_acquire_for(0)
@note You may call this function from ISR context.
*/
bool try_acquire();
/** Wait until a Semaphore resource becomes available.
@param millisec timeout value.
@return true if a resource was acquired, false otherwise.
@note You may call this function from ISR context if the millisec parameter is set to 0.
@deprecated Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.
*/
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.")
bool try_acquire_for(uint32_t millisec);
/** Wait until a Semaphore resource becomes available.
@param rel_time timeout value.
@return true if a resource was acquired, false otherwise.
@note You may call this function from ISR context if the rel_time parameter is set to 0.
*/
bool try_acquire_for(Kernel::Clock::duration_u32 rel_time);
/** Wait until a Semaphore resource becomes available.
@param millisec absolute timeout time, referenced to Kernel::get_ms_count()
@return true if a resource was acquired, false otherwise.
@note the underlying RTOS may have a limit to the maximum wait time
due to internal 32-bit computations, but this is guaranteed to work if the
wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
the acquire attempt will time out earlier than specified.
@note You cannot call this function from ISR context.
@deprecated Pass a chrono time_point, not an integer millisecond count. For example use
`Kernel::Clock::now() + 5s` rather than `Kernel::get_ms_count() + 5000`.
*/
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono time_point, not an integer millisecond count. For example use `Kernel::Clock::now() + 5s` rather than `Kernel::get_ms_count() + 5000`.")
bool try_acquire_until(uint64_t millisec);
/** Wait until a Semaphore resource becomes available.
@param millisec absolute timeout time, referenced to Kernel::get_ms_count()
@return true if a resource was acquired, false otherwise.
@note the underlying RTOS may have a limit to the maximum wait time
due to internal 32-bit computations, but this is guaranteed to work if the
wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
the acquire attempt will time out earlier than specified.
@note You cannot call this function from ISR context.
*/
bool try_acquire_until(Kernel::Clock::time_point abs_time);
/** Release a Semaphore resource that was obtain with Semaphore::acquire.
@return status code that indicates the execution status of the function:
@a osOK the token has been correctly released.
@a osErrorResource the maximum token count has been reached.
@a osErrorParameter internal error.
@note You may call this function from ISR context.
*/
osStatus release(void);
/** Semaphore destructor
*
* @note You cannot call this function from ISR context.
*/
~Semaphore();
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
};
/** @}*/
/** @}*/
}
#endif

290
rtos/ThisThread.h Normal file
View File

@ -0,0 +1,290 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2019 ARM Limited
* SPDX-License-Identifier: MIT
*
* 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 THIS_THREAD_H
#define THIS_THREAD_H
#include <stdint.h>
#include "platform/mbed_toolchain.h"
#include "rtos/Kernel.h"
#include "rtos/mbed_rtos_types.h"
namespace rtos {
/** \addtogroup rtos-public-api */
/** @{*/
/**
* \defgroup rtos_ThisThread ThisThread namespace
* @{
*/
/** The ThisThread namespace allows controlling the current thread.
*
* Example:
* @code
* #include "mbed.h"
* #include "rtos.h"
*
* Thread thread;
* DigitalOut led1(LED1);
*
* #define STOP_FLAG 1
*
* // Blink function toggles the led in a long running loop
* void blink(DigitalOut *led) {
* while (!ThisThread::flags_wait_any_for(STOP_FLAG, 1000)) {
* *led = !*led;
* }
* }
*
* // Spawns a thread to run blink for 5 seconds
* int main() {
* thread.start(callback(blink, &led1));
* ThisThread::sleep_for(5000);
* thread.signal_set(STOP_FLAG);
* thread.join();
* }
* @endcode
*
*/
namespace ThisThread {
/** Clears the specified Thread Flags of the currently running thread.
@param flags specifies the flags of the thread that should be cleared.
@return thread flags before clearing.
@note You cannot call this function from ISR context.
@see Thread::flags_set
*/
uint32_t flags_clear(uint32_t flags);
/** Returns the Thread Flags currently set for the currently running thread.
@return current thread flags or 0 if not in a valid thread.
@note You cannot call this function from ISR context.
@see Thread::flags_set
*/
uint32_t flags_get();
/** Wait for all of the specified Thread Flags to become signaled for the current thread.
@param flags specifies the flags to wait for
@param clear whether to clear the specified flags after waiting for them. (default: true)
@return actual thread flags before clearing, which will satisfy the wait
@note You cannot call this function from ISR context.
@see Thread::flags_set
*/
uint32_t flags_wait_all(uint32_t flags, bool clear = true);
/** Wait for any of the specified Thread Flags to become signaled for the current thread.
@param flags specifies the flags to wait for
@param clear whether to clear the specified flags after waiting for them. (default: true)
@return actual thread flags before clearing, which will satisfy the wait
@note You cannot call this function from ISR context.
@see Thread::flags_set
*/
uint32_t flags_wait_any(uint32_t flags, bool clear = true);
/** Wait for all of the specified Thread Flags to become signaled for the current thread.
@param flags specifies the flags to wait for
@param millisec timeout value.
@param clear whether to clear the specified flags after waiting for them. (default: true)
@return actual thread flags before clearing, which may not satisfy the wait
@note You cannot call this function from ISR context.
@see Thread::flags_set
@deprecated Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.
*/
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.")
uint32_t flags_wait_all_for(uint32_t flags, uint32_t millisec, bool clear = true);
/** Wait for all of the specified Thread Flags to become signaled for the current thread.
@param flags specifies the flags to wait for
@param rel_time timeout value.
@param clear whether to clear the specified flags after waiting for them. (default: true)
@return actual thread flags before clearing, which may not satisfy the wait
@note You cannot call this function from ISR context.
@see Thread::flags_set
*/
uint32_t flags_wait_all_for(uint32_t flags, Kernel::Clock::duration_u32 rel_time, bool clear = true);
/** Wait for all of the specified Thread Flags to become signaled for the current thread.
@param flags specifies the flags to wait for
@param millisec absolute timeout time, referenced to Kernel::get_ms_count()
@param clear whether to clear the specified flags after waiting for them. (default: true)
@return actual thread flags before clearing, which may not satisfy the wait
@note You cannot call this function from ISR context.
@note the underlying RTOS may have a limit to the maximum wait time
due to internal 32-bit computations, but this is guaranteed to work if the
wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
the wait will time out earlier than specified.
@see Thread::flags_set
@deprecated Pass a chrono time_point, not an integer millisecond count. For example use `Kernel::Clock::now() + 5s`
rather than `Kernel::get_ms_count() + 5000`.
*/
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono time_point, not an integer millisecond count. For example use `Kernel::Clock::now() + 5s` rather than `Kernel::get_ms_count() + 5000`.")
uint32_t flags_wait_all_until(uint32_t flags, uint64_t millisec, bool clear = true);
/** Wait for all of the specified Thread Flags to become signaled for the current thread.
@param flags specifies the flags to wait for
@param abs_time absolute timeout time, referenced to Kernel::Clock
@param clear whether to clear the specified flags after waiting for them. (default: true)
@return actual thread flags before clearing, which may not satisfy the wait
@note You cannot call this function from ISR context.
@note the underlying RTOS may have a limit to the maximum wait time
due to internal 32-bit computations, but this is guaranteed to work if the
wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
the wait will time out earlier than specified.
@see Thread::flags_set
*/
uint32_t flags_wait_all_until(uint32_t flags, Kernel::Clock::time_point abs_time, bool clear = true);
/** Wait for any of the specified Thread Flags to become signaled for the current thread.
@param flags specifies the flags to wait for
@param millisec timeout value.
@param clear whether to clear the specified flags after waiting for them. (default: true)
@return actual thread flags before clearing, which may not satisfy the wait
@note You cannot call this function from ISR context.
@see Thread::flags_set
@deprecated Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.
*/
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.")
uint32_t flags_wait_any_for(uint32_t flags, uint32_t millisec, bool clear = true);
/** Wait for any of the specified Thread Flags to become signaled for the current thread.
@param flags specifies the flags to wait for
@param rel_time timeout value.
@param clear whether to clear the specified flags after waiting for them. (default: true)
@return actual thread flags before clearing, which may not satisfy the wait
@note You cannot call this function from ISR context.
@see Thread::flags_set
*/
uint32_t flags_wait_any_for(uint32_t flags, Kernel::Clock::duration_u32 rel_time, bool clear = true);
/** Wait for any of the specified Thread Flags to become signaled for the current thread.
@param flags specifies the flags to wait for
@param millisec absolute timeout time, referenced to Kernel::get_ms_count()
@param clear whether to clear the specified flags after waiting for them. (default: true)
@return actual thread flags before clearing, which may not satisfy the wait
@note You cannot call this function from ISR context.
@note the underlying RTOS may have a limit to the maximum wait time
due to internal 32-bit computations, but this is guaranteed to work if the
wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
the wait will time out earlier than specified.
@see Thread::flags_set
@deprecated Pass a chrono time_point, not an integer millisecond count. For example use `Kernel::Clock::now() + 5s`
rather than `Kernel::get_ms_count() + 5000`.
*/
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono time_point, not an integer millisecond count. For example use `Kernel::Clock::now() + 5s` rather than `Kernel::get_ms_count() + 5000`.")
uint32_t flags_wait_any_until(uint32_t flags, uint64_t millisec, bool clear = true);
/** Wait for any of the specified Thread Flags to become signaled for the current thread.
@param flags specifies the flags to wait for
@param abs_time absolute timeout time, referenced to Kernel::Clock
@param clear whether to clear the specified flags after waiting for them. (default: true)
@return actual thread flags before clearing, which may not satisfy the wait
@note You cannot call this function from ISR context.
@note the underlying RTOS may have a limit to the maximum wait time
due to internal 32-bit computations, but this is guaranteed to work if the
wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
the wait will time out earlier than specified.
@see Thread::flags_set
*/
uint32_t flags_wait_any_until(uint32_t flags, Kernel::Clock::time_point abs_time, bool clear = true);
/** 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.
@deprecated Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.
*/
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.")
void sleep_for(uint32_t millisec);
/** Sleep for a specified time period:
@param rel_time 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(Kernel::Clock::duration_u32 rel_time);
/** 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 thread_sleep_until.
@deprecated Pass a chrono time_point, not an integer millisecond count. For example use
`Kernel::Clock::now() + 5s` rather than `Kernel::get_ms_count() + 5000`.
*/
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono time_point, not an integer millisecond count. For example use `Kernel::Clock::now() + 5s` rather than `Kernel::get_ms_count() + 5000`.")
void sleep_until(uint64_t millisec);
/** Sleep until a specified time in millisec
The specified time is according to Kernel::Clock.
@param abs_time absolute time
@note You cannot call this function from ISR context.
@note if abs_time is equal to or lower than Kernel::Clock::now(), this
returns immediately.
@note The equivalent functionality is accessible in C via thread_sleep_until.
*/
void sleep_until(Kernel::Clock::time_point abs_time);
/** Pass control to next equal-priority thread that is in state READY.
(Higher-priority READY threads would prevent us from running; this
will not enable lower-priority threads to run, as we remain READY).
@note You cannot call this function from ISR context.
*/
void yield();
/** Get the thread id of the current running thread.
@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 nullptr if thread has no name or in case of error.
@note You cannot call this function from ISR context.
*/
const char *get_name();
};
/** @}*/
/** @}*/
namespace internal {
/** \addtogroup rtos-internal-api */
/** @{*/
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

284
rtos/Thread.h Normal file
View File

@ -0,0 +1,284 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2019 ARM Limited
* SPDX-License-Identifier: MIT
*
* 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 THREAD_H
#define THREAD_H
#include <stdint.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-public-api */
/** @{*/
/**
* \defgroup rtos_Thread Thread class
* @{
*/
/** The Thread class allow defining, creating, and controlling thread functions in the system.
*
* Example:
* @code
* #include "mbed.h"
* #include "rtos.h"
*
* Thread thread;
* DigitalOut led1(LED1);
* volatile bool running = true;
*
* // Blink function toggles the led in a long running loop
* void blink(DigitalOut *led) {
* while (running) {
* *led = !*led;
* ThisThread::sleep_for(1000);
* }
* }
*
* // Spawns a thread to run blink for 5 seconds
* int main() {
* thread.start(callback(blink, &led1));
* ThisThread::sleep_for(5000);
* running = false;
* thread.join();
* }
* @endcode
*
* @note
* Memory considerations: The thread control structures will be created on current thread's stack, both for the mbed OS
* and underlying RTOS objects (static or dynamic RTOS memory pools are not being used).
* Additionally the stack memory for this thread will be allocated on the heap, if it wasn't supplied to the constructor.
*
* @note
* MBED_TZ_DEFAULT_ACCESS (default:0) flag can be used to change the default access of all user threads in non-secure mode.
* MBED_TZ_DEFAULT_ACCESS set to 1, means all non-secure user threads have access to call secure functions.
* MBED_TZ_DEFAULT_ACCESS set to 0, means none of the non-secure user thread have access to call secure functions,
* to give access to particular thread used overloaded constructor with `tz_module` as argument during thread creation.
*
* MBED_TZ_DEFAULT_ACCESS is target specific define, should be set in targets.json file for Cortex-M23/M33 devices.
*
* @note
* Bare metal profile: This class is not supported.
*/
class Thread : private mbed::NonCopyable<Thread> {
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: 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.
*/
Thread(osPriority priority = osPriorityNormal,
uint32_t stack_size = OS_STACK_SIZE,
unsigned char *stack_mem = nullptr, const char *name = nullptr)
{
constructor(priority, stack_size, stack_mem, name);
}
/** Allocate a new thread without starting execution
@param tz_module trustzone thread identifier (osThreadAttr_t::tz_module)
Context of RTOS threads in non-secure state must be saved when calling secure functions.
tz_module ID is used to allocate context memory for threads, and it can be safely set to zero for
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: 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 = nullptr, const char *name = nullptr)
{
constructor(tz_module, priority, stack_size, stack_mem, name);
}
/** Starts a thread executing the specified function.
@param task function to be executed by this thread.
@return status code that indicates the execution status of the function.
@note a thread can only be started once
@note You cannot call this function ISR context.
*/
osStatus start(mbed::Callback<void()> task);
/** Wait for thread to terminate
@return status code that indicates the execution status of the function.
@note You cannot call this function from ISR context.
*/
osStatus join();
/** Terminate execution of a thread and remove it from Active Threads
@return status code that indicates the execution status of the function.
@note You cannot call this function from ISR context.
*/
osStatus terminate();
/** Set priority of an active thread
@param priority new priority value for the thread function.
@return status code that indicates the execution status of the function.
@note You cannot call this function from ISR context.
*/
osStatus set_priority(osPriority priority);
/** Get priority of an active thread
@return current priority value of the thread function.
@note You cannot call this function from ISR context.
*/
osPriority get_priority() const;
/** Set the specified Thread Flags for the thread.
@param flags specifies the flags of the thread that should be set.
@return thread flags after setting or osFlagsError in case of incorrect parameters.
@note You may call this function from ISR context.
*/
uint32_t flags_set(uint32_t flags);
/** State of the Thread */
enum State {
Inactive, /**< NOT USED */
Ready, /**< Ready to run */
Running, /**< Running */
WaitingDelay, /**< Waiting for a delay to occur */
WaitingJoin, /**< Waiting for thread to join. Only happens when using RTX directly. */
WaitingThreadFlag, /**< Waiting for a thread flag to be set */
WaitingEventFlag, /**< Waiting for a event flag to be set */
WaitingMutex, /**< Waiting for a mutex event to occur */
WaitingSemaphore, /**< Waiting for a semaphore event to occur */
WaitingMemoryPool, /**< Waiting for a memory pool */
WaitingMessageGet, /**< Waiting for message to arrive */
WaitingMessagePut, /**< Waiting for message to be send */
WaitingInterval, /**< NOT USED */
WaitingOr, /**< NOT USED */
WaitingAnd, /**< NOT USED */
WaitingMailbox, /**< NOT USED (Mail is implemented as MemoryPool and Queue) */
/* Not in sync with RTX below here */
Deleted, /**< The task has been deleted or not started */
};
/** State of this Thread
@return the State of this Thread
@note You cannot call this function from ISR context.
*/
State get_state() const;
/** Get the total stack memory size for this Thread
@return the total stack memory size in bytes
@note You cannot call this function from ISR context.
*/
uint32_t stack_size() const;
/** Get the currently unused stack memory for this Thread
@return the currently unused stack memory in bytes
@note You cannot call this function from ISR context.
*/
uint32_t free_stack() const;
/** Get the currently used stack memory for this Thread
@return the currently used stack memory in bytes
@note You cannot call this function from ISR context.
*/
uint32_t used_stack() const;
/** Get the maximum stack memory usage to date for this Thread
@return the maximum stack memory usage to date in bytes
@note You cannot call this function from ISR context.
*/
uint32_t max_stack() const;
/** Get thread name
@return thread name or nullptr if the name was not set.
@note You may call this function from ISR context.
*/
const char *get_name() const;
/** Get thread id
@return thread ID for reference by other functions.
@note You may call this function from ISR context.
*/
osThreadId_t get_id() const;
/** Thread destructor
*
* @note You cannot call this function from ISR context.
*/
virtual ~Thread();
private:
// Required to share definitions without
// delegated constructors
void constructor(osPriority priority = osPriorityNormal,
uint32_t stack_size = OS_STACK_SIZE,
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 = nullptr,
const char *name = nullptr);
static void _thunk(void *thread_ptr);
mbed::Callback<void()> _task;
osThreadId_t _tid;
osThreadAttr_t _attr;
bool _dynamic_stack;
bool _finished;
Semaphore _join_sem;
mutable Mutex _mutex;
mbed_rtos_storage_thread_t _obj_mem;
};
/** @}*/
/** @}*/
}
#endif
#endif

30
rtos/mbed_rtos1_types.h Normal file
View File

@ -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

26
rtos/mbed_rtos_storage.h Normal file
View File

@ -0,0 +1,26 @@
/* 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

80
rtos/mbed_rtos_types.h Normal file
View File

@ -0,0 +1,80 @@
/* 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
/** \addtogroup rtos-public-api */
/** @{*/
/* 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_ */

48
rtos/rtos.h Normal file
View File

@ -0,0 +1,48 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2012 ARM Limited
* SPDX-License-Identifier: MIT
*
* 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 RTOS_H
#define RTOS_H
#include "rtos/mbed_rtos_storage.h"
#include "rtos/Kernel.h"
#include "rtos/Thread.h"
#include "rtos/ThisThread.h"
#include "rtos/Mutex.h"
#include "rtos/Semaphore.h"
#include "rtos/Mail.h"
#include "rtos/MemoryPool.h"
#include "rtos/Queue.h"
#include "rtos/EventFlags.h"
#include "rtos/ConditionVariable.h"
/** \defgroup rtos-public-api RTOS
* \ingroup mbed-os-public
*/
#ifndef MBED_NO_GLOBAL_USING_DIRECTIVE
using namespace rtos;
#endif
#endif

View File

@ -0,0 +1,34 @@
# Copyright (c) 2020 ARM Limited. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
target_sources(mbed-os PRIVATE
mbed_boot.c
mbed_rtos_rtx.c
mbed_rtx_handlers.c
mbed_rtx_idle.cpp
)
add_subdirectory(rtx5)
if(${MBED_TOOLCHAIN} STREQUAL "GCC_ARM")
target_sources(mbed-os
PRIVATE
TOOLCHAIN_GCC_ARM/mbed_boot_gcc_arm.c
)
elseif(${MBED_TOOLCHAIN} STREQUAL "ARM")
target_sources(mbed-os
PRIVATE
TOOLCHAIN_ARM_STD/mbed_boot_arm_std.c
)
elseif(${MBED_TOOLCHAIN} STREQUAL "IAR")
target_sources(mbed-os
PRIVATE
TOOLCHAIN_IAR/mbed_boot_iar.c
)
endif()
target_include_directories(mbed-os
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
rtx4
)

View File

@ -0,0 +1,76 @@
# SPDX-License-Identifier: Apache-2.0
function(_mbed_get_rtx_assembly TOOLCHAIN_DIR)
get_property(target_labels GLOBAL PROPERTY MBED_TARGET_LABELS)
foreach(key ${target_labels})
if(${key} STREQUAL CORTEX_A)
set(STARTUP_RTX_FILE TARGET_CORTEX_A/irq_ca.S)
elseif(${key} STREQUAL M0)
set(STARTUP_RTX_FILE TARGET_M0/irq_cm0.S)
elseif(${key} STREQUAL M0P)
set(STARTUP_RTX_FILE TARGET_M0P/irq_cm0.S)
elseif(${key} STREQUAL M23)
set(STARTUP_RTX_FILE TARGET_M23/irq_armv8mbl.S)
elseif(${key} STREQUAL M3)
set(STARTUP_RTX_FILE TARGET_M3/irq_cm3.S)
elseif(${key} STREQUAL M33)
set(STARTUP_RTX_FILE TARGET_M33/irq_armv8mbl.S)
elseif(${key} STREQUAL RTOS_M4_M7)
set(STARTUP_RTX_FILE TARGET_RTOS_M4_M7/irq_cm4f.S)
endif()
target_sources(mbed-os PRIVATE RTX/Source/${TOOLCHAIN_DIR}/${STARTUP_RTX_FILE})
endforeach()
endfunction()
function(_mbed_add_cortexa_handler_if)
get_property(target_labels GLOBAL PROPERTY MBED_TARGET_LABELS)
foreach(key ${target_labels})
if(${key} STREQUAL CORTEX_A)
target_sources(mbed-os PRIVATE RTX/Config/TARGET_CORTEX_A/handlers.c)
endif()
endforeach()
endfunction()
target_sources(mbed-os PRIVATE Include/cmsis_os2.h)
target_sources(mbed-os PRIVATE Include/os_tick.h)
# Add Cortex A handlers if needed
_mbed_add_cortexa_handler_if()
target_sources(mbed-os PRIVATE RTX/Config/RTX_Config.c)
target_sources(mbed-os PRIVATE RTX/Config/RTX_Config.h)
target_sources(mbed-os PRIVATE RTX/Include/rtx_evr.h)
target_sources(mbed-os PRIVATE RTX/Include/rtx_os.h)
if(${MBED_TOOLCHAIN} STREQUAL "GCC_ARM")
_mbed_get_rtx_assembly(TOOLCHAIN_GCC)
elseif(${MBED_TOOLCHAIN} STREQUAL "ARM")
_mbed_get_rtx_assembly(TOOLCHAIN_ARM)
elseif(${MBED_TOOLCHAIN} STREQUAL "IAR")
_mbed_get_rtx_assembly(TOOLCHAIN_IAR)
endif()
target_sources(mbed-os PRIVATE RTX/Source/rtx_core_ca.h)
target_sources(mbed-os PRIVATE RTX/Source/rtx_core_cm.h)
target_sources(mbed-os PRIVATE RTX/Source/rtx_delay.c)
target_sources(mbed-os PRIVATE RTX/Source/rtx_evflags.c)
target_sources(mbed-os PRIVATE RTX/Source/rtx_evr.c)
target_sources(mbed-os PRIVATE RTX/Source/rtx_kernel.c)
target_sources(mbed-os PRIVATE RTX/Source/rtx_lib.c)
target_sources(mbed-os PRIVATE RTX/Source/rtx_lib.h)
target_sources(mbed-os PRIVATE RTX/Source/rtx_memory.c)
target_sources(mbed-os PRIVATE RTX/Source/rtx_mempool.c)
target_sources(mbed-os PRIVATE RTX/Source/rtx_msgqueue.c)
target_sources(mbed-os PRIVATE RTX/Source/rtx_mutex.c)
target_sources(mbed-os PRIVATE RTX/Source/rtx_semaphore.c)
target_sources(mbed-os PRIVATE RTX/Source/rtx_system.c)
target_sources(mbed-os PRIVATE RTX/Source/rtx_thread.c)
target_sources(mbed-os PRIVATE RTX/Source/rtx_timer.c)
target_sources(mbed-os PRIVATE Source/os_systick.c)
target_sources(mbed-os PRIVATE Source/os_tick_ptim.c)
target_include_directories(mbed-os PUBLIC Include)
target_include_directories(mbed-os PUBLIC RTX/Include)
target_include_directories(mbed-os PUBLIC RTX/Source)
target_include_directories(mbed-os PUBLIC RTX/Config)

View File

@ -0,0 +1,4 @@
# Copyright (c) 2020 ARM Limited. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
mbed_add_cmake_directory_if_labels("TARGET")

View File

@ -0,0 +1,4 @@
# Copyright (c) 2020 ARM Limited. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
mbed_add_cmake_directory_if_labels("TARGET")

View File

@ -0,0 +1,4 @@
# Copyright (c) 2020 ARM Limited. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
mbed_add_cmake_directory_if_labels("TARGET")