采用二值信号量同步
二值信号量可以在某个特殊的中断发生时,让任务解除阻塞,相当于让任务与中断同步。 这样就可以让中断事件处理量大的工作在同步任务中完成,中断服务例程(ISR)中只是快速处理少部份工作。 如此,中断处理可以说是被”推迟(deferred)”到一个”处理(handler)”任务。
这句话可以简单的理解为,只有当对应中断发生时,CPU才去去执行某一tesk,而这个tesk处于一种死循环;那么我们必须采用二值信号量结解决这个问题。
1.创建二值信号量,此时表示信号量的队列为空 xSemaphoreCreateBinary()
2.在tesk中获取信号量 xSemaphoreTake (...)
3.在中断处理函数中释放信号量 xSemaphoreGiveFromISR (...)
cpu上电创建二值信号量, 进入tesk 在tesk中获取二值信号量,获取信号量为0 不执行打印,执行完tesk后 tesk处于阻塞状态;当对应的中断产生后cpu进入中断处理函数,中断处理函数清零中断标志位 并 释放一个信号量,中断结束后,cpu又进入到tesk中再次获取信号量为1,打印“Task creation failed!”,执行完tesk 进入阻塞状态,;当对应的中断产生时... 如此验证了标题那句话二值信号量中断同步
int main(void)
{
...
xSWSemaphore = xSemaphoreCreateBinary();//创建二值信号量
/*Create tickless task*/
if (xTaskCreate(Tickless_task, "Tickless_task", configMINIMAL_STACK_SIZE + 38, NULL, tickless_task_PRIORITY,
NULL) != pdPASS)
{
PRINTF("Task creation failed!.\r\n");
while (1)
;
}
/*Create SW_task task*/
if (xTaskCreate(SW_task, "Switch_task", configMINIMAL_STACK_SIZE + 38, NULL, SW_task_PRIORITY, NULL) != pdPASS)
{
PRINTF("Task creation failed!.\r\n");
while (1)
;
}
/*Task Scheduler*/
vTaskStartScheduler();
for (;;)
;
}
/* Tickless Task 没有按键时打印滴答定时器时间 */
static void Tickless_task(void *pvParameters)
{
PRINTF("\r\nTick count :\r\n");
for (;;)
{
PRINTF("滴答定时器延时%d\r\n", xTaskGetTickCount());
vTaskDelay(TIME_DELAY_SLEEP);
}
}
/* Switch Task 按下sw3时获取信号量并打印 */
static void SW_task(void *pvParameters)
{
for (;;)
{
if (xSemaphoreTake(xSWSemaphore, portMAX_DELAY) == pdTRUE)
PRINTF("CPU waked up by EXT interrupt\r\n");
}
}
void BOARD_SW_IRQ_HANDLER(void) //SW_task 中段处理函数
{
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
GPIO_ClearPinsInterruptFlags(BOARD_SW_GPIO, 1U << BOARD_SW_GPIO_PIN);//清中断
xSemaphoreGiveFromISR(xSWSemaphore, &xHigherPriorityTaskWoken);//释放信号量
}
关于信号量和对列请参考http://www.mamicode.com/info-detail-1368119.html