使用FreeRTOS二进制信号量进行硬件中断

时间:2017-12-25 06:36:24

标签: c embedded atmel freertos electronics

按下按钮后,我正试着让LED点亮。贝娄是应该处理这个问题的代码片段:

void task_player1(void *pvParameters)
{   
    while (1)
    {
        if (xSemaphoreTake(player1_signal, portMAX_DELAY))
        {
            printf(">>>Semaphore taken\n<<<");
            ioport_set_pin_level(L1, HIGH);
            xSemaphoreGive(player1_signal);
        }
        else
        {
            ioport_set_pin_level(L1, LOW);
        }
    }
}

void task_ctrl(void *pvParameters)
{
    bool button1 = 0;       

    while (1)
    {
        button1 = ioport_get_pin_level(B1);
        if (button1)
        {
            xSemaphoreGive(player1_signal);
            printf("Semaphore given\n");
        }
    }
}

我想象的方式是 task_ctrl 在按下按钮时给出信号量。 Task_player1 会被阻止,直到获取信号量,然后它才会打开LED。

问题是它似乎永远不会采用信号量。我正在运行printf语句,向我展示程序到达的程度,它永远不会进入LED亮起的部分。但是当我在 task_ctrl 中没有按下按钮的情况下运行 xSemaphoreGive 时,就会获取信号量。

奇怪的部分是信号量给定语句在按钮点击时打印出来,这意味着信号量也会被给出,但永远不会被采用。

这些任务独立工作,我甚至设法在没有按钮的情况下给出了信号量if if语句,如上所述。

我猜这是按钮按键代码,它也可以在任务之外使用它。那么我做错了什么?我没有正确使用FreeRTOS吗?

编辑:包括任务创建代码

#define TASK_STACK_SIZE (2048/ sizeof(portSTACK_TYPE))

xTaskCreate(task_ctrl, (const signed char * const) "Control", TASK_STACK_SIZE, NULL, 1, NULL);

xTaskCreate(task_player1, (const signed char * const) "Player1", TASK_STACK_SIZE, NULL, 1, NULL);

编辑2:我应该提到的一点是我使用的是FreeRTOS 7.3,因为Atmel Studio没有任何新版本。因此,据我所知,没有屈服函数可用。

1 个答案:

答案 0 :(得分:3)

task_ctrl永远不会阻止 - 这将阻止永远运行任何具有相同或更低优先级的任务。因此,如果task_player具有相同或更低的优先级,即使给出了信号量,也不会安排任务。

看起来没有按钮轮询的工作很难解释,但你没有显示那些代码所以我无法评论。

你应该做两件事:

  1. 确保task_ctrl的优先级低于task_player1(如果没有阻止,则低于任何任务 - 在这种情况下,空闲任务将永远不会运行。)
  2. 确保task_ctrl阻止 - 即使这只是轮询延迟,这样它就不会占用所有可用的CPU周期。
  3. while (1)
    {
        button1 = ioport_get_pin_level(B1);
        if (button1)
        {
            xSemaphoreGive(player1_signal);
            printf("Semaphore given\n");
    
            vtaskDelay( 1 ) ; // at least 1 tick
        }
    }
    

    task_ctrl的一个可能问题是,当按钮被按住时,它会连续重复地给出信号量。某种状态变化检测和开关去抖而不是水平轮询可能更可取。

    轮询任务的另一种解决方案是对teh按钮使用硬件中断,并对来自ISR的事件设置轮询任务块,或让ISR直接提供信号量 - 无论哪种情况,您都必须处理去抖动。