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.

Initializing a byte queue

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.

Posting to a 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.

Receiving from a byte queue

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
  }

Producer-consumer example

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);
  ⁞
}

Advanced Use

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.