![]() |
Synergy Software Package User's Manual
|
The Messaging Framework implements a lightweight and event-driven API for passing messages between threads. The Messaging Framework module allows applications to communicate messages between two or more threads. The framework uses the ThreadX message-queue primitive for message passing and provides more benefits than the ThreadX RTOS message-queue services alone. The Messaging Framework API is purely a software API and does not access any hardware peripherals. The Messaging Framework callback is used to allow an event-producer thread and a message-subscriber thread to handshake after the message passing is done.
The Messaging tab is used to either create custom event classes, events and subscribers for the Messaging Framework module or to customize preconfigured events such as the touch event used by the Touch Panel Framework module.
The Messaging Framework module supports the following functions:
The Messaging Framework module defines APIs for opening and closing the framework, acquiring and releasing buffers, and posting messages to subscribers. A complete list of the available APIs, an example API call and a short description of each can be found in the following table. A table of status return values follows the API summary table.
Messaging Framework Module API Summary
| Function Name | Example API Call and Description |
|---|---|
| open | g_sf_message.p_api->open (g_sf_message.p_ctrl, g_sf_message.p_cfg);Initialize message framework. Initiate the messaging framework control block, configure the work memory corresponding to the configuration parameters. |
| close | g_sf_message.p_api->close (g_sf_message.p_ctrl);Finalize message framework. |
| bufferAcquire | g_sf_message.p_api->bufferAcquire ( g_sf_message.p_ctrl, &p_buffer, &acquire_cfg, wait_option);Acquire buffer for message passing from the block. |
| bufferRelease | g_sf_message.p_api->bufferRelease ( g_sf_message.p_ctrl, &p_buffer, option);Release buffer obtained from SF_MESSAGE_BufferAcquire. |
| post | g_sf_message.p_api->post (g_sf_message.p_ctrl, (sf_message_header_t *) p_payload, &post_cfg, &err_post, wait_option);Post message to the subscribers. |
| pend | g_sf_message.p_api->pend (g_sf_message.p_ctrl, &my_queue, (sf_message_header_t **)&p_buffer, &p_header, wait_option);Pend message. |
| versionGet | g_sf_message.p_api->versionGet (&version);Retrieve the API version with the version pointer. |
Status Return Values
| Name | Description |
|---|---|
| SSP_SUCCESS | API call successful. |
| SSP_ERR_ASSERTION | Required pointer is NULL. |
| SSP_ERR_BUFFER_RELEASED | The buffer is released. |
| SSP_ERR_ILLEGAL_SUBSCRIBER_LISTS | Message subscriber lists is illegal. |
| SSP_ERR_IN_USE | The messaging framework is in use. |
| SSP_ERR_INTERNAL | OS service call fails. |
| SSP_ERR_INVALID_MSG_BUFFER_SIZE | Message buffer size is invalid. |
| SSP_ERR_INVALID_WORKBUFFER_SIZE | Invalid work buffer size. |
| SSP_ERR_MESSAGE_QUEUE_EMPTY | Queue is empty. (Timeout occurs before receiving a message if timeout option is specified.) |
| SSP_ERR_MESSAGE_QUEUE_FULL | Queue is full. (Timeout occurs before sending a message if timeout option is specified.) |
| SSP_ERR_NO_MORE_BUFFER | No more buffer found in the memory block pool. |
| SSP_ERR_NO_SUBSCRIBER_FOUND | No subscriber found. |
| SSP_ERR_NOT_OPEN | Message framework module has yet to be opened. |
| SSP_ERR_TIMEOUT | OS service call returns timeout. |
| SSP_ERR_TOO_MANY_BUFFERS | Too many message buffers. |
The following figure shows the overview of the messaging data flow between a message producer thread and subscriber thread(s) in the system making use of the Messaging Framework module.
The following is a description for each stage of the message passing procedure:
Note: A thread in the system has been called using the sf_message_api_t::open API and message subscriber threads have called the sf_message_api_t::pend API to pend on a message for the event class.
Messaging Framework Module Message Producer and Subscribers
The Message Framework module is an inter-thread messaging system based on the publish/subscribe model. A message is posted with an event class code by an event producer thread. The message subscriber threads can check for pending messages which subscribe to the event class. Subscribers are registered in the subscriber list, which is referred to by the framework. The subscriber list allows the framework to deliver a message to multiple subscribers.
Every thread which joins the Messaging Framework module system network can send a message, and all threads in the network can listen to the message.
Messaging Framework Module Events, Subscribers, and Messages
Messaging Framework Module Event Class Code
The event class code is the most important definition for the Messaging module. The Messaging module uses the event class code as the mechanism to connect a message producer with subscribers; the event class code is the class definition of the events which occur in the application. The classification of the event class relies on the user definition, but it is intended to be the group name of the particular events which can occur in a subsystem.
For example, you can use the 'Audio Playback' event class, which is part of the Audio Playback Framework module. The 'Audio Playback' Event Class is automatically loaded into the event classes window. This window is available on the Messaging tab in the Project Configurator when you add the Audio Playback Framework to your Synergy project.
The event class code is defined in the sf_message_event_class_t enumeration and has a prefix SF_MESSAGE_EVENT_CLASS_XXX. Since the definition of the event class code is different for each system, the framework does not provide a concrete event class code but instead provides a set of event class codes as examples. (See the Configuring the Messaging Framework Module section.) The maximum number for the event class is 255.
An application can use the event class code as follows:
The following figure shows how you can configure an event class using the ISDE:
Messaging Framework Module Event Class Instance Number
The event class instance number is used when an application needs to have different event class instances. For example, the audio streaming event class can have instance N which represents the streaming channel N. Message subscribers can receive a message only if the event class instance number in the message common header matches to the number it owns.
In other words, messages for which the event class instance number is out of range for the subscriber are filtered out and not delivered to the subscriber even though it is the event class subscriber. The maximum for the event class instance number is 255.
An application can use the event class instance number as follows:
Messaging Framework Module Event Code
The event code includes the details of the event definition. For instance, the event codes for the audio playback event class are "playback start" and "playback stop." Another example is 'set' or 'get' for the 'time' Event Class. The event code is enumerated in the sf_message_event_t and has a prefix SF_MESSAGE_EVENT_XXX. The definition of the event code relies on the user code as well as the event class code. The framework provides some code as examples. See Configuring the event class code and event code for configuring the event code. The maximum for the event class instance number is 65535.
An application can use the event code as follows:
The message producer thread sets the event code to the event_b.code bit fields in the sf_message_header_t type common message header before posting the message.
The message subscriber thread performs an action corresponding to the event code which is set to the message header after receiving the message.
Messaging Framework Module Subscriber List
The subscriber list is used for message delivery and is looked up by the framework.
The framework starts to look up the message queues of each subscriber thread from the subscriber group listed in the head of the pointer array to the sf_message_subscriber_list_t instance. The important point of the subscriber list is that it is grouped by event class code (event_class).
When the framework looks up the subscriber list in the post API function at runtime, it compares the Event Class code in the message header (sf_message_header_t::event_b.class), which is included in the message payload data, with the one in the subscriber group instance (event_class). If there is a match, the Framework goes to the next level to get the message queue instance (sf_message_subscriber_t::queue) until the iterations reach number_of_nodes). If there is no match, the framework looks up the next subscriber group and continues until encountering a NULL in the pointer array to the sf_message_subscriber_list_t instance.
In the look-up procedure, the subscriber group listed at the head of the Subscriber List gets the highest throughput for messaging, but lower subscriber groups encounter a penalty and get lower throughput for messaging.
The subscriber list is the look-up table for all message subscribers. The subscriber list is configured at compile time. It is statically mapped to the memory and looked up by the framework when the post API function is called. The subscriber list allows the framework to determine message queues to deliver a message to. The subscriber list consists of two structures sf_message_subscriber_list_t and sf_message_subscriber_t as shown in the following figure:
In the ISDE, you can configure a subscriber grouped by the event class for the thread you named in the Threads tab. In the following example, the thread is named "My Thread" in the Threads tab. The start and end values reflect the event class instance numbers this thread accepts.
Messaging Framework Module Message Payload
The message payload is structured data used by the message producer and the message subscribers to communicate with each other. The message payload contains event class and event code in the common header (sf_message_header_ttype data, see event class and event code) so that a message producer can post a message to the subscribers to inform the subscribers which event happened.
You must define a system specific message payload structure except for modules for which the SSP provides predefined structures such as the Audio Playback Framework module. The message payload can contain additional data, which are required for the event processing, in addition to the common header.
Messaging Framework Module SSP Predefined Payload
The SSP contains the predefined message payload structure sf_audio_playback_data_t type for the Audio Playback Framework module.
The Audio Playback Framework module uses the Messaging Framework internally and defines a suitable message payload structures. An application thread that posts audio event messages to the Audio Playback Framework module can use sf_audio_playback_api.h.
Messaging Framework Module User-Defined Payload
You must define a message payload structure for each event class code; exceptions include the SSP predefined payloads described previously or payloads that require only the common header. To create a new message payload structure, add a common message header (sf_message_header_t type structure) at the head in the user-specific message payload structure. The size of the header is 4 bytes.
The buffer size limit is critical; oversized data written beyond the buffer may destroy data in the block memory pool, which is required by ThreadX kernel. Violating the size limit results in a hard fault exception. The buffer size can be configured insf_message_ctrl_t::buffer_size.
Messaging Framework and OS Message Queue Service
The Messaging Framework module uses the ThreadX primitive-message queue and kernel services and supports some enhancement over the ThreadX RTOS features. For this reason, the Messaging Framework module does not work exactly the same as the ThreadX message-queue service. However, a messaging system with the Messaging Framework module can work simultaneously with the ThreadX message queue services in an application if the two messaging systems are separated.
API Calls Contexts
Estimating the Number of Buffers
The number of buffers available to be allocated in the work memory should be estimated properly when designing the messaging system. The number of buffers is estimated as follows:
where:
The maximum number possible for buffers allocated at the same time equals the total amount of depth of message queues in the system. Ideally, the number of buffers for a robust system should be the sum of the depths of the message queues in the system.
Message Queue Size and Depth Setting
The Messaging Framework module needs a 4-byte memory block on the message queue as it delivers the pointer to the buffer which contains a message payload. For this reason, the size of the message queue is fixed to 4 bytes.
The depth of the message queue is arbitrary, but it should accommodate the number of queued messages at runtime. As a guideline, estimate the value as follows:
where:
This section describes how to include the Messaging Framework Module in an application using the SSP configurator.
To add the Messaging Framework to an application, simply add it to a thread using the stacks selection sequence given in the following table. (The default name for the Messaging Framework is g_sf_message0. This name can be changed in the associated Properties window.)
Messaging Framework Module Selection Sequence
| Resource | ISDE Tab | Stacks Selection Sequence |
|---|---|---|
| g_sf_message0 Messaging Framework on sf_message | Threads | New Stack> Framework> Services> Messaging Framework on sf_message |
When the Messaging Framework on sf_message is added to the thread stack as shown in the following figure, the configurator automatically adds any needed lower‑level modules. Any modules needing additional configuration information have the box text highlighted in Red. Modules with a Gray band are individual modules that stand alone. Modules with a Blue band are shared or common; they need only be added once and can be used by multiple stacks. Modules with a Pink band can require the selection of lower-level modules; these are either optional or recommended. (This is indicated in the block with the inclusion of this text.) If the addition of lower-level modules is required, the module description include Add in the text. Clicking on any Pink banded modules brings up the New icon and displays possible choices.
Note: While using sf_message framework for communication between the multiple threads having different priorities,the priority of the thread in which sf_message stack is added should be kept high.
The Messaging Framework Module must be configured by the user for the desired operation. The available configuration settings and defaults for all the user-accessible properties are given in the properties tab within the SSP configurator and are shown in the following tables for easy reference. Only properties that can be changed without causing conflicts are available for modification. Other properties are locked and not available for changes and are identified with a lock icon for the locked property in the Properties window in the ISDE. This approach simplifies the configuration process and makes it much less error-prone than previous manual approaches to configuration. The available configuration settings and defaults for all the user-accessible properties are given in the Properties tab within the SSP Configurator and are shown in the following tables for easy reference.
Configuration Settings for the Messaging Framework Module on sf_message
| ISDE Property | Value | Description |
|---|---|---|
| Parameter Checking | BSP, Enabled, Disabled Default: BSP | Enables or disables the parameter checking. |
| Message Queue Depth (Total number of messages to be enqueued in a Message Queue) | 16 | Specify the size of Thread X Message Queue in bytes for Message Subscribers. This value is applied to all the Message Queues. |
| Name | g_sf_message0 | The name of Messaging Framework module control block instance. |
| Work memory size in bytes | 2048 | Specify the work memory size in bytes. Choosing a small number results in a small number of buffers which can be allocated at the same time (You can confirm the total buffer number on: sf_message_ctrl_t::number_of_buffers). If the value is smaller than the peak number of messages to be posted at the same time, the Framework has a buffer allocation failure affecting system performance. |
| Pointer to subscriber list array | p_subscriber_lists | Specify the name of pointer to the Subscriber List array. |
| name of the block pool internally used in the messaging framework | sf_msg_blk_pool | The name of the memory block memory the Framework creates in the control block. This parameter might be useful for debugging purpose but NULL can be specified for saving memory. |
| Name of generated initialization function | sf_message_init0 | Name of generated initialization function. |
| Auto Initialization | Enable, Disable Default: Enable | Auto initialization selection. |
The messaging configurator automatically creates the message queue for the subscribers.
To use the Messaging Framework with your own event class, use the Threads tab and the Messaging tab of the project configurator in the ISDE.
In the Threads tab, do the following:
Enter the name of the event class for your thread to subscribe to in the New Event Class dialog box.
Your custom event class code and event code are stored in a file named sf_message_port.h. The audio playback and the touch event classes are two predefined event classes in the SSP. The Touch Event Class only uses the new data event, SF_MESSAGE_EVENT_NEW_DATA.
In the Messaging tab (see also Subscriber List), do the following:
You can define your own message payload structure. Every user-defined message structure must include the sf_message_header_t type structure as one of the members, but the other members are entirely user-definable. The Messaging Framework does not care where the message payload structures are defined. You can include the file which defines your own message payload structure in the source file for your message producer and subscriber threads.
Configure the sf_message_cfg_t type configuration parameters to match your system. You can generate code for the configuration structure through the Synergy Configuration tool. Add a Messaging Framework component to the thread stacks in the Threads tab and modify the properties for the Messaging Framework module in the Properties window. When you press the Generate Project Content button, the code for the Messaging Framework module is generated on the thread code.
Before posting a message, an event producer thread must acquire a buffer for the message from the Messaging Framework module. An event producer thread can acquire the buffer by calling sf_message_api_t::bufferAcquire.
When the API function returns SSP_SUCCESS, the buffer with message buffer size in bytes configured on Synergy Configuration tool is allocated in the memory pool managed by the Messaging Framework. The maximum number allowed to be allocated depends on the configuration Work memory size in bytes specified on the Synergy Configuration tool. For the estimation of the maximum number, see Estimating the Number of Buffers.
The sf_message_api_t::bufferAcquire API has several options to change the message passing behavior:
tx_block_allocate() description for the ThreadX service call in the ThreadX User Guide.After message subscriber threads receive a message posted by an event producer, the message subscriber threads must release the buffer to the framework. Buffer releasing is performed by calling sf_message_api_t::bufferRelease. Since the API function can be called multiple times if there are multiple event subscribers in the system, the actual buffer release is performed only by the last message subscriber thread in the event subscribers. For instance, if there were three subscribers in the subscriber group for the event class, the first and second thread which call sf_message_api_t::bufferRelease do not release the buffer. Only the third thread releases the buffer. Note, if the buffer keep option is specified by sf_message_api_t::bufferAcquire, the buffer is never being released except when option SF_MESSAGE_RELEASE_OPTION_FORCED_RELEASE is passed to the API function argument option. (Also see Messaging Framework callbacks for sf_message_api_t::bufferRelease API function usage.)
The API is also used for invoking a user-callback function to create a handshake between an event producer thread and a message subscriber thread.
Posting a message
sf_message_header_t::event_b.class_code in the payload structure.sf_message_header_t::event_b.code in the payload structure. It is not mandatory to specify this but necessary in most cases.sf_message_header_t::event_b.class_instance. Specify a number from 0 to 255 if your system has multiple instances for an event class. Specify 0 if your system simply uses single event class instance.post API. Note that the pointer to the buffer needs to be casted with sf_message_header_t * type when given to the API. The message will be delivered to the message subscribers which are registered in the message subscriber list. The post API has several options to change the message passing behavior.Checking for a Pending Message
pend. In general use, the second API argument specifies the pointer to a message queue, which you configured for the message subscriber thread in the Thread Subscribers pane in the Messaging tab, but you can specify the other message queues instead if required.pend.sf_message_header_t::event_b.code and the user defined arbitrary data in the message.
Note that pend has the wait_option to change the behavior of the API function:
The fourth argument of pend is the wait time option, which is only valid if the message queue of the message subscriber thread is empty. Any arbitrary ThreadX tick count, TX_WAIT_FOREVER, and TX_NO_WAIT can be set to this option. For details, see tx_queue_send()ThreadX service call in the ThreadX User Guide.
The Messaging Framework module does not use any interrupts.
The steps in using the Messaging Framework on sf_message module in a typical application are:
Once configuration is complete, the module's APIs can be used in the target application as follows:
These common steps are illustrated in a typical operational flow diagram in the following figure: