摘要:聲明本專欄參考韋東山,野火,正點原子以及其他博主的教程,如若侵權請告知,馬上刪帖致歉,個人總結,如有不對,歡迎指正。
聲明:本專欄參考韋東山,野火,正點原子以及其他博主的FreeRTOS教程,如若侵權請告知,馬上刪帖致歉,個人總結,如有不對,歡迎指正。
還是來看看同步實驗怎么做吧
/** FreeRTOS v9.0.0 + STM32 動態創建任務 實驗平臺:韋東山 STM32F103ZE開發板 **/ #include "FreeRTOS.h"#include "task.h"#include "queue.h"/* 開發板硬件bsp頭文件 */#include "bsp_led.h"#include "bsp_usart.h"/* 任務句柄 */static TaskHandle_t AppTaskCreate_Handle = NULL;static TaskHandle_t Task1_Handle = NULL;static TaskHandle_t Task2_Handle = NULL;static TaskHandle_t Task3_Handle = NULL;static xQueueHandle MsgQueue; /*隊列句柄*//* 函數聲明 */static void AppTaskCreate(void);/* 用于創建任務 */static void Flag1_Task(void* pvParameters);/* LED1_Task任務實現 */static void Flag2_Task(void* pvParameters);/* LED2_Task任務實現 */static void Flag3_Task(void* pvParameters);/* LED3_Task任務實現 */static void BSP_Init(void);/* 用于初始化板載相關資源 *//***************************************************************** * @brief 主函數 * @param 無 * @retval 無 * @note 第一步:開發板硬件初始化 第二步:創建APP應用任務 第三步:啟動FreeRTOS,開始多任務調度 ****************************************************************/int main(void){ BaseType_t xReturn = pdPASS;/* 定義一個創建信息返回值,默認為pdPASS */ /* 開發板硬件初始化 */ BSP_Init(); printf("這是一個STM32F103ZE開發板-FreeRTOS-動態創建任務!/r/n"); MsgQueue=xQueueCreate(1,sizeof(int));/*創建隊列:參數,隊列長度,每個長度大小(字節)*/ /* 創建AppTaskCreate任務 */ xReturn = xTaskCreate((TaskFunction_t )AppTaskCreate, /* 任務入口函數 */ (const char* )"AppTaskCreate",/* 任務名字 */ (uint16_t )512, /* 任務棧大小 */ (void* )NULL,/* 任務入口函數參數 */ (UBaseType_t )1, /* 任務的優先級 */ (TaskHandle_t* )&AppTaskCreate_Handle);/* 任務控制塊指針 */ /* 啟動任務調度 */ if(pdPASS == xReturn) vTaskStartScheduler(); /* 啟動任務,開啟調度 */ else return -1; while(1); /* 正常不會執行到這里 */ }/*********************************************************************** * @ 函數名 : AppTaskCreate * @ 功能說明: 為了方便管理,所有的任務創建函數都放在這個函數里面 * @ 參數 : 無 * @ 返回值 : 無 **********************************************************************/static void AppTaskCreate(void){ BaseType_t xReturn = pdPASS;/* 定義一個創建信息返回值,默認為pdPASS */ taskENTER_CRITICAL(); //進入臨界區 /* 創建Flag1_Task任務 */ xReturn = xTaskCreate((TaskFunction_t )Flag1_Task, /* 任務入口函數 */ (const char* )"Flag1_Task",/* 任務名字 */ (uint16_t )512, /* 任務棧大小 */ (void* )NULL, /* 任務入口函數參數 */ (UBaseType_t )2, /* 任務的優先級 */ (TaskHandle_t* )&Task1_Handle);/* 任務控制塊指針 */ if(pdPASS == xReturn) printf("創建Flag1_Task任務成功!/r/n"); /* 創建Flag2_Task任務 */ xReturn = xTaskCreate((TaskFunction_t )Flag2_Task, /* 任務入口函數 */ (const char* )"Flag2_Task",/* 任務名字 */ (uint16_t )512, /* 任務棧大小 */ (void* )NULL, /* 任務入口函數參數 */ (UBaseType_t )2, /* 任務的優先級 */ (TaskHandle_t* )&Task2_Handle);/* 任務控制塊指針 */ if(pdPASS == xReturn) printf("創建Flag2_Task任務成功!/r/n"); /* 創建Flag3_Task任務 */ xReturn = xTaskCreate((TaskFunction_t )Flag3_Task, /* 任務入口函數 */ (const char* )"Flag3_Task",/* 任務名字 */ (uint16_t )512, /* 任務棧大小 */ (void* )NULL, /* 任務入口函數參數 */ (UBaseType_t )1, /* 任務的優先級 */ (TaskHandle_t* )&Task3_Handle);/* 任務控制塊指針 */ if(pdPASS == xReturn) printf("創建Flag3_Task任務成功!/r/n"); vTaskDelete(AppTaskCreate_Handle); //刪除AppTaskCreate任務 taskEXIT_CRITICAL(); //退出臨界區}/********************************************************************** * @ 函數名 : LED_Task * @ 功能說明: LED_Task任務主體 ********************************************************************/uint8_t flag1;uint8_t flag2;uint8_t flag3;/*優先級2*/static void Flag1_Task(void* parameter){ static int value,i; while (1) { for(i=10000;i>1;i--) flag1=1; flag2=0; flag3=0; /* 向隊列中填充內容 */ value++; printf("Task1 Running! value=%d/r/n",value); xQueueSend( MsgQueue, ( void* )&value, queueSEND_TO_BACK); /*發送隊列消息,*/ // vTaskDelay(10); /* 延時1個tick */ }}/*優先級2*/static void Flag2_Task(void* parameter){ static int value1; while (1) { /*如果讀取到隊列消息*/ if(xQueueReceive(MsgQueue,(void *)&value1,pdFALSE)==pdPASS) { flag1=0; flag2=1; flag3=0; printf("Task2 Running! value=%d/r/n",value1);/*將讀取到的數值打印出來*/ } //vTaskDelay(10); /* 延時1個tick */ }}/*優先級2*/static void Flag3_Task(void* parameter){ static int value2; while (1) { flag1=0; flag2=0; flag3=1; printf("Task3 Running! value=%d/r/n",value2); vTaskDelay(10); /* 延時1個tick */ }}/*********************************************************************** * @ 函數名 : BSP_Init * @ 功能說明: 板級外設初始化,所有板子上的初始化均可放在這個函數里面 * @ 參數 : * @ 返回值 : 無 *********************************************************************/static void BSP_Init(void){ /* * STM32中斷優先級分組為4,即4bit都用來表示搶占優先級,范圍為:0~15 * 優先級分組只需要分組一次即可,以后如果有其他的任務需要用到中斷, * 都統一用這個優先級分組,千萬不要再分組,切忌。 */ NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 ); /* LED 初始化 */ LED_GPIO_Config(); /* 串口初始化 */ USART_Config(); }/********************************END OF FILE****************************/
創建三個任務,優先級為321,
xQueueCreate();
flag1Task
flag2Task
flag3Task
根據以上信息可以猜想任務運行過程是怎樣的???
任務一和任務二在執行過程中都沒有進入到阻塞狀態,任務3的優先級是要比任務一和任務二要低的,所以任務三肯定不會運行,那么任務一和任務二相同優先級要如何運行呢??
直接仿真看看
神奇的是串口居然不亂了,任務一先運行,接著任務二打印了信息,這就是通過隊列傳遞信息來實現任務同步
再來做個實驗看看任務互斥
/** FreeRTOS v9.0.0 + STM32 動態創建任務 實驗平臺:韋東山 STM32F103ZE開發板 **/ #include "FreeRTOS.h"#include "task.h"#include "queue.h"/* 開發板硬件bsp頭文件 */#include "bsp_led.h"#include "bsp_usart.h"/* 任務句柄 */static TaskHandle_t AppTaskCreate_Handle = NULL;static TaskHandle_t Task1_Handle = NULL;static TaskHandle_t Task2_Handle = NULL;//static TaskHandle_t Task3_Handle = NULL;//static QueueHandle_t xQueueCalcHandle;static QueueHandle_t xQueueUARTcHandle;/* 函數聲明 */static void AppTaskCreate(void);/* 用于創建任務 */static void Flag1_Task(void* pvParameters);/* LED1_Task任務實現 */static void Flag2_Task(void* pvParameters);/* LED2_Task任務實現 *///static void Flag3_Task(void* pvParameters);/* LED3_Task任務實現 */static void BSP_Init(void);/* 用于初始化板載相關資源 *//*創建隊列*/int InitUARTLock(void){ int val; xQueueUARTcHandle = xQueueCreate(1, sizeof(int));/*創建隊列*/ if (xQueueUARTcHandle == NULL) { printf("can not create queue/r/n"); return -1;/*創建失敗*/ } xQueueSend(xQueueUARTcHandle, &val, portMAX_DELAY);/*死等*/ return 0;/*創建成功*/}/*接收隊列消息*/void GetUARTLock(void){ int val; xQueueReceive(xQueueUARTcHandle, &val, portMAX_DELAY);}/*發送隊列消息*/void PutUARTLock(void){ int val; xQueueSend(xQueueUARTcHandle, &val, portMAX_DELAY);}/***************************************************************** * @brief 主函數 * @param 無 * @retval 無 * @note 第一步:開發板硬件初始化 第二步:創建APP應用任務 第三步:啟動FreeRTOS,開始多任務調度 ****************************************************************/int main(void){ BaseType_t xReturn = pdPASS;/* 定義一個創建信息返回值,默認為pdPASS */ /* 開發板硬件初始化 */ BSP_Init(); printf("這是一個STM32F103ZE開發板-FreeRTOS-動態創建任務!/r/n"); InitUARTLock();/*調用創建隊列函數*/ /* 創建AppTaskCreate任務 */ xReturn = xTaskCreate((TaskFunction_t )AppTaskCreate, /* 任務入口函數 */ (const char* )"AppTaskCreate",/* 任務名字 */ (uint16_t )512, /* 任務棧大小 */ (void* )NULL,/* 任務入口函數參數 */ (UBaseType_t )1, /* 任務的優先級 */ (TaskHandle_t* )&AppTaskCreate_Handle);/* 任務控制塊指針 */ /* 啟動任務調度 */ if(pdPASS == xReturn) vTaskStartScheduler(); /* 啟動任務,開啟調度 */ else return -1; while(1); /* 正常不會執行到這里 */ }/*********************************************************************** * @ 函數名 : AppTaskCreate * @ 功能說明: 為了方便管理,所有的任務創建函數都放在這個函數里面 * @ 參數 : 無 * @ 返回值 : 無 **********************************************************************/static void AppTaskCreate(void){ BaseType_t xReturn = pdPASS;/* 定義一個創建信息返回值,默認為pdPASS */ taskENTER_CRITICAL(); //進入臨界區 /* 創建Flag1_Task任務 */ xReturn = xTaskCreate((TaskFunction_t )Flag1_Task, /* 任務入口函數 */ (const char* )"Flag1_Task",/* 任務名字 */ (uint16_t )512, /* 任務棧大小 */ (void* )NULL, /* 任務入口函數參數 */ (UBaseType_t )2, /* 任務的優先級 */ (TaskHandle_t* )&Task1_Handle);/* 任務控制塊指針 */ if(pdPASS == xReturn) printf("創建Flag1_Task任務成功!/r/n"); /* 創建Flag2_Task任務 */ xReturn = xTaskCreate((TaskFunction_t )Flag2_Task, /* 任務入口函數 */ (const char* )"Flag2_Task",/* 任務名字 */ (uint16_t )512, /* 任務棧大小 */ (void* )NULL, /* 任務入口函數參數 */ (UBaseType_t )2, /* 任務的優先級 */ (TaskHandle_t* )&Task2_Handle);/* 任務控制塊指針 */ if(pdPASS == xReturn) printf("創建Flag2_Task任務成功!/r/n"); /* 創建Flag3_Task任務 */// xReturn = xTaskCreate((TaskFunction_t )Flag3_Task, /* 任務入口函數 */// (const char* )"Flag3_Task",/* 任務名字 */// (uint16_t )512, /* 任務棧大小 */// (void* )NULL, /* 任務入口函數參數 */// (UBaseType_t )1, /* 任務的優先級 */// (TaskHandle_t* )&Task3_Handle);/* 任務控制塊指針 */// if(pdPASS == xReturn)// printf("創建Flag3_Task任務成功!/r/n"); vTaskDelete(AppTaskCreate_Handle); //刪除AppTaskCreate任務 taskEXIT_CRITICAL(); //退出臨界區}/********************************************************************** * @ 函數名 : LED_Task * @ 功能說明: LED_Task任務主體 ********************************************************************/uint8_t flag1;uint8_t flag2;uint8_t flag3;/*優先級2*/static void Flag1_Task(void* parameter){ while (1) { GetUARTLock();/*調用接收消息函數獲得使用權*/ printf("Task1 Running!/r/n"); PutUARTLock();/*調用發送消息函數釋放使用權*/ vTaskDelay(1); /* 延時1個tick */ }}/*優先級2*/static void Flag2_Task(void* parameter){ while (1) { GetUARTLock();/*調用接收消息函數獲得使用權*/ printf("Task2 Running!/r/n"); PutUARTLock();/*調用發送消息函數釋放使用權*/ vTaskDelay(1); /* 延時1個tick */ }}/*優先級1*///static void Flag3_Task(void* parameter)//{// static int value2;// while (1)// {// flag1=0;// flag2=0;// flag3=1;// printf("Task3 Running! value=%d/r/n",value2);// vTaskDelay(10); /* 延時1個tick */ // // }//}/*********************************************************************** * @ 函數名 : BSP_Init * @ 功能說明: 板級外設初始化,所有板子上的初始化均可放在這個函數里面 * @ 參數 : * @ 返回值 : 無 *********************************************************************/static void BSP_Init(void){ /* * STM32中斷優先級分組為4,即4bit都用來表示搶占優先級,范圍為:0~15 * 優先級分組只需要分組一次即可,以后如果有其他的任務需要用到中斷, * 都統一用這個優先級分組,千萬不要再分組,切忌。 */ NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 ); /* LED 初始化 */ LED_GPIO_Config(); /* 串口初始化 */ USART_Config(); }/********************************END OF FILE****************************/
這次實驗創建了兩個任務,任務優先級相同都為2
創建這幾個函數
在任務處理事件中,像臨界保護一樣進行首先調用接收消息的函數獲得使用權,再調用發送消息函數釋放使用權。(隊列里面有數據表示別人可以讀這個隊列)
仿真來看看實驗效果
git倉庫源碼地址:https://gitee.com/he-dejiang/free-rtos.git
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/121365.html
摘要:請參看前一篇文章并發學習筆記一原子性可見性有序性問題六等待通知機制什么是等待通知機制當線程不滿足某個條件,則進入等待狀態如果線程滿足要求的某個條件后,則通知等待的線程重新執行。經極客時間并發編程實戰專欄內容學習整理 請參看前一篇文章:Java 并發學習筆記(一)——原子性、可見性、有序性問題 六、等待—通知機制 什么是等待通知—機制?當線程不滿足某個條件,則進入等待狀態;如果線程滿足要...
摘要:相比之下,物聯網操作系統領域的碎片化問題則非常嚴重,并沒有哪幾個操作系統占據絕對優勢,正處于百花齊放百家爭鳴的階段。在年被公司正式收購,將自己的服務內嵌到系統中,并于年推出了集成無線連接安全等功能的物聯網操作系統。 物聯網操作系統是運行在物聯網設備上的提供物物相連能力的操作系統,其核心在于...
摘要:工作線程執行異步任務,執行完成后把對應額回調函數封裝成一條消息放到消息隊列中主線程不斷地從消息隊列中取消息并執行。當消息隊列為空時,主線程阻塞,直到消息隊列再次非空。取決于何時被主線程的事件循環取到,并執行。 轉自:http://palmer.arkstack.cn/201...一:平時簡單使用 1.setTimeout延遲一段時間執行一次(only one) setTimeout(f...
閱讀 1707·2023-04-26 02:30
閱讀 1032·2021-11-10 11:36
閱讀 1379·2021-10-08 10:14
閱讀 3496·2021-09-28 09:35
閱讀 1551·2021-08-23 09:47
閱讀 2543·2019-08-30 15:56
閱讀 1468·2019-08-30 15:44
閱讀 1749·2019-08-30 13:59