Как я могу отправлять и получать символ из одной задачи в другую задачу с помощью queue на FreeRTOS?

#arduino #embedded #multitasking #freertos

#arduino #встроенный #многозадачность #фриртос

Вопрос:

Когда я пытаюсь отправить переменную из задачи в другую задачу, я ничего не могу получить с помощью xQueueReceive. Я использую UART и Arduino Mega. Я отправлю символ в Arduino, затем Arduino отправит этот символ на другое устройство. Но я не могу получить никакого результата. Вот мой код:

 #include <Arduino_FreeRTOS.h>
#include <semphr.h>
#include <queue.h>

SemaphoreHandle_t xSerialSemaphore;
QueueHandle_t queue;

void TaskWrite( void *pvParameters );
void TaskRead( void *pvParameters );

void setup() {
  Serial.begin(9600);
  
  if ( xSerialSemaphore == NULL )  
  {
    xSerialSemaphore = xSemaphoreCreateMutex(); 
    if ( ( xSerialSemaphore ) != NULL )
      xSemaphoreGive( ( xSerialSemaphore ) ); 
  }

  queue = xQueueCreate(15, sizeof(int));
  if (queue == NULL) {
    Serial.println("Queue can not be created");
  }
  // Now set up two Tasks to run independently.
  xTaskCreate
    TaskDigitalRead
    , "Read"  
    ,  256  
    ,  NULL
    ,  2  
    ,  NULL );

  xTaskCreate(
    TaskWrite
    , "Write"
    ,  256  
    ,  NULL
    ,  1  
    ,  NULL );
}

void loop()
{
  // Empty. Things are done in Tasks.
}

void TaskRead( void *pvParameters __attribute__((unused)) )
{
  int c = 0;
  for (;;) 
  {
    if ( xSemaphoreTake( xSerialSemaphore, ( TickType_t ) 5 ) == pdTRUE )
    {
      xQueueReceive(queue, amp;c, 1000);
      Serial.println(c);
      xSemaphoreGive( xSerialSemaphore );
    }

    vTaskDelay(1); 
  }
}

void TaskWrite( void *pvParameters __attribute__((unused)) )
{

  for (;;)
  {
    if ( xSemaphoreTake( xSerialSemaphore, ( TickType_t ) 5 ) == pdTRUE )
    {
     if(Serial.available()>0)
     {
      int c = Serial.read();
      Serial.print("I received ");
      Serial.println(c);
      xQueueSend(queue, (void *)amp;c, 1000);
     }

      xSemaphoreGive( xSerialSemaphore );
    }

    vTaskDelay(1);
  }
} 
 

Если я включу строку xQueueReceive, я ничего не увижу на последовательном мониторе.

Комментарии:

1. Вам не нужен семафор. Просто заполните (потокобезопасную) очередь в одной задаче / irq и прочитайте ее из другой. Читайте также документы: freertos.org/Embedded-RTOS-Queues.html

Ответ №1:

Похоже, что может возникнуть условие прерывания гонки, если TaskRead сначала принимает семафор, пока очередь еще пуста. Почему бы просто не заблокировать TaskRead в xQueueReceive? Какова вообще цель семафора? Если вам действительно нужно защитить серийный номер самостоятельно, лучше используйте мьютекс для доступа к Serial.