为什么xQueueSendToBack调用被阻塞?

为什么xQueueSendToBack调用被阻塞?,c,embedded,freertos,C,Embedded,Freertos,我正在STM32F103C8T6(蓝色药片板上)上学习FreeRTOS。 我正在尝试使用队列和任务 #include <FreeRTOS.h> #include <libopencm3/stm32/gpio.h> #include <libopencm3/stm32/rcc.h> #include <queue.h> #include <task.h> static QueueHandle_t queue; static void

我正在STM32F103C8T6(蓝色药片板上)上学习FreeRTOS。 我正在尝试使用队列和任务

#include <FreeRTOS.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/rcc.h>
#include <queue.h>
#include <task.h>

static QueueHandle_t queue;

static void
task_receive(void *args __attribute__((unused)))
{
  bool nothing;
  while (1)
  {
    if (xQueueReceive(queue, &nothing, 10) == pdPASS)
      gpio_set(GPIOC, GPIO13); // Turn off
    else
      taskYIELD(); // Yeld so that other taks can run
  }
}

static void
task_send(void *args __attribute__((unused)))
{
  bool nothing = false;
  while (1)
  {
    gpio_clear(GPIOC, GPIO13); // Turn on
    vTaskDelay(pdMS_TO_TICKS(100));
    xQueueSendToBack(queue, &nothing, portMAX_DELAY);
    vTaskDelay(pdMS_TO_TICKS(1000));
  }
}

int
main(void)
{
  rcc_clock_setup_in_hse_8mhz_out_72mhz();

  // Blue-Pill led
  rcc_periph_clock_enable(RCC_GPIOC);
  gpio_set_mode(
    GPIOC,
    GPIO_MODE_OUTPUT_2_MHZ,
    GPIO_CNF_OUTPUT_PUSHPULL,
    GPIO13);
  gpio_set(GPIOC, GPIO13); // Turn off (polarity of the led is inversed!)

  queue = xQueueCreate(32, sizeof(bool));
  if (queue == 0)
  {
    while (1)
    {
      gpio_toggle(GPIOC, GPIO13);
      for (uint32_t i = 0; i < 80000; ++i)
        __asm__("nop");
    };
  }
  xTaskCreate(task_receive, "RECEIVE", 200, NULL, configMAX_PRIORITIES-1, NULL);
  xTaskCreate(task_send, "SEND", 200, NULL, configMAX_PRIORITIES-2, NULL);
  vTaskStartScheduler();
  while(1);
  return 0;
}

您的
任务\u接收
优先级高于
任务\u发送
优先级<如果没有更高优先级的任务,code>taskYIELD将反复运行相同的调用任务

要实现您的目标,请尝试按以下方式更改
任务\u receive

static void
task_receive(void *args __attribute__((unused)))
{
  bool nothing;
  while (1)
  {
    if (xQueueReceive(queue, &nothing, portMAX_DELAY) == pdPASS)
      gpio_set(GPIOC, GPIO13); // Turn off
  }
}
有关taskYIELD的更多信息,请参阅以下内容


通过将编译器更新到最新版本,问题得以解决

Kubuntu 18.04附带
arm none eabi gcc(15:6.3.1+svn253039-1build1)6.3.1 20170620
,使用此编译器,代码不起作用

memcpy
似乎是代码中有问题的函数调用,FreeRTOS在向队列添加元素时会调用它


如果我使用
Version 8-2018-q4-major Linux 64位
编译器,则代码执行良好。可以在此处下载:

在您的示例中,
任务的接收
优先级高于
任务的发送
优先级,因此,在较高优先级的任务中让步将再次让步调用任务。因此,您的
send\u任务
根本不会被抢占。看看这个,我尝试过这个改变,但它并没有改善led的行为(它是打开的,从不关闭)。我还试图使这两项任务具有相同的优先级:没有更好的。让我在这里做一个有根据的猜测。您的代码不是卡在
vTaskDelay
而不是
xQueueSendToBack
中了吗。如果是这种情况,请确保您的systick ISR(我假设systick是RTOS tick源)正确配置为调用FreeRTOS tick函数。看看
libopencm3
是如何处理systick ISR的。我认为它的配置是正确的。我创建了一个示例,用两个任务使led闪烁(一个任务打开led,另一个任务关闭led),每个任务都调用
vTaskDelay
,效果良好。您是否有通过调试器逐步完成源代码的功能?似乎您在FreeRTOS代码中遇到了一个
configAssert
。同样,我希望此时您已经检查了
200
单词的堆栈大小是否足以完成这两项任务。@VictorAmoine我没有发现代码有任何错误(对于非
taskYIELD
one)。我在另一块板上尝试了一个类似的代码,似乎工作得很好(我用UART printfs替换了GPIO调用)。也许您最好尝试对STM32Cube HAL做同样的事情,绕过libopencm3依赖项—只是一个建议。为了进一步帮助您更好地使用FreeRTOS讨论论坛。
static void
task_receive(void *args __attribute__((unused)))
{
  bool nothing;
  while (1)
  {
    if (xQueueReceive(queue, &nothing, portMAX_DELAY) == pdPASS)
      gpio_set(GPIOC, GPIO13); // Turn off
  }
}