element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Personal Blogs
  • Community Hub
  • More
Personal Blogs
Legacy Personal Blogs Switch from TI-RTOS to SimpleLink POSIX: From MailBox to Message Queue
  • Blog
  • Documents
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: Jan Cumps
  • Date Created: 12 May 2018 3:06 PM Date Created
  • Views 1938 views
  • Likes 6 likes
  • Comments 3 comments
  • firmware
  • mailbox
  • msp432
  • message_queue
  • ti-rtos
  • launchpad
  • code_composer_studio
  • posix
Related
Recommended

Switch from TI-RTOS to SimpleLink POSIX: From MailBox to Message Queue

Jan Cumps
Jan Cumps
12 May 2018

A real world migration from TI-RTOS to the POSIX API of TI SimpleLink.

Texas Instruments migrated from the proprietary TI-RTOS to the open POSIX API.

I'm migrating a project that extensively used the TI paradigms to that POSIX API. You're my witness.

image

photo courtesy IKEA of Sweden: KVISSLE Letter tray, white

The blog assumes that you are a TI-RTOS user and want to adapt to the new ways of working.

 

Hardcore POSIX again. Moving from TI-RTOS MailBox API to POSIX message queues. Again, not too complex. The changes to the code are small.

As always, the ideas are not my own. This time I used a Stack Overflow question as guideline: https://stackoverflow.com/questions/3056307/how-do-i-use-mqueue-in-a-c-program-on-a-linux-based-system.

 

Message Queue

 

The use of a POSIX message queue is virtually identical to a TI-RTOS MailBox.

You have a task that puts info on the message queue. In our case, that is a SCPI command that tells our Programmable Electronic Load to enable or disable its input.

There's also a task that listens to the message queue and is woken up by the RTOS when a message is available on the mailbox. In our case the task that guards the Input Enable functionality.

If nothing is posted on that queue, the message is inactive and takes very little resources. Only when the SCPI command puts a message on the queue, the task gets processor time to consume the message and go back to sleep.

 

In the spirit of this blog series, I don't show the original TI-RTOS code. You can find it back by surfing to github:

https://raw.githubusercontent.com/jancumps/msp432/6ce469210adab5464292cbee4c09da81912f05f5/MSP432_SCPI_ElectronicLoad/el…

https://raw.githubusercontent.com/jancumps/msp432/f02395db32b17a1d3165f09d9ee58fa7c9c15b81/MSP432_SCPI_ElectronicLoad/dac_impl/dac_impl.c

 

Let's first look at the consumer side - the task that sleeps unless there's a message arriving. The first part of that task initialises the queue in read mode. The while() loop sleeps and reacts on messages.

#include <mqueue.h>

 

#include 

    mqd_t mq;
    struct mq_attr attr;

    attr.mq_flags = 0;
    attr.mq_maxmsg = 1;
    attr.mq_msgsize = MSGINPUTENABLE_SIZE;
    attr.mq_curmsgs = 0;
    mq = mq_open(QUEUE_NAME_INPUTENABLE, O_CREAT | O_RDONLY, 0644, &attr);

    while (1) {
        ssize_t bytes_read;
        bytes_read = mq_receive(mq, (char *)&d_msg, MSGINPUTENABLE_SIZE, NULL);

        /* wait for mailbox to be posted by writer() */
        if (bytes_read) {
            d_iotxBuffer[1] = d_msg.value ? 0x3F : 0xFF; // bit 7 low is output enable.
            if (! I2C_transfer(i2c_implGetHandle(), &d_ioi2cTransaction)) {
            } else {
                bInputEnable_State = d_msg.value;
            }
        }
    }
}

 

The sender side is also straightforward. We post a message when we want to enable or disable our instrument's input.

 

#include 

void eloadInputEnable(bool bEnable) {
    MsgInputEnable pMsg;

    // value has to be validated before it arrives here. We assume it's valid
    pMsg.value = bEnable;
    /* enqueue message */
    mqd_t mq;
    mq = mq_open(QUEUE_NAME_INPUTENABLE, O_WRONLY);
    mq_send(mq, (char *)&pMsg, MSGINPUTENABLE_SIZE, 0);
}

 

