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