Messages are one way to exchange data between tasks. The message can contain any information: data from a USART, external sensor values, button and switch states, etc. There are two types of messages in OSA: pointer to message and simple byte message.
A pointer to message is the most universal. Through this type of message, the user can send information of any size. The task only sends a pointer to this information.
A simple byte message can accept values from 1 to 255 (0 - message absent). This type of message is implemented in OSA to reduce memory usage. A simple byte message needs 1 byte of RAM (a pointer to message needs 2 bytes for PIC10, PIC12 and PIC16 and 3 bytes for others).
The message can be in one of two states: free (or absent) and busy (or existing). If the message contains information, then it is existing, otherwise it is free.
By default the type of pointer to message is void*. The user can change this by defining OST_MSG type in OSAcfg.h.:
#define OS_MSG_TYPE const char *
In this example we tell the compiler that a pointer to message will point to data in ROM.
To use a pointer to message we must create it via the service OS_Msg_Create.
There are three services to send a message: OS_Msg_Send, OS_Msg_Send_TO and OS_Msg_Send_Now.
OS_Msg_Send first checks if the message is free. If it is busy (e.g. the previous message was not yet received by another task) then the task is put into a wait state until the message becomes free. If the message is free, then it can be sent immediately.
OS_Msg_Send_TO is the same as OS_Msg_Send, with exit if timeout expired while waiting for message to become free.
OS_Msg_Send_Now sends the message immediately, regardless of the current message state. If the message was busy before calling this service, then it will be overwritten by the new data, and the system flag OS_IsEventError will be set.
Here is a small example of using pointers to message:
OST_MSG_CB msg_cb; void Task_USARTReceive (void) { static char BUF[10]; // Buffer for received data from USART static char Message[10]; // Message body OS_Msg_Create(msg_cb); // First we create the message for (;;){ ... // Receiving USART data ... // Wait until message becomes free OS_Cond_Wait(!OS_Msg_Check(msg_cb)); // When we get here we can be sure that the previous message was accepted by another task // and the Message[] array does not contain any information. // Copy received data to message buffer memcpy(Message, BUF, 10); // and send message OS_Msg_Send(msg_cb, (OST_MSG)Message); ... } } . . . void Task_Work (void) { OST_MSG msg; for (;;) { // Waiting for message OS_Msg_Wait(msg_cb, msg); // Now msg points to array Message[] from Task_USARTReceive // After the service OS_Msg_Wait, the message msg_cb becomes free ... } }
By default, the type of a simple byte message is unsigned char. However, the user can change the type of the message by defining OST_SMSG in OSAcfg.h:
#define OS_SMSG_TYPE unsigned long // change SMSG type
By changing the type of a simple message we lose the advantage in RAM usage, but it can be useful in some cases. For example, when we use a pointer to message, we can't modify the memory where the body of the message is placed (array Message[] in previous example) until the message is accepted. When we use a simple message this restriction is removed because the body of the message is copied into the message variable.
Using simple messages is similar to using pointers to messages. Here is an example of using a simple byte message:
OST_SMSG smsg_Buttons; . . . void Task_Buttons (void) { OS_Smsg_Create(smsg_Buttons); for (;;) { . . . if (!RB0 || !RB1 || !RB2) OS_Smsg_Send(smsg_Buttons, (OST_SMSG)PORTB & 0x07); ... } } ... void Task_Work (void) { OST_SMSG smsg; for (;;) { OS_Smsg_Wait(smsg_Buttons, smsg); // Processing pressed button if (smsg & 0x01) ...; if (smsg & 0x02) ...; if (smsg & 0x04) ...; ... } }
Service | Arguments | Description | Properties |
---|---|---|---|
Creating | |||
OS_Msg_Create | (msg_cb) | Create a message control block and zero it | |
Sending | |||
OS_Msg_Send | (msg_cb, message) | Send message. If message already exists then until it becomes free | |
OS_Msg_Send_TO | (msg_cb, message, timeout) | Send message. If message already exists then wait until becomes free. Exit if timeout expired | |
OS_Msg_Send_Now | (msg_cb, message) | Send message. If message already exists then it will be overwritten | |
Checking | |||
bool OS_Msg_Check | (msg_cb) | Check if message exists | |
OS_Msg_Accept | (msg_cb, os_msg_type_var) | Accept existing message. After accepting, message is freed | |
Waiting | |||
OS_Msg_Wait | (msg_cb, os_msg_type_var) | Wait for message. After waiting, message is freed | |
OS_Msg_Wait_TO | (msg_cb, os_msg_type_var, timeout) | Wait for message. Exit if timeout expired |
Service | Arguments | Description | Properties |
---|---|---|---|
Creating | |||
OS_Smsg_Create | (smsg) | Create and zero a simple message | |
Sending | |||
OS_Smsg_Send | (smsg, smessage) | Send a simple message. If message already exists then wait until it becomes free | |
OS_Smsg_Send_TO | (smsg, smessage, timeout) | Send a simple message. If message already exists then wait until it becomes free. Exit if timeout expired | |
OS_Smsg_Send_Now | (smsg, smessage) | Send s simple message. If message already exists then it will be overwritten | |
Checking | |||
bool OS_Smsg_Check | (smsg) | Check if simple message exists | |
OS_Smsg_Accept | (smsg, os_smsg_type_var) | Accept existing simple message. After accepting, message is cleared | |
Waiting | |||
OS_Smsg_Wait | (smsg, os_smsg_type_var) | Wait for simple message. After accepting, simple message is cleared | |
OS_Smsg_Wait_TO | (smsg, os_smsg_type_var, timeout) | Wait for simple message. After accepting, simple message is cleared. Exit if timeout expired |