• Home
Name Date Size #Lines LOC

..--

.application_configD12-May-2024686 1614

BUILD.gnD12-May-2024869 2522

README_zh.mdD12-May-20248.4 KiB288213

os_thread_example.cD12-May-20244.1 KiB13289

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