二值型信號量是任務(task)與中斷(Interrupted)間同步的重要手段,能夠使任務(task)與中斷(Interrupted)同步操作,創建二值型信號量程式如下,
SemaphoreHandle_t xSemaphoreCreateBinary(void);
創建一個二進制信號量,並返回一個可以引用信號量的控制代碼
在中斷(Interrupted)要與任務同步的信號量,要使用以下程式,
xSemaphoreGiveFromISR(SemaphoreHandle_t xSemaphore,
signed BaseType_t *pxHigherPriorityTaskWoken)
SemaphoreHandle_t xSemaphore: 二值型信號量控制代碼
signed BaseType_t *pxHigherPriorityTaskWoken: 最高優先權喚醒
要獲取來至中斷(Interrupted)來信號量,要使用以下程式,
xSemaphoreTake(SemaphoreHandle_t xSemaphore,
TickType_t xTicksToWait);
SemaphoreHandle_t xSemaphore: 二值型信號量控制代碼
TickType_t xTicksToWait: 等待信號量變為可用的時間
接下來以外部中斷來測試二值型信號量,在這之前須準備好外部中斷的配置,並使用按鍵來進行觸發操作,
其中需注意在"FreeRTOSConfig.h"文件第108行#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
這時外部中斷優先權或其他中斷(UART,ADC,I2C....)須設定在6以下,也就是說中斷(Interrupted)優先權不得在5以上,否則會無法操作,測試範例設三個外部中斷來做測試,如下所示,
/*
程式名稱:EXTI配置初始化
程式版本:V1.0
程式撰寫者:Michael Jheng(鄭智遠)
程式撰寫日期:2018/1/7
程式修改日期:N/A
程式說明:
*/
void EXTI_ConfigInit(void){
/* 設定4個KEY的配置 */
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
/* KEY0(GPIOE_4),KEY1(GPIOE_3),KEY2(GPIOE_2) */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOE, &GPIO_InitStructure);
/* 4個外部中斷配置 */
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource2);
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource3);
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource4);
/* KEY0(EXTI_Line4),KEY1(EXTI_Line3),KEY2(EXTI_Line2) */
EXTI_InitStructure.EXTI_Line = EXTI_Line2 | EXTI_Line3 | EXTI_Line4;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
/* KEY2(EXTI_Line2) */
NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 6;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* KEY1(EXTI_Line3) */
NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 7;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* KEY0(EXTI_Line4) */
NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 8;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
創建任務與二值型信號量,如下所示,
/* Task任務控制代碼 */
TaskHandle_t vTaskHandle;
/* Semaphore任務控制代碼 */
SemaphoreHandle_t xSemaphoreTaskOne,xSemaphoreTaskTwo,xSemaphoreTaskThree;
/* 設置xHigherPriorityTaskWoken參數 */
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
/*
程式名稱:創建任務
程式版本:V1.0
程式撰寫者:Michael Jheng(鄭智遠)
程式撰寫日期:2018/1/8
程式修改日期:N/A
程式說明:
*/
void AppTaskCreate(void){
/* 任務Semaphore One */
xTaskCreate(vTaskSemaphoreOne, "vTask Semaphore One", 512, "vTask Semaphore One\r\n", 3, &vTaskHandle);
/* 任務Semaphore Two */
xTaskCreate(vTaskSemaphoreTwo, "vTask Semaphore Two", 512, "vTask Semaphore Two\r\n", 2, &vTaskHandle);
/* 任務Semaphore Three */
xTaskCreate(vTaskSemaphoreThree, "vTask Semaphore Three", 512, "vTask Semaphore Three\r\n", 1, &vTaskHandle);
/* 創建xSemaphoreTaskOne二值型信號量 */
xSemaphoreTaskOne = xSemaphoreCreateBinary();
/* 創建xSemaphoreTaskTwo二值型信號量 */
xSemaphoreTaskTwo = xSemaphoreCreateBinary();
/* 創建xSemaphoreTaskThree二值型信號量 */
xSemaphoreTaskThree = xSemaphoreCreateBinary();
}
外部中斷程式如下所示,
/*
程式名稱:外部中斷2
程式版本:V1.0
程式撰寫者:Michael Jheng(鄭智遠)
程式撰寫日期:2018/1/10
程式修改日期:N/A
程式說明:
*/
void EXTI2_IRQHandler(void){
delay_ms(50);
if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2)==0){
/* 在中斷中發送xSemaphoreTaskOne信號量 */
xSemaphoreGiveFromISR(xSemaphoreTaskOne, &xHigherPriorityTaskWoken);
}
EXTI_ClearITPendingBit(EXTI_Line2);
}
/*
程式名稱:外部中斷3
程式版本:V1.0
程式撰寫者:Michael Jheng(鄭智遠)
程式撰寫日期:2018/1/10
程式修改日期:N/A
程式說明:
*/
void EXTI3_IRQHandler(void){
delay_ms(50);
if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)==0){
/* 在中斷中發送xSemaphoreTaskTwo信號量 */
xSemaphoreGiveFromISR(xSemaphoreTaskTwo, &xHigherPriorityTaskWoken);
}
EXTI_ClearITPendingBit(EXTI_Line3);
}
/*
程式名稱:外部中斷4
程式版本:V1.0
程式撰寫者:Michael Jheng(鄭智遠)
程式撰寫日期:2018/1/10
程式修改日期:N/A
程式說明:
*/
void EXTI4_IRQHandler(void){
delay_ms(50);
if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)==0){
/* 在中斷中發送xSemaphoreTaskThree信號量 */
xSemaphoreGiveFromISR(xSemaphoreTaskThree, &xHigherPriorityTaskWoken);
}
EXTI_ClearITPendingBit(EXTI_Line4);
}
獲取二值型信號量程式如下所示,
/*
程式名稱:任務Semaphore One
程式版本:V1.0
程式撰寫者:Michael Jheng(鄭智遠)
程式撰寫日期:2018/1/11
程式修改日期:N/A
程式說明:
*/
void vTaskSemaphoreOne(void *pvParameters){
for(;;){
/* 獲取xSemaphoreTaskOne信號量 */
if(xSemaphoreTake( xSemaphoreTaskOne, portMAX_DELAY) == pdTRUE){
UART2_Send(pvParameters, strlen(pvParameters));
}
}
}
/*
程式名稱:任務Semaphore Two
程式版本:V1.0
程式撰寫者:Michael Jheng(鄭智遠)
程式撰寫日期:2018/1/11
程式修改日期:N/A
程式說明:
*/
void vTaskSemaphoreTwo(void *pvParameters){
for(;;){
/* 獲取xSemaphoreTaskTwo信號量 */
if(xSemaphoreTake( xSemaphoreTaskTwo, portMAX_DELAY) == pdTRUE){
UART2_Send(pvParameters, strlen(pvParameters));
}
}
}
/*
程式名稱:任務Semaphore Three
程式版本:V1.0
程式撰寫者:Michael Jheng(鄭智遠)
程式撰寫日期:2018/1/11
程式修改日期:N/A
程式說明:
*/
void vTaskSemaphoreThree(void *pvParameters){
for(;;){
/* 獲取xSemaphoreTaskThree信號量 */
if(xSemaphoreTake( xSemaphoreTaskThree, portMAX_DELAY) == pdTRUE){
UART2_Send(pvParameters, strlen(pvParameters));
}
}
}
測試結果如下,
留言列表