====== OSA : Messages ======
===== Intro =====
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**.
~~UP~~
===== Pointer to message =====
By default the type of pointer to message is //void*//. The user can change this by defining ##[[en:osa:ref:description:data_types#OST_MSG|OST_MSG]]## type in ##[[en:osa:ref:appendix:configuration|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 ##[[en:osa:ref:allservices:OS_Msg_Create|OS_Msg_Create]]##.
There are three services to send a message: ##[[en:osa:ref:allservices:OS_Msg_Send|OS_Msg_Send]]##, ##[[en:osa:ref:allservices:OS_Msg_Send_TO|OS_Msg_Send_TO]]## and ##[[en:osa:ref:allservices:OS_Msg_Send_Now|OS_Msg_Send_Now]]##.
##[[en:osa:ref:allservices:OS_Msg_Send|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.
##[[en:osa:ref:allservices:OS_Msg_Send_TO|OS_Msg_Send_TO]]## is the same as ##[[en:osa:ref:allservices:OS_Msg_Send|OS_Msg_Send]]##, with exit if timeout expired while waiting for message to become free.
##[[en:osa:ref:allservices:OS_Msg_Send_Now|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 ##[[en:osa:ref:allservices:OS_IsEventError|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
...
}
}
~~UP~~
===== Simple byte messages =====
By default, the type of a simple byte message is //unsigned char//. However, the user can change the type of the message by defining ##[[en:osa:ref:description:data_types#OST_SMSG|OST_SMSG]]## in ##[[en:osa:ref:appendix:configuration|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.
You cannot use structures, arrays and unions as the type of simple messages. Only enumerable types can be used: char, int, long, bit, bool, float and double.
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) ...;
...
}
}
~~UP~~
===== Services =====
==== Pointers to messages ====
^ Service ^ Arguments ^ Description ^ Properties ^
| **Creating** ||||
| ##[[en:osa:ref:allservices:OS_Msg_Create|OS_Msg_Create]]## | ''(msg_cb)'' | Create a message control block and zero it | {{osa:ref:attr_call_not_int.png|Not allowed in interrupt}} |
| **Sending** ||||
| ##[[en:osa:ref:allservices:OS_Msg_Send|OS_Msg_Send]]## | ''(msg_cb, message)'' | Send message. If message already exists then until it becomes free | {{osa:ref:attr_call_task.png|Allowed only in task}}{{osa:ref:attr_call_ct_sw.png|Switches context}} |
| ##[[en:osa:ref:allservices:OS_Msg_Send_TO|OS_Msg_Send_TO]]## | ''(msg_cb, message, timeout)'' | Send message. If message already exists then wait until becomes free. Exit if timeout expired | {{osa:ref:attr_call_task.png|Allowed only in task}}{{osa:ref:attr_call_ct_sw.png|Switches context}}{{osa:ref:attr_call_to.png|Service uses system timer}} |
| ##[[en:osa:ref:allservices:OS_Msg_Send_Now|OS_Msg_Send_Now]]## | ''(msg_cb, message)'' | Send message. If message already exists then it will be overwritten | {{osa:ref:attr_call_can_int.png|Has alternate service for work in ISR (suffix "_I")}} |
| **Checking** ||||
| ''bool ''\\ ##[[en:osa:ref:allservices:OS_Msg_Check|OS_Msg_Check]]## | ''(msg_cb)'' | Check if message exists | {{osa:ref:attr_call_can_int.png|Has alternate service for work in ISR (suffix "_I")}} |
| ##[[en:osa:ref:allservices:OS_Msg_Accept|OS_Msg_Accept]]## | ''(msg_cb, os_msg_type_var)'' | Accept existing message. After accepting, message is freed | {{osa:ref:attr_call_can_int.png|Has alternate service for work in ISR (suffix "_I")}} |
| **Waiting** ||||
| ##[[en:osa:ref:allservices:OS_Msg_Wait|OS_Msg_Wait]]## | ''(msg_cb, os_msg_type_var)'' | Wait for message. After waiting, message is freed | {{osa:ref:attr_call_task.png|Allowed only in task}}{{osa:ref:attr_call_ct_sw.png|Switches context}} |
| ##[[en:osa:ref:allservices:OS_Msg_Wait_TO|OS_Msg_Wait_TO]]## | ''(msg_cb, os_msg_type_var, timeout)'' | Wait for message. Exit if timeout expired | {{osa:ref:attr_call_task.png|Allowed only in task}}{{osa:ref:attr_call_ct_sw.png|Switches context}}{{osa:ref:attr_call_to.png|Service uses system timer}} |
~~UP~~
==== Simple messages ====
^ Service ^ Arguments ^ Description ^ Properties ^
| **Creating** ||||
| ##[[en:osa:ref:allservices:OS_Smsg_Create|OS_Smsg_Create]]## | ''(smsg)'' | Create and zero a simple message | |
| **Sending** ||||
| ##[[en:osa:ref:allservices:OS_Smsg_Send|OS_Smsg_Send]]## | ''(smsg, smessage)'' | Send a simple message. If message already exists then wait until it becomes free | {{osa:ref:attr_call_task.png|Allowed only in task}}{{osa:ref:attr_call_ct_sw.png|Switches context}} |
| ##[[en:osa:ref:allservices:OS_Smsg_Send_TO|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 | {{osa:ref:attr_call_task.png|Allowed only in task}}{{osa:ref:attr_call_ct_sw.png|Switches context}}{{osa:ref:attr_call_to.png|Service uses system timer}} |
| ##[[en:osa:ref:allservices:OS_Smsg_Send_Now|OS_Smsg_Send_Now]]## | ''(smsg, smessage)'' | Send s simple message. If message already exists then it will be overwritten | {{osa:ref:attr_call_can_int.png|Has alternate service for work in ISR (suffix "_I")}} |
| **Checking** ||||
| ''bool ''\\ ##[[en:osa:ref:allservices:OS_Smsg_Check|OS_Smsg_Check]]## | ''(smsg)'' | Check if simple message exists | {{osa:ref:attr_call_can_int.png|Has alternate service for work in ISR (suffix "_I")}} |
| ##[[en:osa:ref:allservices:OS_Smsg_Accept|OS_Smsg_Accept]]## | ''(smsg, os_smsg_type_var)'' | Accept existing simple message. After accepting, message is cleared | {{osa:ref:attr_call_can_int.png|Has alternate service for work in ISR (suffix "_I")}} |
| **Waiting** ||||
| ##[[en:osa:ref:allservices:OS_Smsg_Wait|OS_Smsg_Wait]]## | ''(smsg, os_smsg_type_var)'' | Wait for simple message. After accepting, simple message is cleared | {{osa:ref:attr_call_task.png|Allowed only in task}}{{osa:ref:attr_call_ct_sw.png|Switches context}} |
| ##[[en:osa:ref:allservices:OS_Smsg_Wait_TO|OS_Smsg_Wait_TO]]## | ''(smsg, os_smsg_type_var, timeout)'' | Wait for simple message. After accepting, simple message is cleared. Exit if timeout expired | {{osa:ref:attr_call_task.png|Allowed only in task}}{{osa:ref:attr_call_ct_sw.png|Switches context}}{{osa:ref:attr_call_to.png|Service uses system timer}} |
~~UP~~