• FreeRTOS之列表


    1.FreeRTOS的列表和列表项十分重要。列表类相当于链表,列表项则相当于链表中的节点。列表项的地址是非连续的,列表项的数量可随时修改。在OS中的任务状态和数量会发生改变,因此使用列表可以很好的满足需求。

    列表和列表项的相关定义与操作函数都存放在task.h、task.c中。

    (1)列表的定义:

    (2)列表项目的定义:

    迷你列表项:

    2.列表和列表项的关系:

    列表类似于双向循环列表,列表项为其中的节点。每个列表项都有前驱指针指向其上一个节点,每个列表项都有后驱指针指向其后一个节点。同时,末尾的列表项和第一个列表项相连接,形成环路。默认情况下,列表的pxIndex指向末尾列表项,而末尾列表项的xItemValue为最大portMAX_DELAY,此部分的操作在初始化列表时完成。

    3.列表相关的API函数:

    (1)初始化列表函数vListInitialise:

    (2)初始化列表项函数vListInitialiseItem:

    (3)往列表中插入列表项函数vListInsert:

    此方法是按升序的方式将列表项插入到列表中。

    在此函数中会遍历到列表项值小于要插入列表项值的最大列表项,即找到列表项值小于要插入的列表项,并且此列表项的值在所有小于要插入列表项值中是最大的,简单来说按升序进行排列,并插入。

    (4)列表末尾插入函数vListInsertEnd:

    此函数并不是直接将列表项插入到末尾列表项的前面,而是将列表项插入到pxIndex所指向列表的前面

    (5)列表项移除函数uxListRemove:

    此函数是将需要删除的列表项从列表中移除,并返回列表的剩余列表项数量。

    4.代码:本文只展示main.c代码,将本文同前面的FreeRTOS动态创建任务相结合便可以得到完整的代码。

    1. #include "stm32f10x.h"
    2. #include "led.h"
    3. #include "delay.h"
    4. #include "FreeRTOS.h"
    5. #include "task.h"
    6. #include "key.h"
    7. #include "sys.h"
    8. #include "usart.h"
    9. #include "time.h"
    10. //¶¨Òåstart_taskµÄÅäÖã¬ÈÎÎñ¾ä±ú£¬ÈÎÎñÓÅÏȼ¶£¬¶ÑÕ»´óС£¬ÈÎÎñÉùÃ÷£º
    11. #define START_TASK_PRIO 1
    12. #define START_TASK_STACK_SIZE 64
    13. TaskHandle_t start_handler;
    14. void start_task(void);
    15. //¶¨ÒåÈÎÎñ1µÄÅäÖã¬ÈÎÎñ¾ä±ú£¬ÈÎÎñÓÅÏȼ¶£¬¶ÑÕ»´óС£¬ÈÎÎñÉùÃ÷£º
    16. #define TASK1_PRIO 2
    17. #define TASK1_STACK_SIZE 64
    18. TaskHandle_t task1_handler;
    19. void task1(void);
    20. //¶¨ÒåÈÎÎñ2µÄÅäÖã¬ÈÎÎñ¾ä±ú£¬ÈÎÎñÓÅÏȼ¶£¬¶ÑÕ»´óС£¬ÈÎÎñÉùÃ÷£º
    21. #define TASK2_PRIO 3
    22. #define TASK2_STACK_SIZE 64
    23. TaskHandle_t task2_handler;
    24. void task2(void);
    25. List_t TestList; //´´½¨Áбí
    26. ListItem_t ListItem1; //´´½¨ÁбíÏî1
    27. ListItem_t ListItem2; //´´½¨ÁбíÏî2
    28. ListItem_t ListItem3; //´´½¨ÁбíÏî3
    29. int flag = 0;
    30. int main(void)
    31. {
    32. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);// ÉèÖÃÖжÏÓÅÏȼ¶·Ö×é4,×ÓÓÅÏȼ¶Îª0
    33. LED_Init();
    34. KEY_Init();
    35. delay_init();
    36. usart_init(9600);
    37. xTaskCreate((TaskFunction_t) start_task, //ÈÎÎñº¯Êý
    38. (const char *)"start_task", //ÈÎÎñÃû³Æ
    39. (uint16_t)START_TASK_STACK_SIZE, //ÈÎÎñ¶ÑÕ»´óС
    40. (void *)NULL, //´«µÝ¸øÈÎÎñº¯ÊýµÄ²ÎÊý
    41. (UBaseType_t)START_TASK_PRIO, //ÈÎÎñÓÅÏȼ¶
    42. (TaskHandle_t *)&start_handler); //ÈÎÎñ¾ä±ú
    43. vTaskStartScheduler(); //¿ªÊ¼ÈÎÎñµ÷¶È
    44. }
    45. /*´´½¨¿ªÊ¼ÈÎÎñ£º*/
    46. void start_task(void)
    47. {
    48. // taskENTER_CRITICAL();
    49. /*´´½¨ÈÎÎñ*/
    50. if(flag == 0)
    51. {
    52. xTaskCreate((TaskFunction_t) task1, //ÈÎÎñº¯Êý
    53. (const char *)"task1", //ÈÎÎñÃû³Æ
    54. (uint16_t)TASK1_STACK_SIZE, //ÈÎÎñ¶ÑÕ»´óС
    55. (void *)NULL, //´«µÝ¸øÈÎÎñº¯ÊýµÄ²ÎÊý
    56. (UBaseType_t)TASK1_PRIO, //ÈÎÎñÓÅÏȼ¶
    57. (TaskHandle_t *)&task1_handler); //ÈÎÎñ¾ä±ú
    58. xTaskCreate((TaskFunction_t) task2, //ÈÎÎñº¯Êý
    59. (const char *)"task2", //ÈÎÎñÃû³Æ
    60. (uint16_t)TASK2_STACK_SIZE, //ÈÎÎñ¶ÑÕ»´óС
    61. (void *)NULL, //´«µÝ¸øÈÎÎñº¯ÊýµÄ²ÎÊý
    62. (UBaseType_t)TASK2_PRIO, //ÈÎÎñÓÅÏȼ¶
    63. (TaskHandle_t *)&task2_handler); //ÈÎÎñ¾ä±ú
    64. flag = 1;
    65. }
    66. vTaskDelay(500);
    67. vTaskDelete(NULL); //ɾ³ýµ±Ç°ÈÎÎñ
    68. // taskEXIT_CRITICAL();
    69. }
    70. void task1(void)
    71. {
    72. while(1)
    73. {
    74. /*LEDÉÁ˸*/
    75. GPIO_ResetBits(GPIOA,GPIO_Pin_8);
    76. GPIO_ResetBits(GPIOD,GPIO_Pin_2);
    77. vTaskDelay(500);
    78. GPIO_SetBits(GPIOA,GPIO_Pin_8);
    79. GPIO_SetBits(GPIOD,GPIO_Pin_2);
    80. vTaskDelay(500);
    81. }
    82. }
    83. void task2(void)
    84. {
    85. /*³õʼ»¯ÁбíºÍÁбíÏî*/
    86. vListInitialise(&TestList);
    87. vListInitialiseItem(&ListItem1);
    88. vListInitialiseItem(&ListItem2);
    89. vListInitialiseItem(&ListItem3);
    90. ListItem1.xItemValue = 40;
    91. ListItem2.xItemValue = 60;
    92. ListItem3.xItemValue = 50;
    93. printf("********´òÓ¡ÁбíºÍÁбíÏîµØÖ·********\r\n");
    94. printf("TestList 0x%p \r\n",&TestList);
    95. printf("TestList->pxIndex 0x%p \r\n",(TestList.pxIndex));
    96. printf("TestList->xListEnd 0x%p \r\n",&(TestList.xListEnd));
    97. printf("ListItem1 0x%p \r\n",&ListItem1);
    98. printf("ListItem2 0x%p \r\n",&ListItem2);
    99. printf("ListItem3 0x%p \r\n",&ListItem3);
    100. printf("****************½áÊø****************\r\n");
    101. printf("\r\n");
    102. // /*²åÈëÁбíÏî1£º*/
    103. vListInsert(&TestList,&ListItem1);
    104. // printf("TestList->xListEnd->pxNext 0x%p \r\n",(int)(TestList.xListEnd.pxNext));
    105. // printf("ListItem1->pxNext 0x%p \r\n",(int)ListItem1.pxNext);
    106. // printf("TestList->xListEnd->pxPrevious 0x%p \r\n",(int)(TestList.xListEnd.pxPrevious));
    107. // printf("ListItem1->pxPrevious 0x%p \r\n",(int)ListItem1.pxPrevious);
    108. // printf("\r\n");
    109. // /*²åÈëÁбíÏî2£º*/
    110. vListInsert(&TestList,&ListItem2);
    111. // printf("TestList->xListEnd->pxNext 0x%p \r\n",(int)(TestList.xListEnd.pxNext));
    112. // printf("ListItem1->pxNext 0x%p \r\n",(int)ListItem1.pxNext);
    113. // printf("ListItem2->pxNext 0x%p \r\n",(int)ListItem2.pxNext);
    114. // printf("TestList->xListEnd->pxPrevious 0x%p \r\n",(int)(TestList.xListEnd.pxPrevious));
    115. // printf("ListItem1->pxPrevious 0x%p \r\n",(int)ListItem1.pxPrevious);
    116. // printf("ListItem2->pxPrevious 0x%p \r\n",(int)ListItem2.pxPrevious);
    117. printf("\r\n");
    118. /*²åÈëÁбíÏî3£º*/
    119. vListInsert(&TestList,&ListItem3);
    120. // printf("TestList->xListEnd->pxNext 0x%p \r\n",(int)(TestList.xListEnd.pxNext));
    121. // printf("ListItem1->pxNext 0x%p \r\n",(int)ListItem1.pxNext);
    122. // printf("ListItem2->pxNext 0x%p \r\n",(int)ListItem2.pxNext);
    123. // printf("ListItem3->pxNext 0x%p \r\n",(int)ListItem3.pxNext);
    124. // printf("TestList->xListEnd->pxPrevious 0x%p \r\n",(int)(TestList.xListEnd.pxPrevious));
    125. // printf("ListItem1->pxPrevious 0x%p \r\n",(int)ListItem1.pxPrevious);
    126. // printf("ListItem2->pxPrevious 0x%p \r\n",(int)ListItem2.pxPrevious);
    127. // printf("ListItem3->pxPrevious 0x%p \r\n",(int)ListItem3.pxPrevious);
    128. printf("\r\n");
    129. /*ɾ³ýÁбíÏî3£º*/
    130. uxListRemove(&ListItem3);
    131. printf("TestList->xListEnd->pxNext 0x%p \r\n",(TestList.xListEnd.pxNext));
    132. printf("ListItem1->pxNext 0x%p \r\n",ListItem1.pxNext);
    133. printf("ListItem2->pxNext 0x%p \r\n",ListItem2.pxNext);
    134. //printf("ListItem3->pxNext 0x%p \r\n",(int)ListItem3.pxNext);
    135. printf("TestList->xListEnd->pxPrevious 0x%p \r\n",(TestList.xListEnd.pxPrevious));
    136. printf("ListItem1->pxPrevious 0x%p \r\n",ListItem1.pxPrevious);
    137. printf("ListItem2->pxPrevious 0x%p \r\n",ListItem2.pxPrevious);
    138. //printf("ListItem3->pxPrevious 0x%p \r\n",(int)ListItem3.pxPrevious);
    139. printf("\r\n");
    140. /*β²åÈëÁбíÏî3£º*/
    141. vListInsertEnd(&TestList,&ListItem3);
    142. printf("TestList->xListEnd->pxNext 0x%p \r\n",(TestList.xListEnd.pxNext));
    143. printf("ListItem1->pxNext 0x%p \r\n",ListItem1.pxNext);
    144. printf("ListItem2->pxNext 0x%p \r\n",ListItem2.pxNext);
    145. printf("ListItem3->pxNext 0x%p \r\n",ListItem3.pxNext);
    146. printf("TestList->xListEnd->pxPrevious 0x%p \r\n",(TestList.xListEnd.pxPrevious));
    147. printf("ListItem1->pxPrevious 0x%p \r\n",ListItem1.pxPrevious);
    148. printf("ListItem2->pxPrevious 0x%p \r\n",ListItem2.pxPrevious);
    149. printf("ListItem3->pxPrevious 0x%p \r\n",ListItem3.pxPrevious);
    150. }

    5.运行结果:

    6.总结:

    本文介绍了FreeRTOS中的列表和列表项的定义,以及列表与列表项的相关操作函数。在理解的时,可以将列表当作双向循环列表,将列表项当作其中的节点。

    列表在FreeRTOS中十分重要,比如FreeRTOSD有三个和任务相关的列表:就绪列表、阻塞列表、挂起列表。当将任务从阻塞状态变成就绪状态时,需要先将列表项对应的任务从阻塞列表中删除,然后再插入到就绪列表中。

    下图为任务的状态图:

    其中,运行、就绪、阻塞态和挂起态的定义是:

    (1)运行态:当前正在运行的任务便处于运行态。

    (2)就绪态:处于就绪态的任务是那些已经准备就绪(这些任务没有被阻塞或者挂起),可以运行的任务, 但是处于就绪态的任务还没有运行,因为有一个同优先级或者更高优先级的任务正在运行!

    (3)阻塞态:如果一个任务当前正在等待某个外部事件的便处于阻塞态,比如如果某个任务调用了函数 vTaskDelay()的话就会进入阻塞态,直到延时周期完成。任务在等待队列、信号量、事 件组、通知或互斥信号量的时候也会进入阻塞态。任务进入阻塞态会有一个超时时间,当超过 这个超时时间任务就会退出阻塞态,即使所等待的事件还没有来临!

    (4)挂起态:挂起态和阻塞态都无法被任务调度器调用进入运行态,但是,挂起的任务没有超时时间。挂起任务函数为vTaskSuspend(),推出挂起函数为xTaskResume()。

  • 相关阅读:
    Linux——IP协议1
    vue中禁止ios浏览器页面滚动的橡皮筋效果
    LVS-NAT模式【案例实验】
    Consul安装配置
    R语言使用plot函数可视化数据散点图,通过xlim参数指定X轴的坐标范围(x axis limits)
    SpringBoot面试
    freemarker+yml介绍 以及freemarker与JSP的区别
    CTF-FTP后门利用【简单易懂】
    《C和指针》笔记31:多维数组的数组名、指向多维数组的指针、作为函数参数的多维数组
    java-php-python-ssm网上拍卖系统2021计算机毕业设计
  • 原文地址:https://blog.csdn.net/qq_43213240/article/details/138197287