close

FreeRTOSlogo-lg-1260x471.jpeg

二值型信號量是任務(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

2.JPG

這時外部中斷優先權或其他中斷(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);    

}

3.JPG

創建任務與二值型信號量,如下所示,

/* 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();
}    

4.JPG

5.JPG

外部中斷程式如下所示,

/*
程式名稱:外部中斷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);
}

6.JPG

7.JPG

8.JPG

獲取二值型信號量程式如下所示,

/*
程式名稱:任務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));
        }        
    }            
}

9.JPG

10.JPG

12.JPG

測試結果如下,

13.JPG

arrow
arrow
    創作者介紹
    創作者 鄭智遠 的頭像
    鄭智遠

    Michael_Jheng的部落格

    鄭智遠 發表在 痞客邦 留言(0) 人氣()