In this case, we open the queue for writing. I don't close the queue - not sure if that's correct or if I'm leaking resources. Shout out in the comments if this is wrong.

To understand the code a little better, here's the declaration of the message structure:

 

#define QUEUE_NAME_INPUTENABLE "/inputenable_queue"

typedef struct MsgInputEnable {
     bool value;
} MsgInputEnable;

// for TI-RTOS message size, use the structure size:
#define MSGINPUTENABLE_SIZE (sizeof(MsgInputEnable))

 

The whole setup isn't very different from what's happening in TI-RTOS. And the functionality is identical.

Very little resources are necessary to support the mechanism. No loops are polling for input. The  microcontroller time is either spent on another task or the processor goes into a well deserved sleep.

 

Related Blog
Switch from TI-RTOS to SimpleLink POSIX: Threads and Semaphores
Switch from TI-RTOS to SimpleLink POSIX: EEPROM API

Switch from TI-RTOS to SimpleLink POSIX: From MailBox to Message Queue

Switch from TI-RTOS to SimpleLink POSIX: LCD Display Driver
Switch from TI-RTOS to SimpleLink POSIX: Sleep when Idle
  • Sign in to reply

Top Comments

  • gecoz
    gecoz over 7 years ago +2
    Hi Jan, I believe the POSIX queue is ultimately implemented as a file on the system (making it persistent to reboot). Just like files, it is managed using descriptors, which is a finite resource of the…
  • Jan Cumps
    Jan Cumps over 7 years ago in reply to gecoz +2
    The sender is long living - in fact as long as the device is turned on. It's not a daemon (not running linux but an RTOS). I'm planning to run a test bed that calls the sender many times and see if I can…
  • gecoz
    gecoz over 7 years ago in reply to Jan Cumps +1
    In addition to your test, it might be useful to inspect the queue descriptor returned by the mq_open() call, to try to understand if such descriptor is a sort of "singleton" instance created by the POSIX…
  • gecoz
    gecoz over 7 years ago in reply to Jan Cumps

    In addition to your test, it might be useful to inspect the queue descriptor returned by the mq_open() call, to try to understand if such descriptor is a sort of "singleton" instance created by the POSIX layer.

     

    Judging by the behaviour of your application when you tried closing the descriptor, and knowing the queue underlying implementation is a TI-RTOS MailBox, it could be possible that the MailBox objects mapping the queue is created the first time the mq_open() is invoked, and its handle returned within the mqd_t descriptor. Any subsequent call to mq_open() would not create the MailBox object, but simply use the handle of the one previously created. The MailBox object would then be destroyed by calling  mq_close() (the MailBox API's do not have an equivalent for the open and close functions, only create and delete).

     

    If that is the case, there wouldn't be any leakage caused by missing the mq_close() call.

     

    Looking forward to reading about your test results.

     

    Fabio

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps over 7 years ago in reply to gecoz

    The sender is long living - in fact as long as the device is turned on. It's not a daemon (not running linux but an RTOS).

    I'm planning to run a test bed that calls the sender many times and see if I can find issues. I've tried closing the queue and also opening it once by the writing part at the start of the process but that leaded to invalid queues.

     

    On a microcontroller they aren't defined as files. There are no file systems. In my case, the queues are implemented on TI-RTOS MailBox .

    • Cancel
    • Vote Up +2 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • gecoz
    gecoz over 7 years ago

    Hi Jan,

     

    I believe the POSIX queue is ultimately implemented as a file on the system (making it persistent to reboot). Just like files, it is managed using descriptors, which is a finite resource of the system.

    The mq_open() call associates a descriptor to the queue, and normally I would expect the caller to release the descriptor once finished using it.

     

    ...In this case, we open the queue for writing. I don't close the queue - not sure if that's correct or if I'm leaking resources...

     

    Now, if the sender side is implemented as a short lived process, it is probably OK to omit the call to mq_close(), as all the resources used by a process are automatically released upon process' termination.

     

    But if your sender is part of a long lived process (i.e. a daemon), and your function is going to be invoked multiple times, then it is advisable to add a call to mq_close() before exiting the function.

     

    Fabio

    • Cancel
    • Vote Up +2 Vote Down
    • Sign in to reply
    • More
    • Cancel
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube