Скрыть объявление
На нашем форуме недоступен просмотр изображений для неавторизованных пользователей. Если Вы уже зарегистрированы на нашем форуме, то можете войти. Если у Вас еще нет аккаунта, мы будем рады, если Вы к нам присоединитесь. Зарегистрироваться Вы можете здесь.

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

Тема в разделе "FreeRTOS", создана пользователем igorlab, 12 апр 2019.

  1. igorlab

    igorlab Новичок

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

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

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

    Код (C):
    1. if (xQueueReceive(d_Steps_Queue, &steps, portMAX_DELAY)) // берет из очереди количество шагов
    2.     {
    3.       for (int i = 0; i < steps; i++) {
    4.         digitalWrite(MOTOR__enable_r,  LOW); // enable stepper
    5.         for (int pos = 0; pos < steps; pos++) {
    6.           digitalWrite(MOTOR_STEP_PIN_r, HIGH);
    7.           vTaskDelay(delayms / portTICK_PERIOD_MS); // delay x 1ms
    8.           digitalWrite(MOTOR_STEP_PIN_r, LOW);
    9.           vTaskDelay(delayms / portTICK_PERIOD_MS); // delay x 1ms  
    10.           //Serial.println("pos = " + String(pos));
    11.         }
    12.         digitalWrite(MOTOR__enable_r,  HIGH); // disable stepper
    13.         xSemaphoreGive(stD_Sem);
    14.       }
    15.     }
     
  2. igorlab

    igorlab Новичок

    Сообщения:
    29
    Симпатии:
    1
    xSemaphoreGive(stD_Sem); - это типа я уже закончил крутить двигателями, продолжай выполнять код
     
  3. Алексей.

    Алексей. Авторитетный участник сообщества

    Сообщения:
    483
    Симпатии:
    58
    А, семафоры вам для чего? Создали бы группу, перед отправкой в очередь установили бы бит в группе, отправили бы команду в очередь и ждали бы пока другой таск этот бит не очистит.
     
    igorlab нравится это.
  4. igorlab

    igorlab Новичок

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

    nikolz Гуру

    Сообщения:
    3.668
    Симпатии:
    399
    посмотрите это:
    FreeRTOS: практическое применение, часть 3 (управление прерываниями) | arm | programming
     
    igorlab нравится это.
  6. Алексей.

    Алексей. Авторитетный участник сообщества

    Сообщения:
    483
    Симпатии:
    58
    EventGroupHandle_t
    Для передачи эвентов между тасками есть апи которое позволяет устанавливать/сбрасывать и ожидать эветты в тасках.
    Простой пример, в одном таске отправляю команду в очередь и жду завершения выполнения команды, в другом таске получаю команду, выполняю и устанавливаю эвент.
    Раскрыть Спойлер
    Код (Text):
    1.  
    2. #include "freertos/FreeRTOS.h"
    3. #include "freertos/task.h"
    4. #include "freertos/queue.h"
    5. #include "freertos/event_groups.h"
    6. #include "Arduino.h"
    7.  
    8. #define MY_WRITE_QUEUE_SIZE 12
    9. #define MY_TASK_PRIORITY    4
    10. #define MY_TASK_STACK       1024
    11. #define MY_TASK_CORE        1
    12.  
    13. const EventBits_t my_bit = BIT0;
    14. xQueueHandle queue;
    15. EventGroupHandle_t eventGroup;
    16.  
    17. void Task1(void *pvParameters) {
    18.   for (; ; ) {
    19.     int value = 0;
    20.     Serial.println("Sending to queue");
    21.     // Отправляем в очередь команду
    22.     xQueueSend(queue, &value, 1);
    23.     // Ждем завершения выполнения команды
    24.     xEventGroupWaitBits(eventGroup, my_bit, pdFALSE, pdTRUE, portMAX_DELAY);
    25.     // Спим 5 секунд
    26.     vTaskDelay(5000 / portTICK_PERIOD_MS);
    27.   }
    28. }
    29.  
    30. void Task2(void *pvParameters) {
    31.   for (; ; ) {
    32.     int value;
    33.     // Ожидаем поступления команды
    34.     if (xQueueReceive(queue, &value, portMAX_DELAY) == pdTRUE) {
    35.       Serial.println("Command is received");
    36.       vTaskDelay(2000 / portTICK_PERIOD_MS);
    37.       Serial.println("Command is executed");
    38.       xEventGroupSetBits(eventGroup, my_bit);
    39.     }
    40.   }
    41. }
    42.  
    43. void setup() {
    44.   Serial.begin(115200);
    45.   eventGroup = xEventGroupCreate();
    46.   queue = xQueueCreate(MY_WRITE_QUEUE_SIZE, sizeof(int));
    47.   xTaskCreatePinnedToCore(Task1, "Task1", MY_TASK_STACK, NULL, MY_TASK_PRIORITY, NULL, MY_TASK_CORE);
    48.   xTaskCreatePinnedToCore(Task2, "Task2", MY_TASK_STACK, NULL, MY_TASK_PRIORITY, NULL, MY_TASK_CORE);
    49. }
    50.  
    51. void loop() {
    52. }
    53.  
    54.  
     
    igorlab нравится это.
  7. igorlab

    igorlab Новичок

    Сообщения:
    29
    Симпатии:
    1
    спасибо за подсказки, пригодились и семафоры и ивенты
     

Поделиться этой страницей