FreeRTOS系統-二值信號量的使用
提示:以下文章基于FreeRTOS全部移植完成,能夠正常運行.
文章目錄
- FreeRTOS系統-二值信號量的使用
- 前言
- 一、FreeRTOS系統的中斷管理?
- 二、二值信號量
- 1.二值信號量介紹
- 需要用到的頭檔案
- 創建信號量
- 釋放信號量
- 獲取信號量
- 2.使用指南
- 總結
前言
FreeRTOS系統的引入可以極大的提高程式的運行效率,搭建的框架也提高了程式的易寫性,提高編程效率.
在使用FreeRTOS系統的程序中,筆者發現GPIO觸發外部中斷,在中斷服務函式中做一個Delay_ms(20)的延時消抖時,會導致FreeRTOS系統停止作業,這樣會導致系統效率降低更嚴重的情況會導致一些需要實時性的功能斷層.
一、FreeRTOS系統的中斷管理?
configLIBRARY_LOWEST_INTERRUPT_PRIORITY]
這個宏是可以定義的中斷最低優先級,由于STM32中斷管理只用了4位來分配搶占優先級和子優先級,并且FreeRTOS使用優先級分組4(沒有子優先級),所以該宏設為15
configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY
這個宏是系統可管理的最高中斷優先級,即為一個閾值,低于該值的可以呼叫一些fromISR的函式,高于該優先級的中斷則不回應打開和關斷中斷(一直都可以進行中斷操作),
configKERNEL_INTERRUPT_PRIORITY
這個宏定義是( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ),實質上就是把15左移4位當作真正的優先級,(因為第四位保留了)
configMAX_SYSCALL_INTERRUPT_PRIORITY
相當于( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ),原因與configKERNEL_INTERRUPT_PRIORITY相同,
經過對上面configLIBRARY_LOWEST_INTERRUPT_PRIORITY]與configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY的宏定義便確定了在這個優先級范圍內能夠呼叫FreeRTOS系統的API了,
這個優先級范圍的確定,接下來我們在外部中斷的優先級定義就必須在此范圍內,否則FreeRTOS的API的呼叫在中斷服務函式中卡死,
二、二值信號量
1.二值信號量介紹
二值型信號量可以理解為任務與中斷間或者兩個任務間的標志,該標志非“滿”即“空”,Give操作相當把該標志置“滿”,Take操作相關與把該標志取"空",經過send和receive操作實作任務與中斷間或者兩任務的操作同步,
需要用到的頭檔案
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
創建信號量
| 函式 | 描述 |
|---|---|
| xSemaphoreCreateBinary() | 動態創建二值信號量 |
| vSemaphoreCreateBinaryStatic() | 靜態創建二值信號量 |
使用(示例):
SemaphoreHandle_t Semaphore_Exit1 = NULL;//宣告變數 用來接收創建二值信號量的句柄
Semaphore_Exit1 = xSemaphoreCreateBinary();//創建外部中斷1 二值信號量
釋放信號量
| 函式 | 描述 |
|---|---|
| xSemaphoreGive() | 任務級釋放二值信號量 |
| xSemaphoreGiveFromISR() | 中斷中釋放二值信號量 |
以上兩個釋放二值信號量的函式,需用戶根據自己的使用環境進行選擇,在中斷服務函式中一定選擇 xSemaphoreGiveFromISR()
使用(示例):
//在外部1中釋放Semaphore_Exit1二值信號量
//引數1:傳入你要釋放的二值信號量的句柄,也就是你創建二值信號量的回傳值
//引數2:默認NULL
void EXTI_1_Triggered_Mptor1_Stop(void)
{
xSemaphoreGiveFromISR( Semaphore_Exit1, NULL );//發送二值信號量
}
獲取信號量
| 函式 | 描述 |
|---|---|
| xSemaphoreTake() | 任務級獲得二值信號量 |
| xSemaphoreTakeFromISR() | 中斷級獲得二值信號量 |
以上兩個獲取二值信號量的函式,需用戶根據自己的使用環境進行選擇,與釋放二值信號量配套使用,
使用(示例):
//創建一個任務進行對二值信號量的獲取判斷,獲取后進行操作,未獲取則進行等待,并釋放資源使其他任務繼續進行,
void Exit1_Irq_task(void *pvParameters)
{
while (1)
{
//引數1:需要獲取的二值信號量句柄
//引數2:等待時間 portMAX_DELAY為永久等待
//回傳值:成功回傳1 失敗回傳 0
if(pdTRUE == xSemaphoreTake(Semaphore_Exit1,portMAX_DELAY))//等待二值信號量 永久等待
{
vTaskDelay(20);//FreeRTOS的延時是一種阻塞態并不會占用系統資源
/********/
省略代碼
/*******/
}
}
}
2.使用指南
思路說明:在一個外部中斷服務函式中釋放二值信號量,創建一個任務進行等待二值信號量的到來,在任務中進行操作,這樣極大的減少了在系統中斷中停留的時間,使得系統運行效率大大提高,
代碼如下(示例):
SemaphoreHandle_t Semaphore_Exit1 = NULL;//宣告變數 用來接收創建二值信號量的句柄
Semaphore_Exit1 = xSemaphoreCreateBinary();//創建外部中斷1 二值信號量
void FreeRTOS_Exec()
{
//創建二值信號量獲取后的處理任務
xTaskCreate((TaskFunction_t )Exit1_Irq_task,
(const char* )"Exit1_Irq_task",
(uint16_t )EXIT1_TRQ_STK_SIZE,
(void* )NULL,
(UBaseType_t )EXIT1_IRQ_TASK_PRIO,
(TaskHandle_t* )&Exit1_Irq_Task_Handler);
vTaskStartScheduler(); //開啟任務調度
}
//創建一個任務進行對二值信號量的獲取判斷,獲取后進行操作,未獲取則進行等待,并釋放資源使其他任務繼續進行,
void Exit1_Irq_task(void *pvParameters)
{
while (1)
{
//引數1:需要獲取的二值信號量句柄
//引數2:等待時間 portMAX_DELAY為永久等待
//回傳值:成功回傳1 失敗回傳 0
if(pdTRUE == xSemaphoreTake(Semaphore_Exit1,portMAX_DELAY))//等待二值信號量 永久等待
{
vTaskDelay(20);//FreeRTOS的延時是一種阻塞態并不會占用系統資源
/********/
省略代碼
/*******/
}
}
}
//在外部中斷1中釋放Semaphore_Exit1二值信號量
//引數1:傳入你要釋放的二值信號量的句柄,也就是你創建二值信號量的回傳值
//引數2:默認NULL
void EXTI_1_Triggered_Mptor1_Stop(void)
{
xSemaphoreGiveFromISR( Semaphore_Exit1, NULL );//發送二值信號量
}
總結
[1].任務的優先級以及分配的空間大小需要適合,
[2].中斷中發送信號量盡量使用xSemaphoreGiveFromISR,
[3]釋放信號量的中斷的優先級數值應大configMAX_SYSCALL_INTERRUPT_PRIORITY,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/241419.html
標籤:其他
上一篇:基于stm32f103與IIC的0.96OLED螢屏顯示字符與平滑滾動顯示
下一篇:程式設計基礎(C語言)
