如何在FreeRTOS中中断xQueueReceive()API?

时间:2015-06-15 03:18:43

标签: task message-queue rtos freertos

在以下代码中

  • SendMessage()是用户通过USB发送消息的API
  • UsbDataReceived()是在USB
  • 上收到数据时由另一个线程调用的函数
  • Task()init()中创建的线程,它从SendMessage()填充的队列中读取并调用低级别usb函数发送消息
  • UsbConnected()是连接USB设备时由另一个线程调用的函数。

我需要实现以下行为:

  • 发送消息后,当最后一条消息的答案到达时,无法发送新消息
  • 当调用UsbConnected()时,必须清空所有队列,如果线程Task()正在等待队列AnswerQueue,则必须将其解除阻塞,以便它可以返回等待队列CommandQueue

下面列出了我最佳解决方案的一个示例。

我必须在具有特定订单的两个队列上发布EVENT_QUEUE_RESETTED消息。

是否有可能以不那么麻烦的方式获得相同的结果?

void UsbhOut(Message_t );
int UsbConnected;
QueueHandle_t MessageQueue;



typedef enum
{
    EVENT_QUEUE_RESETTED,
    EVENT_NEW_MESSAGE,
    EVENT_NEW_ANSWER,
} Event_t;

typedef struct
{
    Event_t Event;
    uint8_t Data[32];
} CommandQueue_t;

typedef struct
{
    Event_t Event;
    uint8_t Data[32];
} AnswerQueue_t;


void init(void)
{
  MessageQueue = xQueueCreate(sizeof(Message_t), 10);
  AnswerQueue = xQueueCreate(sizeof(Message_t), 10);
  xTaskCreate(Task, "", 200, NULL, 1, NULL);
}

void UsbConnected(void)
{
  CommandEvent.Event = EVENT_QUEUE_RESETTED;
  AnswerEvent.Event = EVENT_QUEUE_RESETTED;

  UsbConnected = 1;
  xQueueReset(MessageQueue);
  xQueueReset(AnswerQueue);

  /* The order here is fundmental */
  xQueueSend(AnswerQueue, &AnswerEvent, 0);
  xQueueSend(MessageQeueue, &CommandEvent, 0);

}


int SendMessage(uint8_t * Data)
{
  CommandQueue_t CommandEvent;

  CommandEvent.Event = EVENT_NEW_MESSAGE;
  memcpy(&CommandEvent, Message, 32);

  if(xQueueSend(MessageQueue, &CommandEvent, 0) == pdTRUE)
    return 0;
  else
    return -1;
}


void UsbDataReceived(uint8_t * Data)
{
  AnswerQueue_t AnswerEvent;
  AnswerEvent.Event = EVENT_NEW_ANSWER;
  memcpy(AnswerEvent.Data, Data, 32);

  xQueueSend(AnswerQueue, &AnswerEvent,0);
}


void Task(void *pvParameters)
{
  CommandQueue_t CommandEvent;
  AnswerQueue_t AnswerEvent;
  CommandCallback_t * Callback;

  while(1)
  {
     xQueueReceive(UsbhStaticData.CommandSenderQueue, &CommandEvent, portMAX_DELAY);

     if(CommandEvent.Event == CommandSenderQueueData_t::EVENT_QUEUE_RESETTED)
     {
       continue;
     }

     /* Low level Usb fucntion used to send Data */
     UsbdSendData(Command.Data);

     xQueueReceive(UsbhStaticData.AnswerReceivdQueue, &AnswerEvent, portMAX_DELAY);

     if(AnswerEvent.Event == AnswerReceivedQueueData_t::EVENT_QUEUE_RESETTED)
     {
         continue;
     }
     else if(AnswerEvent.Event == AnswerReceivedQueueData_t::EVENT_ANSWER_RECEIVED)
     {
       ParseData(AnswerEvent.Data);
     }
  }

}

1 个答案:

答案 0 :(得分:1)

您可以使用队列集 FreeRTOS Queue Set API 这样你就可以创建一个包含队列和信号量的队列集。您的任务将阻止队列集。然后通过从队列接收消息或递增信号量来解除阻塞。