USB-CDC иногда теряет куски текста при передаче. ESP32-S3

Это хрень полная. Даже у меня, рукожопа-любителя :sweat_smile: никогда такого небыло.
Я больше грешу на “приёмник”, шнур, USB разъём. Согласен с @andriano:

У ESP32, вроде бы, по умолчанию, скорость 115200. Может быть многовато.

во флэш льёт, читает со скоростью 900к, думаю нормально

1 лайк

Я “многовато” имел ввиду “приёмник”. Для ESP32, конечно норм, не дураки же это так задумали

приёмник должен кушать два мегабита влёгкую

1 лайк

Приёмник здесь лаптоп, что за Ось, какие процессы запущены - неизвестно…
Состояние USB разъёма , кабель, тоже учесть

TeraTerm

код:


#include <Arduino.h>

#include <stdatomic.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <time.h>

#include <freertos/FreeRTOS.h>
#include <freertos/semphr.h>
#include <freertos/task.h>

// Send characters to user terminal
//
extern "C" int console_write_bytes1(const void *buf, size_t len) {
  int len0 = len;
  while( true ) {
    int space = Serial.availableForWrite(), w;  // <----- does not work (see screenshot above)
    // int space = 1, w; // <----- this byte-by-byte approach works.
    if (space) {
      if (space >= len) {
        len0 = Serial.write((const uint8_t *)buf, len);
        Serial.flush();
        return len0;
      }
      w = Serial.write((const uint8_t *)buf, space);
      Serial.flush();
      buf += w;
      len -= w;
    } else
      portYIELD();
  }
  return len0;
}

void setup() {
  Serial.begin(115200);
  delay(1000);
}

void loop() {
  for (int i = 0; i < 100; i++) {
    const char *t = "asdffffffffff khkjhkjhdf";
    console_write_bytes1(t,strlen(t));
    console_write_bytes1(t,strlen(t));
    console_write_bytes1(t,strlen(t));
    console_write_bytes1("\r\n",2);
  }
}

Скринщот без вызова flush() я не пнривожу но там каша. 50 процентов каши и перепутанных слов, пропавших слов.

PS: код выше - минимальный код, который был в си файле, но вот я засунул его в .ино, и результат такой же

Ну так, вместо flush() можно delayMicroseconds() добавить, возможно тот же результат будет.
Надо проверить на другом компе, да с другим шнуром.
Скорость понизить попробовать

Вот, простейший код. В симуляторе норм.

Спойлер

void writeStr(const char * pstr)
{
  uint16_t index = 0;
  char s;
  while((s  = *(pstr + index++)) != NULL)
  Serial.write(s);
   index = 0;
}

void setup() {
  Serial.begin(115200);
  Serial.println("Hello, ESP32-S3!");
}

void loop() {
   const char *t = "asdffffffffff khkjhkjhdf";
  
  for (int i = 0; i < 100; i++) {
   writeStr(t);
    writeStr(t);
     writeStr(t);
     Serial.println(); 
  }
}
Спойлер

P.S А ведь ещё на ESP32 есть же многозадачность. Можно приоритеты выставлять в менеджере. Как то игрался, ещё помню, что в каждом процессе желательно делать delay(), чтобы дать время другим, но это всё слова дилетанта))

ну вот в функции выше, если буфер передачи забит, я делаю portYIELD() (тот же эффект, что и delay()).

надо бы проверить, короче говоря, на другой ЕСПшке. С другим кабелем. А то все на мистику какую-то смахивает.

это ты не видишь как высоколобые на новой плате UNO Q пытаются светодиодиком поморгать )))

Короче я идиот. Купил новый кабель и больше не могу воспроизвести проблему. Закрыл тикет в багтрекере. Радуюсь теперь.

1 лайк

Это ведь твоя тема:
Espshell…
А я тебе рассказываю:

Вот потеха :laughing:

бывает :slight_smile:

А вот нифига. Таки баг в ардуине этой вашей, на есп32 пиленой. Баг я им открыл по-новой.

Короче говоря: если у вас есть задача, которая запущена на ядре отличном от того, на котором запущены Arduino & Events (см. Arduino IDE→Tools→Arduino runs on Core 1 и IDE→Tools→Events runs on Core 1), то Serial.write() , и, соответтственно все на его основе (print и printf например) - глючат.

Пруф оф концепт простой: запускаете задачу на ядре 0, которая печатает всякое на экран в цикле. Будет каша-малаша.

Зря кабель новый покупал.

Ты бы выложил простой пример с конкретной проблемой, чтоб запустить можно было. Здесь же есть спецы по этому камню, и не только, может ответят.

Признали они баг. Проблемный процессор: прерывания генерирует то ядро, на котором регистрировали обработчик. Но вроде пишут, что знают, как починить.

Код простой (sketch.ino):



#include <Arduino.h>
#include "sdkconfig.h"
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>


void setup() {
  Serial.begin(115200);

}

#define console_write_bytes(X,Y) Serial.write((const uint8_t *)X, Y)

void loop_core0(void *arg) {

  arg = arg;
  while (1) {
    for (int i = 0; i < 25; i++) {
      const char *t = "Lorem ipsum dolor +";
      char num[] = { 0, ':', 0 };
      uint8_t r = 5; //esp_random();
      num[0] = '0' + r;
      console_write_bytes(num, 2);
      while(r-- > 0)
        console_write_bytes(t, strlen(t));
      console_write_bytes("\r\n", 2);
    }

    console_write_bytes("\r\n", 2);
    console_write_bytes("\r\n", 2);
    console_write_bytes("\r\n", 2);

    delay(5000);
  }
}

void loop() {

  TaskHandle_t handle;
  xTaskCreatePinnedToCore((TaskFunction_t)loop_core0, "test", 5*1024, NULL, 0 /* Prio */, &handle, 0 /* Core */);

  while(1)
    delay(9999);
}

Настройки Ардуино ИДЕ такие:

Target = “ESP32S3 Dev Module”

Код скетча замысловато вызывает (ну или уже не замысловато) Serial.write(). Вместо красивой портянки на экране получается некрасивая.

Вся проблема в том, что печать производится из ядра 0, а Serial.begin() был вызван на ядре 1. И это приводит к проблеме: