📄 demoreference.c
字号:
/*The example system described in this chapter is comprised of an
Application_Initialize function and six tasks. All of the tasks are created during
initialization. In addition to task execution, task communication and synchronization are
demonstrated in this example.
In the example system listing, the data structures are defined between lines 3 and 20.
Nucleus PLUS control structures are defined between lines 3 and 13.
Application_Initialize starts at line 30, and ends at line 71. In this example, all
system objects (tasks, queues, semaphores, and event flag groups) are created during
initialization. The example system tasks are created between lines 38 and 61. The
communication queue is created at line 64. The system semaphore is created at line 68.
Finally, the system event flag group is created at line 70.
NOTE: A 20,000 byte memory pool, starting at the address specified by the
first_available_memory parameter is created first, at line 35. This memory
pool is used to allocate all of the task stacks and the actual queue area.
Task 0 is the first task to execute when the system starts. This is because task 0 is the
highest priority task in the system (priority 1). Task 3 executes after task 0 suspends
(priority 5). Task 4 executes after task 3 suspends. It is important to realize why task 3
executes before task 4 although they both have the same priority. The reason for this is
that task 3 was created and started first (see Application_Initialize). Tasks of the
same priority execute in the order they become ready for execution. After task 4 suspends,
task 5 executes (priority 7). After task 5 suspends, task 1 executes (priority 10). Finally,
task 2 executes (priority 10) after task 1 suspends on a queue full condition.
Task 0 is defined between lines 76 and 92. Like all of the tasks in this example system,
task 0 does some preliminary initialization and then starts execution of an endless loop.
Processing inside of task 0.s endless loop includes successive calls to NU_Sleep and
NU_Set_Events. Because of the call to NU_Sleep, task 0.s loop is executed once every
18 timer ticks.
NOTE: Task 5 is made ready on each call to NU_Set_Events. Since task 5 has
a lower priority than task 0, it does not execute until task 0 executes the
NU_Sleep call again.
Task 1 is defined between lines 96 and 121. Task 1 continually sends a single 32-bit
message to queue 0. When the capacity of the queue is reached, task 1 suspends, until
room is available in queue 0. The suspension of task 1 allows task 2 to resume execution.
Task 2 is defined between lines 124 and 156. Task 2 continually retrieves single 32-bit
messages from queue 0. When the queue becomes empty, task 2 suspends. The
suspension of task 2 allows task 1 to resume execution.
Tasks 3 and 4 share the same instruction code. However, each task has its own unique
stack. Tasks 3 and 4 are defined between lines 162 and 184. Each task competes for a
binary semaphore. Once the semaphore is obtained, the task sleeps for 100 ticks before
releasing the semaphore again.
This action allows the other task to execute and suspend attempting to obtain the same
semaphore. When the semaphore is released, suspension is lifted on the task waiting for
the semaphore.
Task 5 is defined between lines 186 and 204. This task is in an endless loop waiting for an
event flag to be set. The desired event flag is set by task 0. Therefore, task 5 executes at
the same frequency as task 0.
Example System
The following is a source file listing of the example system.
NOTE: The line number on the left is not part of the actual file, it is there for
reference purposes only.
*/
1 /* Include necessary Nucleus PLUS files. */
2 #include "inucleus.h”
3 /* Define Application data structures. */
4 NU_TASK Task_0;
5 NU_TASK Task_1;
6 NU_TASK Task_2;
7 NU_TASK Task_3;
8 NU_TASK Task_4;
9 NU_TASK Task_5;
10 NU_QUEUE Queue_0;
11 NU_SEMAPHORE Semaphore_0;
12 NU_EVENT_GROUP Event_Group_0;
13 NU_MEMORY_POOL System_Memory;
14 /* Allocate global counters. */
15 UNSIGNED Task_Time;
16 UNSIGNED Task_2_messages_received;
17 UNSIGNED Task_2_invalid_messages;
18 UNSIGNED Task_1_messages_sent;
19 NU_TASK * Who_has_the_resource;
20 UNSIGNED Event_Detections;
21 /* Define prototypes for function references. */
22 void task_0(UNSIGNED argc, VOID *argv);
23 void task_1(UNSIGNED argc, VOID *argv);
24 void task_2(UNSIGNED argc, VOID *argv);
25 void task_3_and_4(UNSIGNED argc, VOID *argv);
26 void task_5(UNSIGNED argc, VOID *argv);
/*27 Define the Application_Initialize routine that determines the initial
28 Nucleus PLUS application environment. */
29
30 void Application_Initialize(void *first_available_memory)
31 {
32 VOID *pointer;
/*33 Create a system memory pool that will be used to allocate task
34 stacks, queue areas, etc. */
35 NU_Create_Memory_Pool(&System_Memory, "SYSMEM”, first_available_memory,
36 20000, 50, NU_FIFO);
37 /* Create each task in the system. */
38 /* Create task 0. */
39 NU_Allocate_Memory(&System_Memory, &pointer, 1000, NU_NO_SUSPEND);
40 NU_Create_Task(&Task_0, "TASK 0”, task_0, 0, NU_NULL, pointer, 1000, 1,
41 20, NU_PREEMPT, NU_START);
42 /* Create task 1. */
43 NU_Allocate_Memory(&System_Memory, &pointer, 1000, NU_NO_SUSPEND);
44 NU_Create_Task(&Task_1, "TASK 1”, task_1, 0, NU_NULL, pointer, 1000, 10,
45 5,NU_PREEMPT, NU_START);
46 /* Create task 2. */
47 NU_Allocate_Memory(&System_Memory, &pointer, 1000, NU_NO_SUSPEND);
48 NU_Create_Task(&Task_2, "TASK 2”, task_2, 0, NU_NULL, pointer, 1000,
49 10, 5, NU_PREEMPT, NU_START);
50 /* Create task 3. Note: task 4 uses the same instruction area. */
51 NU_Allocate_Memory(&System_Memory, &pointer, 1000, NU_NO_SUSPEND);
52 NU_Create_Task(&Task_3, "TASK 3”, task_3_and_4, 0, NU_NULL, pointer,
53 1000, 5, 0, NU_PREEMPT, NU_START);
54 /* Create task 4. Note that task 3 uses the same instruction area.*/
55 NU_Allocate_Memory(&System_Memory, &pointer, 1000, NU_NO_SUSPEND);
56 NU_Create_Task(&Task_4, "TASK 4”, task_3_and_4, 0, NU_NULL, pointer,
57 1000, 5, 0, NU_PREEMPT, NU_START);
58 /* Create task 5. */
59 NU_Allocate_Memory(&System_Memory, &pointer, 1000, NU_NO_SUSPEND);
60 NU_Create_Task(&Task_5, "TASK 5”, task_5, 0, NU_NULL, pointer, 1000, 7, 0,
61 NU_PREEMPT, NU_START);
62 /* Create communication queue. */
63 NU_Allocate_Memory(&System_Memory, &pointer, 100*sizeof(UNSIGNED),
64 NU_NO_SUSPEND);
65 NU_Create_Queue(&Queue_0, "QUEUE 0”, pointer, 100, NU_FIXED_SIZE, 1,
66 NU_FIFO);
67 /* Create synchronization semaphore. */
68 NU_Create_Semaphore(&Semaphore_0, "SEM 0”, 1, NU_FIFO);
69 /* Create event flag group. */
70 NU_Create_Event_Group(&Event_Group_0, "EVGROUP0”);
71 }
72
73 /* Define task 0. Task 0 increments the Task_Time variable every
74 18 clock ticks. Additionally, task 0 sets an event flag that
75 task 5 is waiting for, on each iteration of the loop. */
76 void task_0(UNSIGNED argc, VOID *argv)
77 {
78 STATUS status;
79 /* Access argc and argv just to avoid compilation warnings.*/
80 status = (STATUS) argc + (STATUS) argv;
81 /* Set the clock to 0. This clock ticks every 18 system timer ticks. */
82 Task_Time = 0;
83 while(1)
84 {
85 /* Sleep for 18 timer ticks. The value of the tick is programmable in
IND.ASM and is relative to the speed of the target system. */
86 NU_Sleep(18);
87 /* Increment the time. */
88 Task_Time++;
89 /* Set an event flag to lift the suspension on task 5.*/
90 NU_Set_Events(&Event_Group_0, 1, NU_OR);
91 }
92 }
93 /* Define the queue sending task. Note that the only things that cause
94 this task to suspend are queue full conditions and the time slice
95 specified in the configuration file. */
96 void task_1(UNSIGNED argc, VOID *argv)
97 {
98 STATUS status;
99 UNSIGNED Send_Message;
100 /* Access argc and argv just to avoid compilation warnings. */
101 status = (STATUS) argc + (STATUS) argv;
102 /* Initialize the message counter. */
103 Task_1_messages_sent = 0;
104 /* Initialize the message contents. The receiver will
105 examine the message contents for errors. */
106 Send_Message = 0;
107 while(1)
108 {
109
110 /* Send the message to Queue_0, which task 2 reads from. Note
111 that if the destination queue fills up this task suspends until
112 room becomes available. */
113 status = NU_Send_To_Queue(&Queue_0, &Send_Message, 1,
114 NU_SUSPEND);
115 /* Determine if the message was sent successfully. */
116 if (status == NU_SUCCESS)
117 Task_1_messages_sent++;
118 /* Modify the contents of the next message to send. */
119 Send_Message++;
120 }
121 }
/* Define the queue receiving task. Note that the only things that
122 cause this task to suspend are queue empty conditions and the
123 time slice specified in the configuration file. */
124 void task_2(UNSIGNED argc, VOID *argv)
125 {
126 STATUS status;
127 UNSIGNED Receive_Message;
128 UNSIGNED received_size;
129 UNSIGNED message_expected;
130 /* Access argc and argv just to avoid compilation warnings. */
131 status = (STATUS) argc + (STATUS) argv;
132 /* Initialize the message counter. */
133 Task_2_messages_received = 0;
134 /* Initialize the message error counter. */
135 Task_2_invalid_messages = 0;
136 /* Initialize the message contents to expect. */
137 message_expected = 0;
138 while(1)
139 {
140 /* Retrieve a message from Queue_0, which task 1 writes to.
141 Note that if the source queue is empty this task
142 suspends until something becomes available. */
143 status = NU_Receive_From_Queue(&Queue_0, &Receive_Message, 1,
144 &received_size, NU_SUSPEND);
145 /* Determine if the message was received successfully. */
146 if (status == NU_SUCCESS)
147 Task_2_messages_received++;
148 /* Check the contents of the message against what this task
149 is expecting. */
150 if ((received_size != 1) ||
151 (Receive_Message != message_expected))
152 Task_2_invalid_messages++;
153 /* Modify the expected contents of the next message. */
154 message_expected++;
155 }
156 }
157 /* Tasks 3 and 4 want a single resource. Once one of the tasks gets the
158 resource, it keeps it for 30 clock ticks before releasing it. During
159 this time the other task suspends waiting for the resource. Note that
160 both task 3 and 4 use the same instruction areas but have different
161 stacks. */
162 void task_3_and_4(UNSIGNED argc, VOID *argv)
163 {
164 STATUS status;
165 /* Access argc and argv just to avoid compilation warnings. */
166 status = (STATUS) argc + (STATUS) argv;
167 /* Loop to allocate and deallocate the resource. */
168 while(1)
169 {
170 /* Allocate the resource. Suspend until it becomes available. */
171 status = NU_Obtain_Semaphore(&Semaphore_0, NU_SUSPEND);
172 /* If the status is successful, show that this task owns the
173 resource. */
174 if (status == NU_SUCCESS)
175 {
176 Who_has_the_resource = NU_Current_Task_Pointer();
177 /* Sleep for 100 ticks to cause the other task to suspend on
178 the resource. */
179 NU_Sleep(100);
180 /* Release the semaphore. */
181 NU_Release_Semaphore(&Semaphore_0);
182 }
183 }
184 }
185 /* Define the task that waits for the event to be set by task 0. */
186 void task_5(UNSIGNED argc, VOID *argv)
187 {
188 STATUS status;
189 UNSIGNED event_group;
190 /* Access argc and argv just to avoid compilation warnings. */
191 status = (STATUS) argc + (STATUS) argv;
192 /* Initialize the event detection counter. */
193 Event_Detections = 0;
Nucleus PLUS Reference Manual
194 /* Continue this process forever. */
195 while(1)
196 {
197 /* Wait for an event and consume it. */
198 status = NU_Retrieve_Events(&Event_Group_0, 1, NU_OR_CONSUME,
199 &event_group, NU_SUSPEND);
200 /* If the status is okay, increment the counter. */
201 if (status == NU_SUCCESS)
202 Event_Detections++;
203 }
204 }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -