Почему блокировка вызова xQueueSendToBack? - PullRequest
3 голосов
/ 18 марта 2019

Я изучаю FreeRTOS на STM32F103C8T6 (на плате Blue-Pill). Я пытаюсь использовать очереди и задачи.

#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;
}

Ожидаемое поведение:

  • main

    • Настраивает часы
    • Настройка GPIO для светодиода Blue Pill
    • Отключает светодиод
    • Создает очередь
    • Проверяет, правильно ли была создана очередь: если не мигать, светодиод быстро и навсегда.
    • Расписание двух заданий
    • Запускает планировщик
  • task_send (бесконечно зацикливается)

    • Включите светодиод
    • Подождите 100 мс
    • Вставить сообщение в очередь (здесь содержимое не имеет значения)
    • Подождите 1 сек.
  • task_receive (бесконечно зацикливается)

    • Проверить, находится ли сообщение в очереди
      • Да: выключить светодиод
      • №: yeld

Я ожидаю, что светодиод будет включен на 100 мс, а затем выключен на 900 мс.

Реальное поведение: светодиод всегда включен, кажется, что выполнение программы блокируется на xQueueSendToBack.

Почему блокируется звонок?


FreeRTOSConfig.h

#define configUSE_PREEMPTION        1
#define configUSE_IDLE_HOOK     0
#define configUSE_TICK_HOOK     0
#define configCPU_CLOCK_HZ      ( ( unsigned long ) 72000000 )  
#define configSYSTICK_CLOCK_HZ      ( configCPU_CLOCK_HZ / 8 ) /* fix for vTaskDelay() */
#define configTICK_RATE_HZ      ( ( TickType_t ) 1000 )
#define configMAX_PRIORITIES        ( 5 )
#define configMINIMAL_STACK_SIZE    ( ( unsigned short ) 128 )
#define configTOTAL_HEAP_SIZE       ( ( size_t ) ( 17 * 1024 ) )
#define configMAX_TASK_NAME_LEN     ( 16 )
#define configUSE_TRACE_FACILITY    0
#define configUSE_16_BIT_TICKS      0
#define configIDLE_SHOULD_YIELD     1
#define configUSE_MUTEXES       1

/* Co-routine definitions. */
#define configUSE_CO_ROUTINES       0
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )

/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */

#define INCLUDE_vTaskPrioritySet        1
#define INCLUDE_uxTaskPriorityGet       1
#define INCLUDE_vTaskDelete             1
#define INCLUDE_vTaskCleanUpResources   0
#define INCLUDE_vTaskSuspend            1
#define INCLUDE_vTaskDelayUntil         1
#define INCLUDE_vTaskDelay              1

/* This is the raw value as per the Cortex-M3 NVIC.  Values can be 255
(lowest) to 0 (1?) (highest). */
#define configKERNEL_INTERRUPT_PRIORITY         255
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY    191 /* equivalent to 0xb0, or priority 11. */


/* This is the value being used as per the ST library which permits 16
priority values, 0 to 15.  This must correspond to the
configKERNEL_INTERRUPT_PRIORITY setting.  Here 15 corresponds to the lowest
NVIC value of 255. */
#define configLIBRARY_KERNEL_INTERRUPT_PRIORITY 15

Ответы [ 2 ]

2 голосов
/ 18 марта 2019

Ваш приоритет task_receive выше, чем приоритет task_send.taskYIELD будет запускать одну и ту же задачу вызова снова и снова, если нет задач с более высоким приоритетом.

Чтобы достичь желаемого, попробуйте изменить task_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
  }
}

Для получения дополнительной информации о задании YIELD, пожалуйста, обратитесь к следующему.

https://www.freertos.org/a00020.html#taskYIELD

0 голосов
/ 21 марта 2019

Проблема была решена путем обновления компилятора до последней версии.

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-bit, то код выполняется нормально. Его можно скачать здесь: https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads

...