README_zh.md
1# NiobeU4开发板OpenHarmony内核编程开发——Thread多线程
2本示例将演示如何在Niobe u4开发板上使用liteos-m接口进行多线程开发
3
4## Thread struct分析
5
6### TSK_INIT_PARAM_S
7
8```
9typedef struct tagTskInitParam {
10 TSK_ENTRY_FUNC pfnTaskEntry; /< Task entrance function */
11 UINT16 usTaskPrio; /< Task priority */
12 UINT32 uwArg; /< Task parameters */
13 UINTPTR stackAddr; /< Task satck memory */
14 UINT32 uwStackSize; /< Task stack size */
15 CHAR *pcName; /< Task name */
16 UINT32 uwResved; /**< Reserved */
17} TSK_INIT_PARAM_S;
18```
19
20**描述:**
21|名字|描述|
22|:--|:------|
23| pfnTaskEntry | 新建线程的函数入口 |
24| usTaskPrio |线程优先级,0-31|
25| uwArg | 线程函数传参 |
26| stackAddr | 堆栈起始地址 |
27| uwStackSize | 堆栈大小,当传入值为0时,使用默认值LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE |
28| pcName | 线程名称 |
29
30## Thread API分析
31
32### LOS_TaskCreate()
33
34```c
35UINT32 LOS_TaskCreate(UINT32 *taskID, TSK_INIT_PARAM_S *taskInitParam);
36```
37**描述:**
38
39函数LOS_TaskCreate通过将线程添加到活动线程列表并将其设置为就绪状态来启动线程函数。当创建的thread函数的优先级高于当前运行的线程且线程调度未被锁定时,创建的thread函数立即启动并成为新的运行线程。
40可以在RTOS启动(调用 osKernelStart)之前安全地调用该函数,但不能在内核初始化 (调用 osKernelInitialize)之前调用该函数。
41> **注意** :不能在中断服务调用该函数
42
43
44**参数:**
45
46|名字|描述|
47|:--|:------|
48| taskID | 指针,指向线程id |
49| taskInitParam |新建线程的相关属性以及线程的函数入口和参数等|
50
51### LOS_TaskSuspend()
52
53```c
54UINT32 LOS_TaskSuspend(UINT32 taskID);
55```
56**描述:**
57
58根据参数taskID,挂起相应任务。此时任务taskID如果处于运行态,会由运行态切换到阻塞态,并插入到阻塞队列中,而cpu会转去执行就绪列表中最高优先级的任务。
59> **注意** :不能在任务调度处于关闭的状态下调用(即不能在调用osKernelLock之后调用)
60
61
62**参数:**
63
64|名字|描述|
65|:--|:------|
66| taskID | 线程id |
67
68### LOS_TaskResume()
69
70```c
71UINT32 LOS_TaskResume(UINT32 taskID)
72```
73**描述:**
74
75根据参数taskID,恢复相应任务。此时任务taskID如果处于阻塞态,会由阻塞态切换到就绪态,并插入到就绪队列中,如果此时就绪队列中没有比该任务taskID更高优先级的任务,则任务taskID会由就绪态切换到运行态。
76
77
78**参数:**
79
80|名字|描述|
81|:--|:------|
82| taskID | 线程id |
83
84### osThreadJoin()
85
86```c
87UINT32 LOS_TaskJoin(UINT32 taskID, UINTPTR *retval);
88```
89**描述:**
90
91挂起当前任务,等待指定任务taskID运行结束并回收其任务控制块资源。
92
93
94**参数:**
95
96|名字|描述|
97|:--|:------|
98| taskID | 线程id |
99| retval | 线程taskID结束后的返回值 |
100
101### LOS_TaskDelete()
102
103```c
104UINT32 LOS_TaskDelete(UINT32 taskID);
105```
106**描述:**
107
108删除指定线程/任务,释放其任务堆栈和任务控制块的资源
109
110**参数:**
111
112|名字|描述|
113|:--|:------|
114| taskID | 线程id |
115
116### LOS_TaskLock()
117```c
118VOID LOS_TaskLock(VOID);
119```
120**描述:**
121
122锁任务调度。在任务调度被锁的状态下,不能调用LOS_TaskSuspend,LOS_TaskDelay
123
124
125### LOS_TaskUnlock()
126```c
127UINT32 LOS_TaskUnlock(VOID);
128```
129**描述:**
130
131解锁任务调度。
132
133
134## 软件设计
135
136**主要代码分析**
137
138在OS_Thread_example函数中,通过osThreadNew()函数创建了threadHi和threadLo两个不同优先级的任务,包括任务延迟、挂起、恢复等操作,,threadHi和threadLo启动后会输出打印日志,通过打印日志可熟悉任务优先级调度机制。
139
140```c
141UINT32 g_taskHiId;
142UINT32 g_taskLoId;
143#define TSK_PRIOR_HI 4
144#define TSK_PRIOR_LO 5
145
146UINT32 Example_TaskHi(VOID)
147{
148 UINT32 ret;
149
150 printf("Enter TaskHi Handler.\n");
151
152 /* 延时100个Ticks,延时后该任务会挂起,执行剩余任务中最高优先级的任务(TaskLo任务) */
153 ret = LOS_TaskDelay(100);
154 if (ret != LOS_OK) {
155 printf("Delay TaskHi Failed.\n");
156 return LOS_NOK;
157 }
158
159 /* 100个Ticks时间到了后,该任务恢复,继续执行 */
160 printf("TaskHi LOS_TaskDelay Done.\n");
161
162 /* 挂起自身任务 */
163 ret = LOS_TaskSuspend(g_taskHiId);
164 if (ret != LOS_OK) {
165 printf("Suspend TaskHi Failed.\n");
166 return LOS_NOK;
167 }
168 printf("TaskHi LOS_TaskResume Success.\n");
169 return ret;
170}
171
172/* 低优先级任务入口函数 */
173UINT32 Example_TaskLo(VOID)
174{
175 UINT32 ret;
176
177 printf("Enter TaskLo Handler.\n");
178
179 /* 延时100个Ticks,延时后该任务会挂起,执行剩余任务中最高优先级的任务 */
180 ret = LOS_TaskDelay(100);
181 if (ret != LOS_OK) {
182 printf("Delay TaskLo Failed.\n");
183 return LOS_NOK;
184 }
185
186 printf("TaskHi LOS_TaskSuspend Success.\n");
187
188 /* 恢复被挂起的任务g_taskHiId */
189 ret = LOS_TaskResume(g_taskHiId);
190 if (ret != LOS_OK) {
191 printf("Resume TaskHi Failed.\n");
192 return LOS_NOK;
193 }
194 return ret;
195}
196
197/* 任务测试入口函数,创建两个不同优先级的任务 */
198UINT32 Example_TskCaseEntry(VOID)
199{
200 UINT32 ret;
201 TSK_INIT_PARAM_S initParam;
202
203 /* 锁任务调度,防止新创建的任务比本任务高而发生调度 */
204 LOS_TaskLock();
205
206 printf("LOS_TaskLock() Success!\n");
207
208 UINT32 curTaskID = LOS_CurTaskIDGet();
209 TSK_INFO_S taskInfo;
210 ret = LOS_TaskInfoGet(curTaskID,&taskInfo);
211 if(ret == LOS_OK)
212 {
213 printf("curTask pro = %d\n",taskInfo.usTaskPrio);
214 }
215
216
217 initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_TaskHi;
218 initParam.usTaskPrio = TSK_PRIOR_HI;
219 initParam.pcName = "TaskHi";
220 initParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
221 initParam.uwResved = 0; /* detach 属性 */
222
223 /* 创建高优先级任务,由于锁任务调度,任务创建成功后不会马上执行 */
224 ret = LOS_TaskCreate(&g_taskHiId, &initParam);
225 if (ret != LOS_OK) {
226 LOS_TaskUnlock();
227
228 printf("Example_TaskHi create Failed!\n");
229 return LOS_NOK;
230 }
231
232 printf("Example_TaskHi create Success!\n");
233
234 initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_TaskLo;
235 initParam.usTaskPrio = TSK_PRIOR_LO;
236 initParam.pcName = "TaskLo";
237 initParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
238
239 /* 创建低优先级任务,由于锁任务调度,任务创建成功后不会马上执行 */
240 ret = LOS_TaskCreate(&g_taskLoId, &initParam);
241 if (ret != LOS_OK) {
242 LOS_TaskUnlock();
243 printf("Example_TaskLo create Failed!\n");
244 return LOS_NOK;
245 }
246
247 printf("Example_TaskLo create Success!\n");
248
249 /* 解锁任务调度,此时会发生任务调度,执行就绪队列中最高优先级任务 */
250 LOS_TaskUnlock();
251 ret = LOS_TaskJoin(g_taskHiId, NULL);
252 if (ret != LOS_OK) {
253 printf("Join Example_TaskHi Failed!\n");
254 } else {
255 printf("Join Example_TaskHi Success!\n");
256 }
257 return LOS_OK;
258}
259
260OHOS_APP_RUN(Example_TskCaseEntry);
261```
262
263## 编译调试
264
265### 修改 Kconfig.liteos_m.board 文件
266
267- 进入//kernel/liteos_m目录, 在menuconfig配置中进入如下选项:
268 `(Top) → Platform → Board Selection → select board niobeu4 → use openvalley niobeu4 application → niobeu4 application choose`
269- 选择 `002_system_los_thread`
270- 回到sdk根目录,执行`hb build`脚本进行编译。
271
272### 运行结果<a name="section_os_thread_example"></a>
273
274示例代码编译烧录代码后,按下开发板的RESET按键,通过串口助手查看日志:
275```c
276LOS_TaskLock() Success!
277curTask pro = 15
278Example_TaskHi create Success!
279Example_TaskLo create Success!
280Enter TaskHi Handler.
281Enter TaskLo Handler.
282TaskHi LOS_TaskDelay Done.
283TaskHi LOS_TaskSuspend Success.
284TaskHi LOS_TaskResume Success.
285Join Example_TaskHi Success!
286
287```
288