Simple Reader and Writer Tasks Using Mailboxes

Here are two tasks; a writer task which generates ASCII characters one at a time and sends each one to a reader task, and a reader task which displays the received characters via the UART output. This demonstrates the basic of IPC (Inter Process Communication) using a mailbox.

 

A mailbox is a kernel construct that has a number of mail slots. When a task posts a message (which is just a “void *” pointer) to a mailbox, a mail slot is used to hold the message. When a task fetches a message, the message is copied to the fetcher’s pointer-to argument. Fetching a message removes it from the mailbox.

 

#include <ctype.h>

 

extern REXIS_MAILBOX *mbox1;

 

void writer_task(unsigned arg0)

      {

      while (1)

            {

            for (int x = 0; x < 128; x++)

                  {

                  if (isprint(x))

                        REXIS_MailboxPost(mbox1, &x);

                  REXIS_ TaskSleepMilliSecs(rand() % 1000);

                  }

            }

      }

 

void reader_task(unsigned arg0)

      {

while (1)

      {

      int *pi;

 

      REXIS_MailboxFetch(mbox1, (void **)&pi, 0);

      putchar(pi[0]);

      }

      }

 

Before these two tasks are run, mailbox mbox1 must be created. This can be done in main(), prior to calling REXIS_SysStart. It could also be created in one of the other tasks, as long as it is not referenced before it is created:

 

      mbox1 = REXIS_MailboxCreate(0);

 

The argument to REXIS_Mailbox is the number of “mail slots” If zero (0) is specified, a default value (which is 10 as of this writing) will be used instead. In this example, the writer_task loops through the values from 0 to 127, and if the value is a printable character, it drops it at the mailbox and then goes to sleep for a random number of milliseconds. The reader_task uses REXIS_MailboxFetch to fetch the message (i.e. the character), and then writes it out using putchar.

 

Here we begin to see some of the true power of an RTOS. When the reader task calls REXIS_MailboxFetch, if there is a pending message the call returns immediately with the message, and the call behaves like a function call with just some kernel transition overhead. If there is no message pending, then the reader task will block, and not use any CPU time. When the next message arrives, the REXIS kernel switches execution back to reader task at the earliest appropriate time. Using an RTOS, no explicit polling or busy waiting is needed, allowing the system to utilize the CPU time more efficiently.

 

If multiple tasks are waiting for a message to arrive at a mailbox, they are ordered by task priority, so a high priority task will receive the message before a lower priority one.