Ucos ii Task Management
After the task is created, the ucos ii programming has been implemented. With further programming, it is still not enough to learn how to create a task.
In my project, we need to implement the 485 communication function. I created Task 1 for Serial 1 to send data, and task 2 for Serial 1 to receive data. The intention of the program itself is to receive the feedback from Serial Port 1 after the data is sent.
However, when the program is downloaded to the circuit board, the problem occurs and the communication fails. The reason is that when Task 1 is sending data, the CPU runs to task 2 from time to accept the data, in this way, the data sent by the user will be accepted.
Therefore, mc2008 was wondering if it could be implemented. When Task 1 is executed, Task 2 is not executed. When Task 1 is completed, Task 2 is executed. Similarly, when Task 2 is finished, Task 1 can be executed.
The answer is yes.
Ucos ii provides two operations: Task suspension and task recovery.
What is a pending task? What is a recovery task?
To put it simply, a pending task is to hook up the task, the CPU does not execute it, and the recovery task is the reverse operation of the pending task. It's like if your girlfriend hangs you up and doesn't miss you anymore. Haha, I know it's wrong.
In my Project, Task 2 is suspended when Task 1 is executed. When Task 1 is finished, Task 2 is restored. In this way, the problem of sending conflict is solved.
The following describes the pending and resuming operations in detail.
To suspend a task, you must use the ostasksuspend () function. A task can suspend itself or other tasks. ostasksuspend () only requires one parameter, that is, the priority of the task to be suspended.
Program list l 4.16 ostasksuspend (). |
Int8u ostasksuspend (int8u PRIO) |
{ |
Boolean self; |
OS _tcb * ptcb; |
|
|
If (PRIO = OS _idle_prio) {(1) |
Return (OS _task_suspend_idle ); |
} |
If (PRIO> = OS _lowest_prio & PRIO! = OS _prio_self) {(2) |
Return (OS _prio_invalid ); |
} |
OS _enter_critical (); |
If (PRIO = OS _prio_self) {(3) |
Prio = ostcbcur-> ostcbprio; |
Self = true; |
} Else if (PRIO = ostcbcur-> ostcbprio) {(4) |
Self = true; |
} Else { |
Self = false; |
} |
If (ptcb = ostcbpriotbl [PRIO]) = (OS _tcb *) 0) {(5) |
OS _exit_critical (); |
Return (OS _task_suspend_prio ); |
} Else { |
If (osrdytbl [ptcb-> ostcby] & = ~ Ptcb-> ostcbbitx) = 0) {(6) |
Osrdygrp & = ~ Ptcb-> ostcbbity; |
} |
Ptcb-> ostcbstat | = OS _stat_suspend; (7) |
OS _exit_critical (); |
If (Self = true) {(8) |
Ossched (); |
} |
Return (OS _no_err ); |
} |
} |
First, understand the implementation process of the suspension.
1. First, ostasksuspend () should ensure that the user's application is not pending idle tasks [l4.16 (1)], and then confirm that the user-specified priority is valid [l4.16 (2)]. Remember that the maximum valid priority level (that is, the lowest priority) is OS _lowest_prio. Note that you can suspend a statistical task (Statistic ). You may have noticed that the first test [l4.16 (1)] was repeated in [l4.16 (2. This is done to be compatible with μC/OS. The first test can be removed and saves a little time for program processing. However, this is of little significance, so I decided to leave it.
2. Then, ostasksuspend () checks whether the user has suspended the task calling this function by specifying OS _prio_self [l4.16 (3)]. You can also specify a priority to suspend the task [l4.16 (4)] that calls this function. In both cases, the task scheduler needs to be called. This is why I want to define the local variable self, which will be tested as appropriate. If the user does not suspend the task that calls this function, ostasksuspend () does not need to run the task scheduler because the task with lower priority is being suspended.
3. Then, ostasksuspend () checks whether the task to be suspended exists [l4.16 (5)]. If the task exists, it will be removed from the ready table [l4.16 (6)]. In my understanding, this is the most critical part of the task suspension function. The so-called task suspension means to delete the task from the ready table, because the next task executed by the CPU is the task with the highest priority in the ready table, when the task is not in the ready table, it is not possible that the task will be executed again. The following describes the implementation process. The readiness flag of each task is placed in the readiness table. The readiness table has two variables: osrdygrp and osrdytbl []. In osrdygrp, tasks are grouped by priority, and eight tasks are a group. Each bit in osrdygrp indicates whether there are ready tasks in each group of 8 tasks. When the task enters the ready state, the corresponding bit of the corresponding element in the ready table osrdytbl [] is also set. For example, if I want to delete a task with a priority of 5 from the ready table, I need to clear the fifth digit of osrdytbl [0] and the second digit of osrdygrp.
Note that the task to be suspended may not be in the ready table, because it may be waiting for the occurrence of the event or the expiration of the delay. In this case, the bit corresponding to the task to be suspended in osrdytbl [] has been cleared (that is, 0 ). Clearing this bit again is much faster than checking whether it is cleared first and then clearing it when it is not cleared. Therefore, I did not check this bit and cleared it directly. Now, ostasksuspend () can set the OS _stat_suspend flag in OS _tcb of the task to indicate that the task is being suspended [l4.16 (7)]. Finally, ostasksuspend () calls the task scheduler [l4.16 (8)] only when the suspended task is the task that calls this function.