C-用弗雷托斯二进制信号量中断硬件



我基本上试图在按下按钮后将LED点亮。下面是应该处理此操作的代码的片段:

void task_player1(void *pvParameters)
{   
    while (1)
    {
        if (xSemaphoreTake(player1_signal, portMAX_DELAY))
        {
            printf(">>>Semaphore takenn<<<");
            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 givenn");
        }
    }
}

我要设想的方式是task_ctrl在按钮上给出信号量。 Task_player1被阻止,直到需要信号量,之后应打开LED。

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

奇怪的部分是"Semaphore givenn"语句在按钮点击上打印出来,这应该意味着也给出了信号量,但永远不会被拿走。

任务独自工作,我什至设法在没有按钮的情况下使用按钮,如我上面所述。

我猜想这是按钮按代码的东西,该按钮也可以在任务之外使用。那我做错了什么?我不是正确使用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没有任何更新版本。因此,据我所知,没有收益功能可用。

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

它似乎没有按钮轮询工作很难解释,但是您尚未显示该代码,因此我无法发表评论。

您应该做两件事:

  1. 确保task_ctrl的优先级较低,至少比task_player1(如果不阻止任何任务,则比任何任务都低 - 在这种情况下,闲置任务永远不会运行)。
  2. 确保task_ctrl阻止 - 即使只是轮询延迟,以免吞噬所有可用的CPU周期。

while (1)
{
    button1 = ioport_get_pin_level(B1);
    if (button1)
    {
        xSemaphoreGive(player1_signal);
        printf("Semaphore givenn");
        vtaskDelay( 1 ) ; // at least 1 tick
    }
}

task_ctrl的一个可能的问题是,它将在保留按钮时连续且反复地给出信号量。某种状态变化检测和切换脱回反弹而不是级别的轮询。

投票任务的替代解决方案是使用硬件中断TEH按钮,并在ISR上使用事件的投票任务块,或者将ISR直接提供给信号量 - 在任何一种情况下,您都必须交易审问。

最新更新