• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе 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() {
}
 
Сверху Снизу