Detailed explanation of mailbox exampe, a built-in routine of DSP/BIOS
[Copy link]
The main program of the routine:
#include <std.h>
#include <log.h>
#include <mbx.h>
#include <tsk.h>
#include "mailboxcfg.h"
#define NUMMSGS 3 /* number of messages */
#define TIMEOUT 10
typedef struct MsgObj {
Int id; /* writer task id */
Char val; /* message value */
} MsgObj, *Msg;
Void reader(Void);
Void writer(Arg id_arg);
/*
* ===== === main ========
*/
Void main()
{
/* Does nothing */
}
/*
* ======== reader ========
*/
Void reader (Void)
{
MsgObj msg;
Int i;
for (i=0; ;i++) {
/* wait for mailbox to be posted by writer() */
if (MBX_pend(&mbx, &msg, TIMEOUT) == 0) {
LOG_printf (&trace, "timeout expired for MBX_pend()");
break;
}
/* print value */
LOG_printf(&trace, "read '%c' from (%d).", msg.val, msg.id);
}
LOG_printf(&trace, "reader done.");
}
/*
* ======== writer ========
*/
Void writer(Arg id_arg)
{
MsgObj msg;
Int i;
Int id = ArgToInt (id_arg);
for (i=0; i < NUMMSGS; i++) {
/* fill in value */
msg.id = id;
msg.val = i % NUMMSGS + (Int)('a');
/* enqueue message */
MBX_post(&mbx, &msg, TIMEOUT);
LOG_printf(&trace, "(%d) writing '%c' ...", id, (Int)msg.val);
/* what happens if you call TSK_yield () here? */
// TSK_yield();
}
// LOG_printf(&trace, "writer (%d) done.", id);
}
The program creates four tasks, one reader task, three writer tasks, and three Each writer task calls the same task function writer(), but the function parameters passed are different, which are 0, 1, and 2 respectively; the priorities of the four tasks are the same, and the task creation order is: reader->writer0 ->writer1->writer2. Mailbox size is 8 bytes, 2 words in length.
The program running results are as follows
Let’s analyze how this demo achieves the above results: First, we need to know the order in which the program is executed. Here I will simply draw a flow chart of the program.
After the program executes the main() function, the first thing to execute is the reader() function. When executing the MBX_pend function, it is found that the mailbox is empty, so the task is blocked and can only continue to run after the system calls the MBX_post function. At this time, the program executes the writer0 task. The writer0 task is to write data into the mailbox. Since the length of the mailbox is 2 bytes, after writing two bytes, the mailbox is full, and the task switches to the reader task, which is printing. Extract the contents of the mailbox and clear the data in the mailbox. Then MBX_pend is blocked again and continues to execute the writer0 task. The remaining tasks of writer0 can only write one more byte to the mailbox, so the writer1 task is started. At this time, the mailbox is full again, so the task is switched to reader to read data. Following the steps of this demonstration, the inferred results are different from the actual output results. So where is the problem?
After consulting some information from my predecessors, I finally understood that mailbox has its own task queue. Here I will borrow a vivid example from my predecessors to illustrate:
Suppose there are three teams of ABC people queuing up to buy tickets, each with 3 people, named A1A2A3B1B2B3C1C2C3. They queue in the square outside the ticketing hall. There is a door in the ticketing hall. People who want to enter the hall must line up in front of the door. Then you can go in. From their respective teams to the queues at the door, follow the order of ABC. Each team at the door can only have one person. There are two windows selling tickets in the hall. If there are people buying tickets at both windows, then the one behind them will People can only line up at the door and cannot enter the hall. Only when the people who bought tickets at the two windows have left, the first two people in the back can enter the hall. People who enter the hall, if there are still people in their team, must Notify the next person to come and line up. Then take a look at the order of buying tickets and queuing up. At first A1A2 arrives at the door, the hall is empty, two people go in, informs A3 to come and line up,
A3 arrives at the door, it is full, queues at the door, and there is already one person in team A Outside the door, it’s team B’s turn. B1 queues up at the door, lining up behind A3. Group B ends. It’s team C’s turn. C1 queues behind B1. Team C ends. Now the first round of ticket sales begins. A1 and A2 buy their tickets and leave. People can enter through the gate. A3 enters the hall. Because there is no one in team A, there is no need to notify. Then B1 enters the hall and notifies B2 of team B to come and queue. B2 can only queue behind C1.
The hall is full and no one is allowed to enter . , start selling tickets, A3B1 buys and leaves. The door opens, C1 enters, notifies C2 to come and queue, C2 queues behind B2, B2 enters, notifies B3 to queue, B3 queues behind C2. The hall is full, starts selling tickets, C1B2 buys Finished leaving. The hall is empty, the door is open, C2 enters, C3 is notified, C3 is in line behind B3, B3 enters the hall, there is no one in Team B, no notification is needed, the hall is full, tickets are sold, C2B3 buys and leaves, the hall is empty, the door is opened , C3 entered, and there was no one behind him, so there was no need to notify him. Since all the queues had been queued up, even though the hall was not full, tickets were being sold. C3 finished buying and left. The ticket seller waited for a while and found that no one came to buy, so he I closed the door and went home. The order of buying tickets is A1A2A3B1 C1B2 C2B3 C3. By analogy with tsk and mbx, the three tsk are the three lines of ABC. Every time you want to post a piece of data, you have to line up at the door, and the line at the door is the task of mbx. Queue, only when the contents in mbx are read, will the tasks in the task queue be started in sequence.
I drew a schematic diagram according to the meaning of this example:
By modifying the mailbox size and the number of bytes written to the mailbox by each task, I did some tests and found that when the number of mailboxes is smaller than the number of tasks, , the above theory is correct, but once the number of mailboxes exceeds the number of tasks, the same tasks will appear in the same queue when the tasks are queued, which conflicts with the above theory, and it is impossible to know what the task queue is at this time. Yes, the MBX_pend and MBX_post functions are API interface functions provided by TI. The result of being closed source is that we do not know how to set up the task queue inside the function, so this part still needs to be studied.
|