【问题标题】:How to interrupt an xQueueReceive() API in FreeRTOS?如何在 FreeRTOS 中中断 xQueueReceive() API?
【发布时间】:2015-06-15 03:18:43
【问题描述】:

在下面的代码中

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

我需要实现以下行为:

  • 一旦发送了一条消息,直到最后一条消息的答复到达时,才能发送新消息
  • UsbConnected()被调用时,所有的队列都必须被清空,如果线程Task()正在队列AnswerQueue上等待,它必须被解除阻塞,以便它可以返回等待队列@ 987654330@

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

我必须以特定顺序在两个队列上发布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);
     }
  }

}

【问题讨论】:

    标签: task message-queue rtos freertos


    【解决方案1】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-11-27
      • 2022-08-19
      • 2021-09-21
      • 2021-04-01
      • 2020-10-02
      • 1970-01-01
      • 2021-01-16
      相关资源
      最近更新 更多