Skip to content

Commit

Permalink
Merge pull request #5760 from bulislaw/rtc_isr_safe_doc
Browse files Browse the repository at this point in the history
Add notes about ISR safety to RTOS doxygen
  • Loading branch information
0xc0170 committed Jan 15, 2018
2 parents 2c6403e + ec681b6 commit 940614c
Show file tree
Hide file tree
Showing 9 changed files with 184 additions and 11 deletions.
17 changes: 16 additions & 1 deletion rtos/ConditionVariable.h
Expand Up @@ -118,7 +118,10 @@ struct Waiter;
*/
class ConditionVariable : private mbed::NonCopyable<ConditionVariable> {
public:
/** Create and Initialize a ConditionVariable object */
/** Create and Initialize a ConditionVariable object
*
* @note You may call this function from ISR context.
*/
ConditionVariable(Mutex &mutex);

/** Wait for a notification
Expand All @@ -142,6 +145,8 @@ class ConditionVariable : private mbed::NonCopyable<ConditionVariable> {
*
* mutex.unlock();
* @endcode
*
* @note You cannot call this function from ISR context.
*/
void wait();

Expand Down Expand Up @@ -176,21 +181,31 @@ class ConditionVariable : private mbed::NonCopyable<ConditionVariable> {
*
* mutex.unlock();
* @endcode
*
* @note You cannot call this function from ISR context.
*/
bool wait_for(uint32_t millisec);

/** Notify one waiter on this condition variable that a condition changed.
*
* @note - The thread calling this function must be the owner of the ConditionVariable's mutex
*
* @note This function may be called from ISR context.
*/
void notify_one();

/** Notify all waiters on this condition variable that a condition changed.
*
* @note - The thread calling this function must be the owner of the ConditionVariable's mutex
*
* @note This function may be called from ISR context.
*/
void notify_all();

/** ConditionVariable destructor
*
* @note You may call this function from ISR context.
*/
~ConditionVariable();

protected:
Expand Down
21 changes: 20 additions & 1 deletion rtos/EventFlags.h
Expand Up @@ -46,29 +46,40 @@ namespace rtos {
*/
class EventFlags : private mbed::NonCopyable<EventFlags> {
public:
/** Create and Initialize a EventFlags object */
/** Create and Initialize an EventFlags object
*
* @note You cannot call this function from ISR context.
*/
EventFlags();

/** Create and Initialize a 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 specifies the flags that shall be set.
@return event flags after setting or error code if highest bit set (@a osFlagsError).
@note This function may be called from ISR context.
*/
uint32_t set(uint32_t flags);

/** Clear the specified Event Flags.
@param flags specifies the flags that shall be cleared. (default: 0x7fffffff - all flags)
@return event flags before clearing or error code if highest bit set (@a osFlagsError).
@note You may call this function from ISR context.
*/
uint32_t clear(uint32_t flags = 0x7fffffff);

/** Get the currently set Event Flags.
@return set event flags.
@note You may call this function from ISR context.
*/
uint32_t get() const;

Expand All @@ -77,6 +88,8 @@ class EventFlags : private mbed::NonCopyable<EventFlags> {
@param timeout timeout value or 0 in case of no time-out. (default: osWaitForever)
@param clear specifies wether to clear the flags after waiting for them. (default: true)
@return event flags before clearing or error code if highest bit set (@a osFlagsError).
@note You may call this function from ISR context if the timeout parameter is set to 0.
*/
uint32_t wait_all(uint32_t flags = 0, uint32_t timeout = osWaitForever, bool clear = true);

Expand All @@ -85,9 +98,15 @@ class EventFlags : private mbed::NonCopyable<EventFlags> {
@param timeout timeout value or 0 in case of no time-out. (default: osWaitForever)
@param clear specifies wether to clear the flags after waiting for them. (default: true)
@return event flags before clearing or error code if highest bit set (@a osFlagsError).
@note This function may be called from ISR context if the timeout parameter is set to 0.
*/
uint32_t wait_any(uint32_t flags = 0, uint32_t timeout = osWaitForever, bool clear = true);

/** Event flags destructor
@note You cannot call this function from ISR context.
*/
~EventFlags();

private:
Expand Down
19 changes: 18 additions & 1 deletion rtos/Mail.h
Expand Up @@ -55,12 +55,17 @@ namespace rtos {
template<typename T, uint32_t queue_sz>
class Mail : private mbed::NonCopyable<Mail<T, queue_sz> > {
public:
/** Create and Initialise Mail queue. */
/** Create and Initialize Mail queue.
*
* @note You cannot call this function from ISR context.
*/
Mail() { };

/** Check if the mail queue is empty
*
* @return True if the mail queue is empty, false if not
*
* @note You may call this function from ISR context.
*/
bool empty() const {
return _queue.empty();
Expand All @@ -69,6 +74,8 @@ class Mail : private mbed::NonCopyable<Mail<T, queue_sz> > {
/** Check if the mail queue is full
*
* @return True if the mail queue is full, false if not
*
* @note You may call this function from ISR context.
*/
bool full() const {
return _queue.full();
Expand All @@ -77,6 +84,8 @@ class Mail : private mbed::NonCopyable<Mail<T, queue_sz> > {
/** Allocate a memory block of type T
@param millisec timeout value or 0 in case of no time-out. (default: 0).
@return pointer to memory block that can be filled with mail or NULL in case error.
@note You may call this function from ISR context if the millisec parameter is set to 0.
*/
T* alloc(uint32_t millisec=0) {
return _pool.alloc();
Expand All @@ -85,6 +94,8 @@ class Mail : private mbed::NonCopyable<Mail<T, queue_sz> > {
/** Allocate a memory block of type T and set memory block to zero.
@param millisec timeout value or 0 in case of no time-out. (default: 0).
@return pointer to memory block that can be filled with mail or NULL in case error.
@note You may call this function from ISR context if the millisec parameter is set to 0.
*/
T* calloc(uint32_t millisec=0) {
return _pool.calloc();
Expand All @@ -93,6 +104,8 @@ class Mail : private mbed::NonCopyable<Mail<T, queue_sz> > {
/** 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.
@note You may call this function from ISR context.
*/
osStatus put(T *mptr) {
return _queue.put(mptr);
Expand All @@ -101,6 +114,8 @@ class Mail : private mbed::NonCopyable<Mail<T, queue_sz> > {
/** Get a mail from a queue.
@param millisec timeout value or 0 in case of no time-out. (default: osWaitForever).
@return event that contains mail information or error code.
@note You may call this function from ISR context if the millisec parameter is set to 0.
*/
osEvent get(uint32_t millisec=osWaitForever) {
osEvent evt = _queue.get(millisec);
Expand All @@ -113,6 +128,8 @@ class Mail : private mbed::NonCopyable<Mail<T, queue_sz> > {
/** 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.
@note You may call this function from ISR context.
*/
osStatus free(T *mptr) {
return _pool.free(mptr);
Expand Down
15 changes: 13 additions & 2 deletions rtos/MemoryPool.h
Expand Up @@ -50,7 +50,10 @@ 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. */
/** Create and Initialize a memory pool.
*
* @note You cannot call this function from ISR context.
*/
MemoryPool() {
memset(_pool_mem, 0, sizeof(_pool_mem));
memset(&_obj_mem, 0, sizeof(_obj_mem));
Expand All @@ -63,20 +66,27 @@ class MemoryPool : private mbed::NonCopyable<MemoryPool<T, pool_sz> > {
MBED_ASSERT(_id);
}

/** Destroy a memory pool */
/** Destroy a memory pool
*
* @note You cannot call this function from ISR context.
*/
~MemoryPool() {
osMemoryPoolDelete(_id);
}

/** Allocate a memory block of type T from a memory pool.
@return address of the allocated memory block or NULL in case of no memory available.
@note You may call this function from ISR context.
*/
T* alloc(void) {
return (T*)osMemoryPoolAlloc(_id, 0);
}

/** Allocate a memory block of type T from a memory pool and set memory block to zero.
@return address of the allocated memory block or NULL in case of no memory available.
@note You may call this function from ISR context.
*/
T* calloc(void) {
T *item = (T*)osMemoryPoolAlloc(_id, 0);
Expand All @@ -92,6 +102,7 @@ class MemoryPool : private mbed::NonCopyable<MemoryPool<T, pool_sz> > {
is NULL 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, (void*)block);
Expand Down
22 changes: 21 additions & 1 deletion rtos/Mutex.h
Expand Up @@ -40,18 +40,26 @@ namespace rtos {
/** The Mutex class is used to synchronize the execution of threads.
This is for example used to protect access to a shared resource.
@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 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 Mutex : private mbed::NonCopyable<Mutex> {
public:
/** Create and Initialize a Mutex object */
/** 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);

Expand All @@ -63,11 +71,15 @@ class Mutex : private mbed::NonCopyable<Mutex> {
@a osErrorParameter internal error.
@a osErrorResource the mutex could not be obtained when no timeout was specified.
@a osErrorISR this function cannot be called from the interrupt service routine.
@note You cannot call this function from ISR context.
*/
osStatus lock(uint32_t millisec=osWaitForever);

/** Try to lock the mutex, and return immediately
@return true if the mutex was acquired, false otherwise.
@note This function cannot be called from ISR context.
*/
bool trylock();

Expand All @@ -77,14 +89,22 @@ class Mutex : private mbed::NonCopyable<Mutex> {
@a osErrorParameter internal error.
@a osErrorResource the mutex was not locked or the current thread wasn't the owner.
@a osErrorISR this function cannot be called from the interrupt service routine.
@note This function cannot be called from ISR context.
*/
osStatus unlock();

/** Get the owner the this mutex
@return the current owner of this mutex.
@note You cannot call this function from ISR context.
*/
osThreadId get_owner();

/** Mutex destructor
*
* @note You cannot call this function from ISR context.
*/
~Mutex();

private:
Expand Down
18 changes: 16 additions & 2 deletions rtos/Queue.h
Expand Up @@ -52,7 +52,10 @@ namespace rtos {
template<typename T, uint32_t queue_sz>
class Queue : private mbed::NonCopyable<Queue<T, queue_sz> > {
public:
/** Create and initialize a message Queue. */
/** Create and initialize a message Queue.
*
* @note You cannot call this function from ISR context.
*/
Queue() {
memset(&_obj_mem, 0, sizeof(_obj_mem));
osMessageQueueAttr_t attr = { 0 };
Expand All @@ -63,14 +66,19 @@ class Queue : private mbed::NonCopyable<Queue<T, queue_sz> > {
_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;
Expand All @@ -79,6 +87,8 @@ class Queue : private mbed::NonCopyable<Queue<T, queue_sz> > {
/** 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;
Expand All @@ -93,6 +103,8 @@ class Queue : private mbed::NonCopyable<Queue<T, queue_sz> > {
@a osErrorTimeout the message could not be put into the queue in the given time.
@a osErrorResource not enough space in the queue.
@a osErrorParameter internal error or non-zero timeout specified in an ISR.
@note You may call this function from ISR context if the millisec parameter is set to 0.
*/
osStatus put(T* data, uint32_t millisec=0, uint8_t prio=0) {
return osMessageQueuePut(_id, &data, prio, millisec);
Expand All @@ -106,6 +118,8 @@ class Queue : private mbed::NonCopyable<Queue<T, queue_sz> > {
@a osOK no message is available in the queue and no timeout was specified.
@a osEventTimeout no message 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.
*/
osEvent get(uint32_t millisec=osWaitForever) {
osEvent event;
Expand Down

0 comments on commit 940614c

Please sign in to comment.