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示例代码:

  1. #include "tos.h"
  2. #include "mcu_init.h"
  3.  
  4. #define STK_SIZE_TASK_DEMO 512
  5.  
  6. #define PRIO_TASK_DEMO 4
  7.  
  8. k_stack_t stack_task_demo[STK_SIZE_TASK_DEMO];
  9.  
  10. k_task_t task_demo;
  11.  
  12. k_msg_queue_t msg_queue;
  13.  
  14. struct msg_st {
  15. char *msg;
  16. size_t size;
  17. } msgs[TOS_CFG_MSG_POOL_SIZE] = {
  18. { "msg 0", 6 },
  19. { "msg 1", 6 },
  20. { "msg 2", 6 },
  21. };
  22.  
  23. struct msg_st dummy_msg = { "dummy msg", 10 };
  24.  
  25. extern void entry_task_demo(void *arg);
  26.  
  27. void fifo_opt(void) {
  28. k_err_t err;
  29. int i = 0;
  30. char *msg_received = K_NULL;
  31. size_t msg_size = 0;
  32.  
  33. for (; i < TOS_CFG_MSG_POOL_SIZE; ++i) {
  34. printf("msg put: %s\n", msgs[i].msg);
  35. err = tos_msg_queue_put(&msg_queue, (void *)msgs[i].msg, msgs[i].size, TOS_OPT_MSG_PUT_FIFO);
  36. if (err != K_ERR_NONE) {
  37. printf("should never happen\n");
  38. }
  39. }
  40.  
  41. err = tos_msg_queue_put(&msg_queue, (void *)dummy_msg.msg, dummy_msg.size, TOS_OPT_MSG_PUT_FIFO);
  42. if (err == K_ERR_MSG_QUEUE_FULL) {
  43. printf("msg queue is full\n");
  44. } else {
  45. printf("should never happen\n");
  46. }
  47.  
  48. for (i = 0; i < TOS_CFG_MSG_POOL_SIZE; ++i) {
  49. err = tos_msg_queue_get(&msg_queue, (void **)&msg_received, &msg_size);
  50. if (err == K_ERR_NONE) {
  51. printf("msg received: %s\n", msg_received);
  52. printf("msg size: %d\n", msg_size);
  53. } else {
  54. printf("should never happen\n");
  55. }
  56. }
  57. err = tos_msg_queue_get(&msg_queue, (void **)&msg_received, &msg_size);
  58. if (err == K_ERR_MSG_QUEUE_EMPTY) {
  59. printf("msg queue is empty\n");
  60. } else {
  61. printf("should never happen\n");
  62. }
  63. }
  64.  
  65. void lifo_opt(void) {
  66. k_err_t err;
  67. int i = 0;
  68. char *msg_received = K_NULL;
  69. size_t msg_size = 0;
  70.  
  71. for (; i < TOS_CFG_MSG_POOL_SIZE; ++i) {
  72. printf("msg put: %s\n", msgs[i].msg);
  73. err = tos_msg_queue_put(&msg_queue, (void *)msgs[i].msg, msgs[i].size, TOS_OPT_MSG_PUT_LIFO);
  74. if (err != K_ERR_NONE) {
  75. printf("should never happen\n");
  76. }
  77. }
  78. err = tos_msg_queue_put(&msg_queue, (void *)dummy_msg.msg, dummy_msg.size, TOS_OPT_MSG_PUT_LIFO);
  79. if (err == K_ERR_MSG_QUEUE_FULL) {
  80. printf("msg queue is full\n");
  81. } else {
  82. printf("should never happen\n");
  83. }
  84.  
  85. for (i = 0; i < TOS_CFG_MSG_POOL_SIZE; ++i) {
  86. err = tos_msg_queue_get(&msg_queue, (void **)&msg_received, &msg_size);
  87. if (err == K_ERR_NONE) {
  88. printf("msg received: %s\n", msg_received);
  89. printf("msg size: %d\n", msg_size);
  90. } else {
  91. printf("should never happen\n");
  92. }
  93. }
  94. err = tos_msg_queue_get(&msg_queue, (void **)&msg_received, &msg_size);
  95. if (err == K_ERR_MSG_QUEUE_EMPTY) {
  96. printf("msg queue is empty\n");
  97. } else {
  98. printf("should never happen\n");
  99. }
  100. }
  101.  
  102. void entry_task_demo(void *arg)
  103. {
  104. tos_msg_queue_create(&msg_queue);
  105.  
  106. printf("max msg in pool: %d\n", TOS_CFG_MSG_POOL_SIZE);
  107. printf("msg queue using TOS_OPT_MSG_PUT_FIFO\n");
  108. fifo_opt();
  109.  
  110. printf("msg queue using TOS_OPT_MSG_PUT_LIFO\n");
  111. lifo_opt();
  112. }
  113.  
  114. int main(void)
  115. {
  116. board_init();
  117. tos_knl_init();
  118. (void)tos_task_create(&task_demo, "demo1", entry_task_demo, NULL,
  119. PRIO_TASK_DEMO, stack_task_demo, STK_SIZE_TASK_DEMO,
  120. 0);
  121. tos_knl_start();
  122. }
