• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Нужна помощь семафоры

igorlab

New member
Доброго дня, ардуинщики :)
помогите пожалуйста разобраться с семафорами:

по прочтеному в нете полагал, что если в коде таска встретился xSemaphoreTake( stD_Sem, portMAX_DELAY); то пока таск не получит этот семафор - код выполняться не будет, но по факту - код выполняется

код который должен ждать пока не закончат вращаться двигатели
Код:
void Task_run(void *pvParameters)  // This is a task.
{
  for (;;)
  {
    xSemaphoreTake( run_Sem, portMAX_DELAY);
    for (int n = 0; n < 3; n++) {
      Serial.print("loop 1 # "); Serial.println(String(n));
      int steps = 1000;
      xQueueSend( d_Steps_Queue, &steps, 0 );
      xSemaphoreTake( stD_Sem, portMAX_DELAY);// должно приостановиться здесь до выполнения таска прочитавшего из очереди d_Steps_Queue, по факту не останавливается
      vTaskDelay(5000 / portTICK_PERIOD_MS);
    }
    Serial.println("run finished");
  }
}
код который вращает двигатели:

Код:
if (xQueueReceive(d_Steps_Queue, &steps, portMAX_DELAY)) // берет из очереди количество шагов
    {
      for (int i = 0; i < steps; i++) {
        digitalWrite(MOTOR__enable_r,  LOW); // enable stepper
        for (int pos = 0; pos < steps; pos++) {
          digitalWrite(MOTOR_STEP_PIN_r, HIGH);
          vTaskDelay(delayms / portTICK_PERIOD_MS); // delay x 1ms
          digitalWrite(MOTOR_STEP_PIN_r, LOW);
          vTaskDelay(delayms / portTICK_PERIOD_MS); // delay x 1ms  
          //Serial.println("pos = " + String(pos));
        }
        digitalWrite(MOTOR__enable_r,  HIGH); // disable stepper
        xSemaphoreGive(stD_Sem);
      }
    }
 

igorlab

New member
xSemaphoreGive(stD_Sem); - это типа я уже закончил крутить двигателями, продолжай выполнять код
 

Алексей.

Active member
А, семафоры вам для чего? Создали бы группу, перед отправкой в очередь установили бы бит в группе, отправили бы команду в очередь и ждали бы пока другой таск этот бит не очистит.
 

igorlab

New member
" установили бы бит в группе" @Алексей. Вы имеете ввиду очередь? это мое первое знакомство с многопоточностью поэтому и решил, что семафоры подходят для моей цели
 

nikolz

Well-known member
" установили бы бит в группе" @Алексей. Вы имеете ввиду очередь? это мое первое знакомство с многопоточностью поэтому и решил, что семафоры подходят для моей цели
посмотрите это:
FreeRTOS: практическое применение, часть 3 (управление прерываниями) | arm | programming
 

Алексей.

Active member
" установили бы бит в группе" @Алексей. Вы имеете ввиду очередь?
EventGroupHandle_t
Для передачи эвентов между тасками есть апи которое позволяет устанавливать/сбрасывать и ожидать эветты в тасках.
Простой пример, в одном таске отправляю команду в очередь и жду завершения выполнения команды, в другом таске получаю команду, выполняю и устанавливаю эвент.
Код:
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/event_groups.h"
#include "Arduino.h"

#define MY_WRITE_QUEUE_SIZE 12
#define MY_TASK_PRIORITY    4
#define MY_TASK_STACK       1024
#define MY_TASK_CORE        1

const EventBits_t my_bit = BIT0;
xQueueHandle queue;
EventGroupHandle_t eventGroup;

void Task1(void *pvParameters) {
  for (; ; ) {
    int value = 0;
    Serial.println("Sending to queue");
    // Отправляем в очередь команду
    xQueueSend(queue, &value, 1);
    // Ждем завершения выполнения команды
    xEventGroupWaitBits(eventGroup, my_bit, pdFALSE, pdTRUE, portMAX_DELAY);
    // Спим 5 секунд
    vTaskDelay(5000 / portTICK_PERIOD_MS);
  }
}

void Task2(void *pvParameters) {
  for (; ; ) {
    int value;
    // Ожидаем поступления команды
    if (xQueueReceive(queue, &value, portMAX_DELAY) == pdTRUE) {
      Serial.println("Command is received");
      vTaskDelay(2000 / portTICK_PERIOD_MS);
      Serial.println("Command is executed");
      xEventGroupSetBits(eventGroup, my_bit);
    }
  }
}

void setup() {
  Serial.begin(115200);
  eventGroup = xEventGroupCreate();
  queue = xQueueCreate(MY_WRITE_QUEUE_SIZE, sizeof(int));
  xTaskCreatePinnedToCore(Task1, "Task1", MY_TASK_STACK, NULL, MY_TASK_PRIORITY, NULL, MY_TASK_CORE);
  xTaskCreatePinnedToCore(Task2, "Task2", MY_TASK_STACK, NULL, MY_TASK_PRIORITY, NULL, MY_TASK_CORE);
}

void loop() {
}
 
Сверху Снизу