Вопрос multiloop

igorlab

New member
Доброго дня!
Помогите разобраться с многопоточностью (если правильно назвал) на ESP32.
немного изменил скрипт примера

Код:
int i = 0;

void setup() {
  Serial.begin(115200);
  xTaskCreatePinnedToCore(loop1, "loop1", 4096, NULL, 1, NULL, 1);
  xTaskCreatePinnedToCore(loop2, "loop2", 4096, NULL, 1, NULL, 1);
}
void loop() {
  while (true) {  
    int command = Serial.read();//read a command  
    if (command == -1) break;//if no more commands, then exit
    else if (command == 't') {
      Serial.println("read 't'");
      i = -1;
    }
  }
}

void loop1(void *pvParameters) {
  while (1) {
    if (i == -1 ){
      Serial.println("loop изменил i на -1");
      i = 0;
    }  
    delay(100);
  }
}

void loop2(void *pvParameters) {
  while (1) {
    Serial.print("loop2 i = "); Serial.println(i);
    delay(500);
  }
}
код работает, при отправке из терминала 't' - loop1 реагирует только в том случае, если строка delay(100); не закомментирована - подскажите зачем там этот делей? и можно ли подобным образом сделать три loops - в одном будет код обработки датчиков, во втором код веб сервера, а в третьем код бота для телеграмма?
 

Юрий Ботов

Moderator
Команда форума
Cлово 'loop' в этом примере вас здорово запутало

Код:
int i = 0;
// это setup Arduino
void setup() {
    // инициализация устройств
    Serial.begin(115200);
    // а также датчиков и т.п.

    // пристегивание задач на выполнение операционной системе
    xTaskCreatePinnedToCore(task1, "task1", 4096, NULL, 1, NULL, 1);
    xTaskCreatePinnedToCore(task2, "task2", 4096, NULL, 1, NULL, 1);
    xTaskCreatePinnedToCore(task3, "task3", 4096, NULL, 1, NULL, 1);
}
// это loop Arduino - он должен быть пустым !
void loop() {}

// а вот это три задачи, в них то все и работает

// читает байт из serial, ждет команду 't' и  устанавливает флаг
void task3(void *pvParameters) {
    int command = -1;
    while (true) {
        if( Serial.available())
        {
            command = Serial.read();
            if(command == 't')
            {
                Serial.println("read 't'");
                i = -1;
            }
        }
        delay(10); // отпустите цикл, дайте драйверу Serial достучаться до процессора
    }
}
// время от времени отрабатывает команду и сбрасывает флаг
void task1(void *pvParameters) {
    while (1)
    {
        if (i == -1 )
        {
            Serial.println("task3 изменил i на -1");
            i = 0;
        }
        delay(100);
    }
}

// периодическая задача
void task2(void *pvParameters) {
    while (1)
    {
        Serial.print("task2 i = "); Serial.println(i);
        delay(500);
    }
}
К слову, в freertos есть специальные "флаги" не позволяющие наделать глупостей при "мультипоточности". Вариант с целой переменной может вызвать непредсказуемые ошибки (оптимизатор компилятора может засунуть ваш флажок в регистр и при выходе из прерывания или смене контекста флаг будет перезаливаться старый - неизмененный)
 
Последнее редактирование:

Алексей.

Active member
@igorlab,
В setup-е запускаете таски на первом ядре, а на каком работает loop не очевидно.
Для передачи флагов между тасками безболезненно использовать EventGroupHandle_t, а для передачи данных xQueueHandle.

П.С.
Результат запуска таска вы не проверяете, вдруг он (xTaskCreatePinnedToCore) вернет не pdPASS, а вы и не узнаете.
Может так и надо...
 
Последнее редактирование:

igorlab

New member
спасибо за ответы, и комментарии в коде!
/ это loop Arduino - он должен быть пустым ! - инересно, почему должен быть пустым? тем более, со знаком восклицания))
про xQueueHandle нагуглил здесь, сейчас знакомлюсь как его юзать
 

Юрий Ботов

Moderator
Команда форума
Должен быть пустым потому что "тасками"(tasks) операционка может корректно управлять: вытеснять их при необходимости, и т.п. а этот "квази loop" с точки зрения FreeRTOS это просто продолжение setup... он имеет право все нафиг завесить или к нему могут просто не вернуть управление если если при создании taskXX изменили приоритет на более высокий...
 
Сверху Снизу