• 2.8 内核基础组件
    • 2.8.1 消息队列
      • 概述
      • API讲解
      • 编程实例
      • 运行效果
    • 2.8.2 字符流先入先出队列
      • 概述
      • API讲解
      • 编程实例
      • 运行效果

    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

    实例代码