Byte queues provide byte-based buffers between tasks and interrupt service routines.
A byte queue is a structure that enables tasks to post and receive data bytes. The byte queue has a buffer, which enables a number of posts to be completed without receives occurring. The buffer keeps the posted bytes in FIFO order, so the oldest byte is received first. When the buffer isn't full, a post will put the byte at the back of the queue and the calling task continues execution. When the buffer is full, a post will block the calling task until there is room for the byte. When the buffer isn't empty, a receive will return the byte from the front of the queue and continue execution of the calling task. When the buffer is empty, a receive will block the calling task until a byte is posted.
You allocate a byte queue by declaring it as a C variable:
CTL_BYTE_QUEUE_t m1;
A byte queue is initialized using ctl_byte_queue_init:
unsigned char queue[20]; ⁞ ctl_byte_queue_init(&m1, queue, 20);
This example uses an 20-element array for the byte queue.
You can post a byte to a byte queue with an optional timeout using ctl_byte_queue_post:
ctl_byte_queue_post(&m1, 45, CTL_TIMEOUT_NONE, 0);
This example posts the byte 45 to the byte queue.
You can post multiple bytes to a byte queue with an optional timeout using ctl_byte_queue_post_multi:
if (ctl_byte_queue_post(&m1, 4, bytes, CTL_TIMEOUT_ABSOLUTE, ctl_get_current_time()+1000) != 4) { // timeout occurred }
This example uses a timeout and tests the return result to see if the timeout occurred.
If you want to post a byte and you don't want to block access (e.g., from an interrupt service routine), you can use ctl_byte_queue_post_nb (or ctl_byte_queue_post_multi_nb to post multiple bytes).
if (ctl_byte_queue_post_nb(&m1, 45) == 0) { // queue is full }
This example tests the return result to see if the post failed.
You can receive a byte with an optional timeout by using ctl_byte_queue_receive:
unsigned char msg; ctl_byte_queue_receive(&m1, &msg, CTL_TIMEOUT_NONE, 0);
This example receives the oldest byte in the byte queue.
You can receive multiple bytes from a byte queue with an optional timeout using ctl_byte_queue_receive_multi:
if (ctl_byte_queue_receive_multi(&m1, 4, bytes, CTL_TIMEOUT_DELAY, 1000) != 4) { // timeout occurred }
This example tests the return result to see if the timeout occurred.
If you want to receive a byte and you don't want to block (e.g., from an interrupt service routine), you can use ctl_byte_queue_receive_nb (or ctl_byte_queue_receive_multi_nb to receive multiple bytes).
if (ctl_byte_queue_receive_nb(&m1, &msg) == 0) { // queue is empty }
The following example uses a byte queue to implement the producer-consumer problem.
CTL_BYTE_QUEUE_t m1; void *queue[20]; void task1(void) { ⁞ ctl_byte_queue_post(&m1, (void *)i, CTL_TIMEOUT_NONE, 0); ⁞ } void task2(void) { void *msg; ⁞ ctl_byte_queue_receive(&m1, &msg, CTL_TIMEOUT_NONE, 0); ⁞ } int main(void) { ⁞ ctl_byte_queue_init(&m1, queue, 20); ⁞ }
You can associate event flags with a byte queue that are set (and similarly cleared) when the byte queue is not full and not empty using the function ctl_byte_queue_setup_events.
For example, you can use this to wait for messages to arrive from multiple byte (or message) queues.
CTL_BYTE_QUEUE_t m1, m2; CTL_EVENT_SET_t e; ctl_byte_queue_setup_events(&m1, &e, 1<<0, 1<<1); ctl_byte_queue_setup_events(&m2, &e, 1<<2, 1<<3); ⁞ switch (ctl_events_wait(CTL_EVENT_WAIT_ANY_EVENTS, &e, (1<<0) | (1<<2), CTL_TIMEOUT_NONE, 0)) { case 1<<0: ctl_byte_queue_receive(&m1, … break; case 1<<2: ctl_byte_queue_receive(&m2, … break; }
This example sets up and waits for the not-empty event of byte queue m1 and the not-empty event of byte queue m2. When the wait completes, it reads from the appropriate byte queue. Note that you must not use a ‘with auto clear’ event wait type when waiting on events associated with a byte queue.
You can use ctl_byte_queue_num_used to test how many bytes are in a byte queue and ctl_byte_queue_num_free to learn how many free bytes are in a byte queue. With these functions, you can poll the byte queue:
while (ctl_byte_queue_num_free(&m1) < 10) ctl_task_timeout_wait(ctl_get_current_time()+1000); ctl_byte_queue_post_multi(&m1, 10, …
This example waits for 10 elements to be free before it posts 10 elements.