这是我的问题:
我正在将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);
}
}
}
答案 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()
似乎表明这种保护已经成为排队实现的一部分。我只是提出这个值得注意的事情。