运行效果

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示例代码:

  1. #include "tos.h"
  2. #include "mcu_init.h"
  3.  
  4. #define STK_SIZE_TASK_DEMO 512
  5.  
  6. #define PRIO_TASK_DEMO 4
  7.  
  8. k_stack_t stack_task_demo[STK_SIZE_TASK_DEMO];
  9.  
  10. k_task_t task_demo;
  11.  
  12. #define FIFO_BUFFER_SIZE 5
  13. uint8_t fifo_buffer[FIFO_BUFFER_SIZE];
  14.  
  15. k_fifo_t fifo;
  16.  
  17. extern void entry_task_demo(void *arg);
  18.  
  19. void char_push(void)
  20. {
  21. k_err_t err;
  22. int i = 0;
  23. uint8_t data;
  24.  
  25. // 往fifo中压入FIFO_BUFFER_SIZE个字符,分别是a、b、c、d、e
  26. for (i = 0; i < FIFO_BUFFER_SIZE; ++i) {
  27. printf("char pushed: %c\n", 'a' + i);
  28. err = tos_fifo_push(&fifo, 'a' + i);
  29. if (err != K_ERR_NONE) {
  30. printf("should never happen\n");
  31. }
  32. }
  33.  
  34. // fifo最多包含FIFO_BUFFER_SIZE个字符,上文逻辑中已经压入了最大的字符量,此时继续压入字符会返回K_ERR_FIFO_FULL(fifo已满)
  35. err = tos_fifo_push(&fifo, 'z');
  36. if (err == K_ERR_FIFO_FULL) {
  37. printf("fifo is full: %s\n", tos_fifo_is_full(&fifo) ? "TRUE" : "FALSE");
  38. } else {
  39. printf("should never happen\n");
  40. }
  41.  
  42. // 从fifo中把所有的字符都弹出来
  43. for (i = 0; i < FIFO_BUFFER_SIZE; ++i) {
  44. err = tos_fifo_pop(&fifo, &data);
  45. if (err == K_ERR_NONE) {
  46. printf("%d pop: %c\n", i, data);
  47. } else {
  48. printf("should never happen\n");
  49. }
  50. }
  51. // 此时继续弹出字符,会返回K_ERR_FIFO_EMPTY(fifo已空)
  52. err = tos_fifo_pop(&fifo, &data);
  53. if (err == K_ERR_FIFO_EMPTY) {
  54. printf("fifo is empty: %s\n", tos_fifo_is_empty(&fifo) ? "TRUE" : "FALSE");
  55. } else {
  56. printf("should never happen\n");
  57. }
  58. }
  59.  
  60. void stream_push(void)
  61. {
  62. int count = 0, i = 0;
  63. uint8_t stream[FIFO_BUFFER_SIZE] = { 'a', 'b', 'c', 'd', 'e' };
  64. uint8_t stream_dummy[1] = { 'z' };
  65. uint8_t stream_pop[FIFO_BUFFER_SIZE];
  66.  
  67. // 压入字符流,字符流的长度是5,不超过fifo的最大长度FIFO_BUFFER_SIZE,会压入成功,并返回压入字符流的长度5
  68. count = tos_fifo_push_stream(&fifo, &stream[0], FIFO_BUFFER_SIZE);
  69. if (count != FIFO_BUFFER_SIZE) {
  70. printf("should never happen\n");
  71. }
  72.  
  73. // 继续压入字符流(即使是长度为1的字符流),因fifo已满无法继续压入,返回长度0(压入失败)
  74. count = tos_fifo_push_stream(&fifo, &stream_dummy[0], 1);
  75. if (count == 0) {
  76. printf("fifo is full: %s\n", tos_fifo_is_full(&fifo) ? "TRUE" : "FALSE");
  77. } else {
  78. printf("should never happen\n");
  79. }
  80.  
  81. // 将前文中压入的字符流全部弹出,返回前文压入的字符流长度5(弹出的字符流长度)
  82. count = tos_fifo_pop_stream(&fifo, &stream_pop[0], FIFO_BUFFER_SIZE);
  83. if (count == FIFO_BUFFER_SIZE) {
  84. printf("stream popped:\n");
  85. for (i = 0; i < FIFO_BUFFER_SIZE; ++i) {
  86. printf("%c", stream_pop[i]);
  87. }
  88. printf("\n");
  89. } else {
  90. printf("should never happen\n");
  91. }
  92.  
  93. // 继续弹出,因fifo已空,返回0
  94. count = tos_fifo_pop_stream(&fifo, &stream_pop[0], 1);
  95. if (count == 0) {
  96. printf("fifo is empty: %s\n", tos_fifo_is_empty(&fifo) ? "TRUE" : "FALSE");
  97. } else {
  98. printf("should never happen\n");
  99. }
  100. }
  101.  
  102. void entry_task_demo(void *arg)
  103. {
  104. // 创建了一个最多包含FIFO_BUFFER_SIZE个字符的fifo
  105. tos_fifo_create(&fifo, &fifo_buffer[0], FIFO_BUFFER_SIZE);
  106.  
  107. printf("fifo, dealing with char\n");
  108. char_push();
  109.  
  110. printf("fifo, dealing with stream\n");
  111. stream_push();
  112. }
  113.  
  114. int main(void)
  115. {
  116. board_init();
  117. tos_knl_init();
  118. (void)tos_task_create(&task_demo, "demo1", entry_task_demo, NULL,
  119. PRIO_TASK_DEMO, stack_task_demo, STK_SIZE_TASK_DEMO,
  120. 0);
  121. tos_knl_start();
  122. }
运行效果

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

实例代码