2.8 内核基础组件
2.8.1 消息队列
概述
消息队列提供了一种同步的传递/收取消息的机制,与队列(tos_queue)不同的是,tos_queue基于消息队列封装了一层异步的机制,实际上tos_queue的底层消息管理采用的就是消息队列。
API讲解
编程实例
1、在tos_config.h中,配置消息队列组件开关TOS_CFG_MSG_EN:
#define TOS_CFG_MSG_EN 1u
2、在tos_config.h中,配置消息队列池大小TOS_CFG_MSG_POOL_SIZE:
#define TOS_CFG_MSG_POOL_SIZE 3u
这是消息队列池中可以承载的最大消息数量
3、编写main.c示例代码:
- #include "tos.h"
- #include "mcu_init.h"
- #define STK_SIZE_TASK_DEMO 512
- #define PRIO_TASK_DEMO 4
- k_stack_t stack_task_demo[STK_SIZE_TASK_DEMO];
- k_task_t task_demo;
- k_msg_queue_t msg_queue;
- struct msg_st {
- char *msg;
- size_t size;
- } msgs[TOS_CFG_MSG_POOL_SIZE] = {
- { "msg 0", 6 },
- { "msg 1", 6 },
- { "msg 2", 6 },
- };
- struct msg_st dummy_msg = { "dummy msg", 10 };
- extern void entry_task_demo(void *arg);
- void fifo_opt(void) {
- k_err_t err;
- int i = 0;
- char *msg_received = K_NULL;
- size_t msg_size = 0;
- for (; i < TOS_CFG_MSG_POOL_SIZE; ++i) {
- printf("msg put: %s\n", msgs[i].msg);
- err = tos_msg_queue_put(&msg_queue, (void *)msgs[i].msg, msgs[i].size, TOS_OPT_MSG_PUT_FIFO);
- if (err != K_ERR_NONE) {
- printf("should never happen\n");
- }
- }
- err = tos_msg_queue_put(&msg_queue, (void *)dummy_msg.msg, dummy_msg.size, TOS_OPT_MSG_PUT_FIFO);
- if (err == K_ERR_MSG_QUEUE_FULL) {
- printf("msg queue is full\n");
- } else {
- printf("should never happen\n");
- }
- for (i = 0; i < TOS_CFG_MSG_POOL_SIZE; ++i) {
- err = tos_msg_queue_get(&msg_queue, (void **)&msg_received, &msg_size);
- if (err == K_ERR_NONE) {
- printf("msg received: %s\n", msg_received);
- printf("msg size: %d\n", msg_size);
- } else {
- printf("should never happen\n");
- }
- }
- err = tos_msg_queue_get(&msg_queue, (void **)&msg_received, &msg_size);
- if (err == K_ERR_MSG_QUEUE_EMPTY) {
- printf("msg queue is empty\n");
- } else {
- printf("should never happen\n");
- }
- }
- void lifo_opt(void) {
- k_err_t err;
- int i = 0;
- char *msg_received = K_NULL;
- size_t msg_size = 0;
- for (; i < TOS_CFG_MSG_POOL_SIZE; ++i) {
- printf("msg put: %s\n", msgs[i].msg);
- err = tos_msg_queue_put(&msg_queue, (void *)msgs[i].msg, msgs[i].size, TOS_OPT_MSG_PUT_LIFO);
- if (err != K_ERR_NONE) {
- printf("should never happen\n");
- }
- }
- err = tos_msg_queue_put(&msg_queue, (void *)dummy_msg.msg, dummy_msg.size, TOS_OPT_MSG_PUT_LIFO);
- if (err == K_ERR_MSG_QUEUE_FULL) {
- printf("msg queue is full\n");
- } else {
- printf("should never happen\n");
- }
- for (i = 0; i < TOS_CFG_MSG_POOL_SIZE; ++i) {
- err = tos_msg_queue_get(&msg_queue, (void **)&msg_received, &msg_size);
- if (err == K_ERR_NONE) {
- printf("msg received: %s\n", msg_received);
- printf("msg size: %d\n", msg_size);
- } else {
- printf("should never happen\n");
- }
- }
- err = tos_msg_queue_get(&msg_queue, (void **)&msg_received, &msg_size);
- if (err == K_ERR_MSG_QUEUE_EMPTY) {
- printf("msg queue is empty\n");
- } else {
- printf("should never happen\n");
- }
- }
- void entry_task_demo(void *arg)
- {
- tos_msg_queue_create(&msg_queue);
- printf("max msg in pool: %d\n", TOS_CFG_MSG_POOL_SIZE);
- printf("msg queue using TOS_OPT_MSG_PUT_FIFO\n");
- fifo_opt();
- printf("msg queue using TOS_OPT_MSG_PUT_LIFO\n");
- lifo_opt();
- }
- int main(void)
- {
- board_init();
- tos_knl_init();
- (void)tos_task_create(&task_demo, "demo1", entry_task_demo, NULL,
- PRIO_TASK_DEMO, stack_task_demo, STK_SIZE_TASK_DEMO,
- 0);
- tos_knl_start();
- }
运行效果
max msg in pool: 3msg queue using TOS_OPT_MSG_PUT_FIFOmsg put: msg 0msg put: msg 1msg put: msg 2msg queue is fullmsg received: msg 0msg size: 6msg received: msg 1msg size: 6msg received: msg 2msg size: 6msg queue is emptymsg queue using TOS_OPT_MSG_PUT_LIFOmsg put: msg 0msg put: msg 1msg put: msg 2msg queue is fullmsg received: msg 2msg size: 6msg received: msg 1msg size: 6msg received: msg 0msg size: 6msg queue is empty
2.8.2 字符流先入先出队列
概述
字符流先入先出队列,提供的是一个面向字符操作的环形队列实现,提供了基本的字符流入队出队操作。
API讲解
编程实例
1、编写main.c示例代码:
- #include "tos.h"
- #include "mcu_init.h"
- #define STK_SIZE_TASK_DEMO 512
- #define PRIO_TASK_DEMO 4
- k_stack_t stack_task_demo[STK_SIZE_TASK_DEMO];
- k_task_t task_demo;
- #define FIFO_BUFFER_SIZE 5
- uint8_t fifo_buffer[FIFO_BUFFER_SIZE];
- k_fifo_t fifo;
- extern void entry_task_demo(void *arg);
- void char_push(void)
- {
- k_err_t err;
- int i = 0;
- uint8_t data;
- // 往fifo中压入FIFO_BUFFER_SIZE个字符,分别是a、b、c、d、e
- for (i = 0; i < FIFO_BUFFER_SIZE; ++i) {
- printf("char pushed: %c\n", 'a' + i);
- err = tos_fifo_push(&fifo, 'a' + i);
- if (err != K_ERR_NONE) {
- printf("should never happen\n");
- }
- }
- // fifo最多包含FIFO_BUFFER_SIZE个字符,上文逻辑中已经压入了最大的字符量,此时继续压入字符会返回K_ERR_FIFO_FULL(fifo已满)
- err = tos_fifo_push(&fifo, 'z');
- if (err == K_ERR_FIFO_FULL) {
- printf("fifo is full: %s\n", tos_fifo_is_full(&fifo) ? "TRUE" : "FALSE");
- } else {
- printf("should never happen\n");
- }
- // 从fifo中把所有的字符都弹出来
- for (i = 0; i < FIFO_BUFFER_SIZE; ++i) {
- err = tos_fifo_pop(&fifo, &data);
- if (err == K_ERR_NONE) {
- printf("%d pop: %c\n", i, data);
- } else {
- printf("should never happen\n");
- }
- }
- // 此时继续弹出字符,会返回K_ERR_FIFO_EMPTY(fifo已空)
- err = tos_fifo_pop(&fifo, &data);
- if (err == K_ERR_FIFO_EMPTY) {
- printf("fifo is empty: %s\n", tos_fifo_is_empty(&fifo) ? "TRUE" : "FALSE");
- } else {
- printf("should never happen\n");
- }
- }
- void stream_push(void)
- {
- int count = 0, i = 0;
- uint8_t stream[FIFO_BUFFER_SIZE] = { 'a', 'b', 'c', 'd', 'e' };
- uint8_t stream_dummy[1] = { 'z' };
- uint8_t stream_pop[FIFO_BUFFER_SIZE];
- // 压入字符流,字符流的长度是5,不超过fifo的最大长度FIFO_BUFFER_SIZE,会压入成功,并返回压入字符流的长度5
- count = tos_fifo_push_stream(&fifo, &stream[0], FIFO_BUFFER_SIZE);
- if (count != FIFO_BUFFER_SIZE) {
- printf("should never happen\n");
- }
- // 继续压入字符流(即使是长度为1的字符流),因fifo已满无法继续压入,返回长度0(压入失败)
- count = tos_fifo_push_stream(&fifo, &stream_dummy[0], 1);
- if (count == 0) {
- printf("fifo is full: %s\n", tos_fifo_is_full(&fifo) ? "TRUE" : "FALSE");
- } else {
- printf("should never happen\n");
- }
- // 将前文中压入的字符流全部弹出,返回前文压入的字符流长度5(弹出的字符流长度)
- count = tos_fifo_pop_stream(&fifo, &stream_pop[0], FIFO_BUFFER_SIZE);
- if (count == FIFO_BUFFER_SIZE) {
- printf("stream popped:\n");
- for (i = 0; i < FIFO_BUFFER_SIZE; ++i) {
- printf("%c", stream_pop[i]);
- }
- printf("\n");
- } else {
- printf("should never happen\n");
- }
- // 继续弹出,因fifo已空,返回0
- count = tos_fifo_pop_stream(&fifo, &stream_pop[0], 1);
- if (count == 0) {
- printf("fifo is empty: %s\n", tos_fifo_is_empty(&fifo) ? "TRUE" : "FALSE");
- } else {
- printf("should never happen\n");
- }
- }
- void entry_task_demo(void *arg)
- {
- // 创建了一个最多包含FIFO_BUFFER_SIZE个字符的fifo
- tos_fifo_create(&fifo, &fifo_buffer[0], FIFO_BUFFER_SIZE);
- printf("fifo, dealing with char\n");
- char_push();
- printf("fifo, dealing with stream\n");
- stream_push();
- }
- int main(void)
- {
- board_init();
- tos_knl_init();
- (void)tos_task_create(&task_demo, "demo1", entry_task_demo, NULL,
- PRIO_TASK_DEMO, stack_task_demo, STK_SIZE_TASK_DEMO,
- 0);
- tos_knl_start();
- }
运行效果
fifo, dealing with charchar pushed: achar pushed: bchar pushed: cchar pushed: dchar pushed: efifo is full: TRUE0 pop: a1 pop: b2 pop: c3 pop: d4 pop: efifo is empty: TRUEfifo, dealing with streamfifo is full: TRUEstream popped:abcdefifo is empty: TRUE