从队列中读取总是提供错误的价值

时间:2012-03-28 09:07:40

标签: c

这是我的问题:

我正在将FreeRTOS与Cortex-M3 MCU配合使用。我有一个名为EXTI15_10的ISR,它 在引脚EXTI_Line10,EXTI_Line11..etc的上升沿触发。 在ISR中,我将变量“status”设置为某个指定值,然后再离开ISR 我将变量状态放入队列并将其发送到我的线程。这很好。

定期调用该线程并调用该函数 xQueuePeek()从队列中获取项目。注意xQueuePeek() 从队列中获取项目而不将其从队列中删除。 这也很好,但我只收到一次正确的值。 这意味着,生成中断,将状态设置为一个值并放入 queue,threads读取正确的值。但所有下一个中断 正确设置状态(我在将项目放入队列之前检查过),但我的 线程始终读取旧值。我这里有编译器的问题吗? 优化和波动? xQueueSendFromISR(),期待作为第二个论点 const void *而不是volatile void *。我在这里做错了什么?

ISR:

void EXTI15_10_IRQHandler()
{   
    portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
    int status;

    if (EXTI_GetITStatus(EXTI_Line10))
        status = 100;
    else if (EXTI_GetITStatus(EXTI_Line11))
        status = 200
    else if (EXTI_GetITStatus(EXTI_Line12))
        status = 300;
    else if (EXTI_GetITStatus(EXTI_Line13))
        status = 400;
    else if (EXTI_GetITStatus(EXTI_Line14))
        status = 500;
    else if (EXTI_GetITStatus(EXTI_Line15))
        status = 600;

    // Clear the pending interrupt bits
    EXTI_ClearITPendingBit(EXTI_Lines15_10);

    xQueueSendFromISR(queue, &status, &xHigherPriorityTaskWoken);
    portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
}

主题:

static void thread_xy()
{
    portTickType xLastExecutionTime;

    xLastExecutionTime = xTaskGetTickCount();
    int status_from_queue = 0;

    for (;;) {
        xLastExecutionTime = xTaskGetTickCount();
        vTaskDelayUntil(&xLastExecutionTime, CHECK_AND_ENABLE_LEDS_DELAY);

        if (queue != 0) {
            if (xQueuePeek(queue, &status_from_queue, portMAX_DELAY))
                // Received item from queue...
                print("Status from queue = %d\n", status_from_queue);
        }
    }
}

1 个答案:

答案 0 :(得分:2)

如果您只是在队列中偷看,那么,是的,您将始终获得相同的价值,因为您将其留在那里。队列是先进先出的数据结构,但为了获得队列中的第二个值,您通常必须删除第一个。

考虑以下顺序:

initial state            queue = { }
interrupt adds 7         queue = { 7 }
application peeks (7)    queue = { 7 }
interrupt adds 42        queue = { 7, 42 }
application peeks (7)    queue = { 7, 42 }
interrupt adds 314159    queue = { 7, 42, 314159 }
application peeks (7)    queue = { 7, 42, 314159 }

如果你想从队列中提取一个值并使用它,你需要得到它而不是窥视它。没有它,队列也将最终填满。

我还应该提一下,这里可能存在竞争条件,这可能会给你带来麻烦。如果你的应用程序在中断到达时修改队列(通过从中获取值)的一半,你将会遇到各种麻烦,因为队列不会处于一致状态。

当队列可能处于不一致状态时,您需要一种方法来停止(或更好地延迟)中断。这可能就像在应用程序修改中断时禁用中断一样简单(例如,如果您使用的是多处理器系统,则可能需要更复杂的代码)。

当然,xQueuePeek()(和其他相关的)代码可能已经这样做了,因为你有一个xQueueSendFromISR()似乎表明这种保护已经成为排队实现的一部分。我只是提出这个值得注意的事情。