#include <stdio.h>
#include <string.h>
#include "atom.h"
#include "atomqueue.h"
#include "atomtimer.h"
Data Structures | |
struct | queue_timer |
Typedefs | |
typedef struct queue_timer | QUEUE_TIMER |
Functions | |
uint8_t | atomQueueCreate (ATOM_QUEUE *qptr, uint8_t *buff_ptr, uint32_t unit_size, uint32_t max_num_msgs) |
uint8_t | atomQueueDelete (ATOM_QUEUE *qptr) |
uint8_t | atomQueueGet (ATOM_QUEUE *qptr, int32_t timeout, uint8_t *msgptr) |
uint8_t | atomQueuePut (ATOM_QUEUE *qptr, int32_t timeout, uint8_t *msgptr) |
Queue library.
This module implements a queue / message-passing library with the following features:
Usage instructions:
All queue objects must be initialised before use by calling atomQueueCreate(). Once initialised atomQueueGet() and atomQueuePut() are used to send and receive messages via the queue respectively.
Messages can be added to a queue by calling atomQueuePut(). If the queue is full the caller will block until space becomes available (by a message being removed from the queue). Optionally a non-blocking call can be made in which case the call will return with a status code indicating that the queue is full. This allows messages to be posted from interrupt handlers or threads which you do not wish to block, providing it is not fatal that the call could fail if the queue was full.
Messages can be received from the queue by calling atomQueueGet(). This will return the first message available in the queue in FIFO order. If the queue is empty then the call will block. Optionally, a non-blocking call can be made in which case the call will return with a status code indicating that the queue is full. This allows messages to be received by interrupt handlers or threads which you do not wish to block.
A queue which is no longer required can be deleted using atomQueueDelete(). This function automatically wakes up any threads which are waiting on the deleted queue.
typedef struct queue_timer QUEUE_TIMER |
uint8_t atomQueueCreate | ( | ATOM_QUEUE * | qptr, | |
uint8_t * | buff_ptr, | |||
uint32_t | unit_size, | |||
uint32_t | max_num_msgs | |||
) |
atomQueueCreate
Initialises a queue object.
Must be called before calling any other queue library routines on a queue. Objects can be deleted later using atomQueueDelete().
Does not allocate storage, the caller provides the queue object.
Callers pass in their own buffer area for storing the queue messages while in transit between threads. The provided storage must be large enough to store (unit_size
* max_num_mgs
) bytes. i.e. the storage area will be used for up to max_num_msgs
messages each of size unit_size
.
Queues use a fixed-size message.
This function can be called from interrupt context.
[in] | qptr | Pointer to queue object |
[in] | buff_ptr | Pointer to buffer storage area |
[in] | unit_size | Size in bytes of each queue message |
[in] | max_num_msgs | Maximum number of messages in the queue |
ATOM_OK | Success | |
ATOM_ERR_PARAM | Bad parameters |
References ATOM_ERR_PARAM, ATOM_OK, atom_queue::buff_ptr, atom_queue::getSuspQ, atom_queue::insert_index, atom_queue::max_num_msgs, atom_queue::num_msgs_stored, atom_queue::putSuspQ, atom_queue::remove_index, uint8_t, and atom_queue::unit_size.
uint8_t atomQueueDelete | ( | ATOM_QUEUE * | qptr | ) |
atomQueueDelete
Deletes a queue object.
Any threads currently suspended on the queue will be woken up with return status ATOM_ERR_DELETED. If called at thread context then the scheduler will be called during this function which may schedule in one of the woken threads depending on relative priorities.
This function can be called from interrupt context, but loops internally waking up all threads blocking on the queue, so the potential execution cycles cannot be determined in advance.
[in] | qptr | Pointer to queue object |
ATOM_OK | Success | |
ATOM_ERR_QUEUE | Problem putting a woken thread on the ready queue | |
ATOM_ERR_TIMER | Problem cancelling a timeout on a woken thread |
Only call the scheduler if we are in thread context, otherwise it will be called on exiting the ISR by atomIntExit().
References ATOM_ERR_DELETED, ATOM_ERR_PARAM, ATOM_ERR_QUEUE, ATOM_ERR_TIMER, ATOM_OK, atomCurrentContext(), atomSched(), atomTimerCancel(), CRITICAL_END, CRITICAL_START, CRITICAL_STORE, FALSE, atom_queue::getSuspQ, atom_queue::putSuspQ, atom_tcb::suspend_timo_cb, atom_tcb::suspend_wake_status, tcbDequeueHead(), tcbEnqueuePriority(), tcbReadyQ, TRUE, and uint8_t.
uint8_t atomQueueGet | ( | ATOM_QUEUE * | qptr, | |
int32_t | timeout, | |||
uint8_t * | msgptr | |||
) |
atomQueueGet
Attempt to retrieve a message from a queue.
Retrieves one message at a time. Messages are copied into the passed msgptr
storage area which should be large enough to contain one message of unit_size
bytes. Where multiple messages are in the queue, messages are retrieved in FIFO order.
If the queue is currently empty, the call will do one of the following depending on the timeout
value specified:
timeout
== 0 : Call will block until a message is available
timeout
> 0 : Call will block until a message or the specified timeout
timeout
== -1 : Return immediately if no message is on the queue
If a maximum timeout value is specified (timeout
> 0), and no message is present on the queue for the specified number of system ticks, the call will return with ATOM_TIMEOUT
.
This function can only be called from interrupt context if the timeout
parameter is -1 (in which case it does not block).
[in] | qptr | Pointer to queue object |
[in] | timeout | Max system ticks to block (0 = forever, -1 = no block) |
[out] | msgptr | Pointer to which the received message will be copied |
ATOM_OK | Success | |
ATOM_TIMEOUT | Queue wait timed out before being woken | |
ATOM_WOULDBLOCK | Called with timeout == -1 but queue was empty | |
ATOM_ERR_DELETED | Queue was deleted while suspended | |
ATOM_ERR_CONTEXT | Not called in thread context and attempted to block | |
ATOM_ERR_PARAM | Bad parameter | |
ATOM_ERR_QUEUE | Problem putting the thread on the suspend queue | |
ATOM_ERR_TIMER | Problem registering the timeout |
Fill out the data needed by the callback to wake us up.
Store the timer details in the TCB so that we can cancel the timer callback if the queue is put before the timeout occurs.
Current thread now blocking, schedule in a new one. We already know we are in thread context so can call the scheduler from here.
Normal atomQueuePut() wakeups will set ATOM_OK status, while timeouts will set ATOM_TIMEOUT and queue deletions will set ATOM_ERR_DELETED.
Check suspend_wake_status. If it is ATOM_OK then we were woken because a message has been put on the queue and we can now copy it out. Otherwise we were woken because we timed out waiting for a message, or the queue was deleted, so we should just quit.
The scheduler may now make a policy decision to thread switch if we are currently in thread context. If we are in interrupt context it will be handled by atomIntExit().
References ATOM_ERR_CONTEXT, ATOM_ERR_PARAM, ATOM_ERR_QUEUE, ATOM_ERR_TIMER, ATOM_OK, ATOM_WOULDBLOCK, atomCurrentContext(), atomSched(), atomTimerRegister(), atom_timer::cb_data, atom_timer::cb_func, atom_timer::cb_ticks, CRITICAL_END, CRITICAL_START, CRITICAL_STORE, FALSE, atom_queue::getSuspQ, atom_queue::num_msgs_stored, POINTER, queue_timer::queue_ptr, atom_tcb::suspend_timo_cb, atom_tcb::suspend_wake_status, atom_tcb::suspended, queue_timer::suspQ, queue_timer::tcb_ptr, tcbDequeueEntry(), tcbEnqueuePriority(), TRUE, and uint8_t.
uint8_t atomQueuePut | ( | ATOM_QUEUE * | qptr, | |
int32_t | timeout, | |||
uint8_t * | msgptr | |||
) |
atomQueuePut
Attempt to put a message onto a queue.
Sends one message at a time. Messages are copied from the passed msgptr
storage area which should contain a message of unit_size
bytes.
If the queue is currently full, the call will do one of the following depending on the timeout
value specified:
timeout
== 0 : Call will block until space is available
timeout
> 0 : Call will block until space or the specified timeout
timeout
== -1 : Return immediately if the queue is full
If a maximum timeout value is specified (timeout
> 0), and no space is available on the queue for the specified number of system ticks, the call will return with ATOM_TIMEOUT
.
This function can only be called from interrupt context if the timeout
parameter is -1 (in which case it does not block and may fail to post a message if the queue is full).
[in] | qptr | Pointer to queue object |
[in] | timeout | Max system ticks to block (0 = forever, -1 = no block) |
[out] | msgptr | Pointer from which the message should be copied out |
ATOM_OK | Success | |
ATOM_WOULDBLOCK | Called with timeout == -1 but queue was full | |
ATOM_TIMEOUT | Queue wait timed out before being woken | |
ATOM_ERR_DELETED | Queue was deleted while suspended | |
ATOM_ERR_CONTEXT | Not called in thread context and attempted to block | |
ATOM_ERR_PARAM | Bad parameter | |
ATOM_ERR_QUEUE | Problem putting the thread on the suspend queue | |
ATOM_ERR_TIMER | Problem registering the timeout |
Fill out the data needed by the callback to wake us up.
Store the timer details in the TCB so that we can cancel the timer callback if a message is removed from the queue before the timeout occurs.
Current thread now blocking, schedule in a new one. We already know we are in thread context so can call the scheduler from here.
Normal atomQueueGet() wakeups will set ATOM_OK status, while timeouts will set ATOM_TIMEOUT and queue deletions will set ATOM_ERR_DELETED.
Check suspend_wake_status. If it is ATOM_OK then we were woken because a message has been removed from the queue and we can now add ours. Otherwise we were woken because we timed out waiting for a message, or the queue was deleted, so we should just quit.
The scheduler may now make a policy decision to thread switch if we are currently in thread context. If we are in interrupt context it will be handled by atomIntExit().
References ATOM_ERR_CONTEXT, ATOM_ERR_PARAM, ATOM_ERR_QUEUE, ATOM_ERR_TIMER, ATOM_OK, ATOM_WOULDBLOCK, atomCurrentContext(), atomSched(), atomTimerRegister(), atom_timer::cb_data, atom_timer::cb_func, atom_timer::cb_ticks, CRITICAL_END, CRITICAL_START, CRITICAL_STORE, FALSE, atom_queue::max_num_msgs, atom_queue::num_msgs_stored, POINTER, atom_queue::putSuspQ, queue_timer::queue_ptr, atom_tcb::suspend_timo_cb, atom_tcb::suspend_wake_status, atom_tcb::suspended, queue_timer::suspQ, queue_timer::tcb_ptr, tcbDequeueEntry(), tcbEnqueuePriority(), TRUE, and uint8_t.