• Home
Name Date Size #Lines LOC

..--

BUILD.gnD12-May-2024801 2117

README_zh.mdD12-May-20248.5 KiB231175

kernel_queue_example.cD12-May-20243.7 KiB12571

README_zh.md

1# 小凌派-RK2206开发板OpenHarmonyOS内核开发-队列
2
3## 实验内容
4
5本例程演示如何在小凌派-RK2206开发板上使用鸿蒙LiteOS-M内核接口,进行队列编程开发。例程创建一个队列,两个任务;任务1调用写队列接口发送消息,任务2调用读队列接口接收消息。
6
7![小凌派-RK2206开发板](../../docs/figures/lockzhiner-rk2206.jpg)
8
9## 程序设计
10
11队列,是一种常用于任务间通信的数据结构。队列可以在任务与任务、任务与中断之间传递消息,实现任务接收来自其他任务或者中断的不固定长度的消息。任务能够从队列里面读取消息,当队列中的消息为空时,读取消息的任务将被阻塞,阻塞的时间可以由用户自行定义,任务会一直等待队列里新消息的到来或者直到等待的时间超过阻塞时间,任务就会从阻塞态转为就绪态。
12
13队列中可以存储有限的、大小固定的数据结构。任务与任务、任务与中断之间要传递的数据保存在队列中;队列所能保存的最大数据数量叫做队列的长度,创建队列的时候需要指定数据的大小和队列的长度。
14
15通过队列,任务或中断可以将一条或者多条消息放入队列中,这样其他的任务就可以通过队列获取消息。当多个消息发送到队列时,通常是将先进队列的消息先传出去,即队列支持先进先出的原则(FIFO)。
16
17### API分析
18
19#### LOS_QueueCreate()
20
21```c
22UINT32 LOS_QueueCreate(CHAR *queueName,
23                        UINT16 len,
24                        UINT32 *queueID,
25                        UINT32 flags,
26                        UINT16 maxMsgSize);
27```
28
29**描述:**
30
31创建一个队列,由系统动态申请队列空间。
32
33**参数:**
34
35| 名字       | 描述               |
36| :--------- | :----------------- |
37| queueName  | 需要创建的队列名   |
38| len        | 需要创建队列的长度 |
39| queueID    | 创建生成的队列ID   |
40| flags      | 队列模式           |
41| maxMsgSize | 队列节点大小       |
42
43**返回值:**
44
45| 返回值                                                                                                                                                                                     | 描述 |
46| :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--- |
47| LOS_OK                                                                                                                                                                                     | 成功 |
48| LOS_ERRNO_QUEUE_CB_UNAVAILABLE`<br>` LOS_ERRNO_QUEUE_CREATE_NO_MEMORY `<br>` LOS_ERRNO_QUEUE_CREAT_PTR_NULL `<br>` LOS_ERRNO_QUEUE_PARA_ISZERO `<br>` LOS_ERRNO_QUEUE_SIZE_TOO_BIG | 失败 |
49
50#### LOS_QueueDelete()
51
52```c
53UINT32 LOS_QueueDelete(UINT32 queueID);
54```
55
56**描述:**
57
58根据队列ID删除一个指定队列。
59
60**参数:**
61
62| 名字    | 描述             |
63| :------ | :--------------- |
64| queueID | 需要删除的队列ID |
65
66**返回值:**
67
68| 返回值                                                                                       | 描述 |
69| :------------------------------------------------------------------------------------------- | :--- |
70| LOS_OK                                                                                       | 成功 |
71| LOS_ERRNO_QUEUE_PTR_NULL`<br>` LOS_ERRNO_QUEUE_INVALID `<br>` LOS_ERRNO_QUEUE_NOT_CREATE | 失败 |
72
73#### LOS_QueueRead()
74
75```c
76UINT32 LOS_QueueRead(UINT32 queueID,
77                    VOID *bufferAddr,
78                    UINT32 bufferSize,
79                    UINT32 timeOut);
80```
81
82**描述:**
83
84读取指定队列头节点中的数据(队列节点中的数据实际上是一个地址)。
85
86**参数:**
87
88| 名字       | 描述             |
89| :--------- | :--------------- |
90| queueID    | 需要读取的队列ID |
91| bufferAddr | 缓冲区指针       |
92| bufferSize | 缓冲区大小       |
93| timeout    | 超时时间         |
94
95**返回值:**
96
97| 返回值                                                                                                                                                                                                                                                                                        | 描述 |
98| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--- |
99| LOS_OK                                                                                                                                                                                                                                                                                        | 成功 |
100| LOS_ERRNO_QUEUE_INVALID`<br>` LOS_ERRNO_QUEUE_READ_PTR_NULL `<br>` LOS_ERRNO_QUEUE_READSIZE_ISZERO `<br>` LOS_ERRNO_QUEUE_READ_IN_INTERRUPT `<br>` LOS_ERRNO_QUEUE_NOT_CREATE `<br>` LOS_ERRNO_QUEUE_ISEMPTY `<br>` LOS_ERRNO_QUEUE_PEND_IN_LOCK `<br>` LOS_ERRNO_QUEUE_TIMEOUT | 失败 |
101
102### 软件设计
103
104**主要代码分析**
105
106在queue_example函数中,通过LOS_QueueCreate函数创建一个队列;通过LOS_TaskCreate函数创建两个线程:msg_write_thread和msg_read_thread。
107
108```c
109void queue_example()
110{
111    unsigned int thread_id1;
112    unsigned int thread_id2;
113    TSK_INIT_PARAM_S task1 = {0};
114    TSK_INIT_PARAM_S task2 = {0};
115    unsigned int ret = LOS_OK;
116
117    ret = LOS_QueueCreate("queue", MSG_QUEUE_LENGTH, &m_msg_queue, 0, BUFFER_LEN);
118    if (ret != LOS_OK)
119    {
120        printf("Failed to create Message Queue ret:0x%x\n", ret);
121        return;
122    }
123
124    task1.pfnTaskEntry = (TSK_ENTRY_FUNC)msg_write_thread;
125    task1.uwStackSize = 2048;
126    task1.pcName = "msg_write_thread";
127    task1.usTaskPrio = 24;
128    ret = LOS_TaskCreate(&thread_id1, &task1);
129    if (ret != LOS_OK)
130    {
131        printf("Failed to create msg_write_thread ret:0x%x\n", ret);
132        return;
133    }
134
135    task2.pfnTaskEntry = (TSK_ENTRY_FUNC)msg_read_thread;
136    task2.uwStackSize = 2048;
137    task2.pcName = "msg_read_thread";
138    task2.usTaskPrio = 25;
139    ret = LOS_TaskCreate(&thread_id2, &task2);
140    if (ret != LOS_OK)
141    {
142        printf("Failed to create msg_read_thread ret:0x%x\n", ret);
143        return;
144    }
145}
146```
147
148msg_write_thread函数每隔1s,通过LOS_QueueWrite函数向队列中发送消息。
149
150```c
151void msg_write_thread(void)
152{
153    unsigned int data = 0;
154    unsigned int ret = LOS_OK;
155
156    while (1)
157    {
158        data++;
159        ret = LOS_QueueWrite(m_msg_queue, (void *)&data, sizeof(data), LOS_WAIT_FOREVER);
160        if (LOS_OK != ret)
161        {
162            printf("%s write Message Queue msg fail ret:0x%x\n", __func__, ret);
163        }
164        else
165        {
166            printf("%s write Message Queue msg:%u\n", __func__, data);
167        }
168
169        /*delay 1s*/
170        LOS_Msleep(1000);
171    }
172}
173```
174
175msg_read_thread函数通过LOS_QueueRead函数读取队列中的消息,当队列中没有消息的时候,msg_read_thread函数阻塞等待消息。
176
177```c
178void msg_read_thread(void)
179{
180    unsigned int addr;
181    unsigned int ret = LOS_OK;
182    unsigned int *pData = NULL;
183
184    while (1)
185    {
186        /*wait for message*/
187        ret = LOS_QueueRead(m_msg_queue, (void *)&addr, BUFFER_LEN, LOS_WAIT_FOREVER);
188        if (ret == LOS_OK)
189        {
190            pData = addr;
191            printf("%s read Message Queue msg:%u\n", __func__, *pData);
192        }
193        else
194        {
195            printf("%s read Message Queue fail ret:0x%x\n", __func__, ret);
196        }
197    }
198}
199```
200
201## 编译调试
202
203### 修改 BUILD.gn 文件
204
205修改 `vendor/lockzhiner/lingpi/sample` 路径下 BUILD.gn 文件,指定 `a5_kernel_queue` 参与编译。
206
207```r
208"a5_kernel_queue",
209```
210
211在主目录下输入编译命令。
212
213```shell
214hb build -f
215```
216
217### 运行结果
218
219例程代码编译烧写到开发板后,按下开发板的RESET按键,通过串口软件查看日志,Thread_Msg_Write函数1S写入一次数据,此时Thread_Msg_Read函数退出阻塞读取数据并打印接收的数据。
220
221```r
222msg_write_thread write Message Queue msg:1
223msg_read_thread read Message Queue msg:1
224msg_write_thread write Message Queue msg:2
225msg_read_thread read Message Queue msg:2
226msg_write_thread write Message Queue msg:3
227msg_read_thread read Message Queue msg:3
228msg_write_thread write Message Queue msg:4
229msg_read_thread read Message Queue msg:4
230```
231