[Опрос (закрыт)] блокировка поведения серийного.USB во время TX

victor_pv
Sun 20 августа 2017 г. 16:37
Существует очень долгая дискуссия о поведении Serialusb TX в разных ядрах и о позиции потери байтов.
В основном есть 2 разных способа управления USB -передачами, если хост не обрабатывает данные по скорости, которую отправляет MCU:
С одной стороны serialusb.write () может просто отбросить пакеты, а не блокировать после установленного периода времени ожидания, возвращая значение, которое указывает, сколько байтов может быть подходит в буфере TX. Период времени ожидания может быть жестким, или может быть изменен в соответствии с определенной скоростью передачи, поэтому тайм -аут, только если хост признает пакеты с более медленной скоростью.
С другой стороны, serialusb.write () может заблокировать неумело до тех пор, пока данные не будут в очереди для TX, и вернуться только в случае успешного в очереди в очереди.

Пожалуйста, проголосуйте ниже и добавьте любой дополнительный комментарий, который вы хотите добавить в ветку.

Martinayotte
Солнце 20 августа 2017 г. 16:50
Я проголосовал за «Другое» просто потому, что в старом Libmaple F4 уже есть начало решения, которое я использовал с некоторое время:
https: // github.com/rogerclarkmelbourne/ ... .H#166-L67
Пусть это может быть просто рассмотрена, предоставив дополнительный тайм -аут для EnabledBlockingTX () ...
Другими словами, я бы предпочел универсальное решение, которое охватывает все возможные случаи ! : ugeek:

Стивестронг
Sun 20 августа 2017 г., 8:42 вечера
Я с Мартином на этот раз.
Для приложений, где требуется высокая пропускная способность TX, необходимо предоставить, что хост способен на эту высокую скорость.
В противном случае следует выбрать желаемое поведение, блокировать или нет.

ZMEMW16
Солнце 20 августа 2017 г., 21:00
+1

Rogerclark
Солнце 20 августа 2017 г., 21:21
Определенно есть проблема с полной блокировкой, потому что, если вы запустите с сандируемой зарядной устройства или аккумулятором USB или забудьте, что есть сериал.Печать в некотором количестве кода.

Программа висит..

То же самое потенциально применяется, если терминал не открыт.

Я выбрал второй вариант, я.e Не блокируйте, но возвращайте, сколько места доступно, так как это позволило бы программе выбрать, чтобы заблокировать себя, если это необходимо

Однако, оглядываясь назад, я должен посмотреть, что сериал.Печать возвращается в остальной части мира Arduino. Например.на AVR и Due.

victor_pv
Пн 21 августа 2017 г. 12:57
Ребята, поскольку вариант, который не был включен, является тем, что, по -видимому, получает наибольшее количество голосов, я добавил его как отдельный вариант, чтобы отслеживать, сколько людей подходит для этого.
Пожалуйста, проголосуйте еще раз, так как изменение очистило голосование.

Но пока кажется лучшим вариантом - сделать его настраиваемым.
Я посмотрю на Teensy и с учетом кода, чтобы увидеть, что они делают, и это может быть по умолчанию, а затем настраивается, чтобы действовать напротив.

Rogerclark
Пн 21 августа 2017 г. 1:27
Виктор

Я знаю, что упоминал об этом раньше, но ....

Можете ли вы также посмотреть, что происходит в отношении DTR, Beause Afik Наша реализация Serialusb в настоящее время не ведет себя так же, как и Due или Teensy.
Я думаю, что разница в том, что мы не помещаем никаких данных в буфер USB TX, DTR не установлен (хост -терминал не активен), но другие доски все еще помещают вещи в буфер TX

В настоящее время у людей есть проблемы с Libmaple, не работающим правильно с некоторыми терминалами, которые не устанавливают DTR по умолчанию.
я.E нормальные доски Arduino работают с этими терминалами, но Libmaple не.

victor_pv
Пн 21 августа 2017 г. 2:46
Это то, что делает ядро ​​Due:
Serialusb TX поведение
https: // github.com/arduino/arduinocore- ... В.CPP#2264 /* Попробуйте отправить байты только в случае самого подключения CDC высокого уровня
открыт (не только труба) - ОС должна установить Linestate, когда порт
открыт и прочитывает Linestate, когда порт закрыт.
байты, отправленные перед пользователем, открывают соединение или после
соединение закрыто потеряно - как с UART. */
Linestate содержит 2 флаги, DTR и RTS, помимо скорости передачи и некоторой другой информации.
Код проверяет, если ставка строки != 0. В этом случае он отправляет.
Если Linestate равен 0, он даже не буферирует данные, просто возвращает 0 и устанавливает флаг.
Если Linestate != 0, затем пытается отправить данные и возвращает значение, указывающее, сколько оно отправило. Мне нужно больше выкопать в коде, чтобы увидеть, может ли он успешно отправить часть того, что запрашивается, но выглядит так.

Хорошо, кажется, что драйвер низкого уровня будет блокировать, пока EP не будет готов взять пакет. Таким образом, класс - это тот, который вернет 0, если строка закрыта, но она открыта, он блокирует.
Похоже, он не делает какого -либо буферизации, как мы делаем для TX, он идет прямо к буферу конечной точки, который для объемной передачи и USB FS - максимум 64 байта.
Там нет тайм -аута или чего -то подобного. Если линия будет открыта, она будет блокировать, если линия будет закрыта, она возвращается сразу же. Но открыта линия - это не просто хост, подключенный к USB, а скорее открыть приложение.
Я не уверен, что произойдет, если строка будет настроена, приложение откроет порт, затем удаляется кабель, и из комментариев в коде, тот, кто написал библиотеку, тоже не знает. // todo - ze - проверьте поведение на разных OSES и проверьте, что происходит, если
// открытое соединение не сломано чисто (кабель вырван, хост умирает
// или блокируется, или виртуальный последовательный порт виртуального виртуального порта)
Даже если нам удастся обнаружить линию открытой и закрытой правильно, мы можем не заблокировать слишком долго блокировать.

РЕДАКТИРОВАТЬ:
Поведение RX:
Он не будет наказывать пакеты RX, пока не сможет написать их в буфер класса. Поэтому, если приложение не читает или не читает достаточно быстро. Так что на RX не должно быть какого -либо капли, что, я думаю, является наиболее подходящим.

Rogerclark
Пн 21 августа 2017 г., 3:11
Спасибо

victor_pv
Пн 21 августа 2017 г. 12:57
Обновил предыдущий пост, чтобы добавить поведение RX в Due.

астер
Пт, сентябрь 01, 2017 22:04
может быть:
Настраивается во время выполнения (блокировка или не блокировка с небольшим тайм-аутом)
+
Если не установлено во время выполнения, используйте конфигурацию по умолчанию, например: она не должна блокировать и возвращать в начало, если в буфере нет места (возвращаемое значение указывает количество байтов в очереди для TX).

victor_pv
Сб 02 сентября 2017 г. 15:04
Похоже, что до сих пор в направлении наличия опции времени выполнения, чтобы сделать его блокировкой или не блокировать, возвращаемое значение должно соответствовать количеству байтов успешной очереди, а когда не блокирующий режим либо возвращается, либо с коротким тайм-аутом в зависимости на скорости запрошен.

Больше голосов или разных мнений о ожидаемом поведении?

fpistm
Сб 09 сентября 2017 12:57
На самом деле, я задаю себе тот же вопрос о поведении USB для ядра STM.
Итак, у меня такая же проблема, как у вас, и жду конца опроса : mrgreen:

victor_pv
Пн 11 сентября 2017 г. 1:14
Из комментариев каждого до сих пор и опроса, я думаю, что наилучшим ожидаемым поведением является:

-Если USB отключен, просто бросьте и вернитесь без тайм -аута, и не сберегайте в буфер. Возврат указывает на отправлено 0 байтов. Вот как работает Arduino Due.
-Если USB подключен, 2 возможно результаты:
  • По умолчанию попробуйте стоять в очередь в буфере и подождать периода времени ожидания. Такой тайм -аут, имитирующий скорость, с которой был открыт порт (115200, если ничего не было предоставлено). Если байты не могут быть отправлены в этом темпе, возврат, указывая, сколько было в очереди. Если эскиз заботится, чтобы проверить штраф возврата, если нет, то данные просто потеряны. Это более или менее то, как будет работать порт USART. Если поместить данные в линию вывода, но не все равно, если кто -нибудь слушает.
  • Во время выполнения вы можете установить тайм -аут на Max (допустим, 0xffff) или скорость BPS на 0, и если это так, функция отправки будет заблокировать бесконечно ожидание, пока не сможет отправить данные. Я думаю, что, если порт отключен от хоста после запуска эскиза, функция TX должна просто вернуться, не видите необходимости блокировать в этом случае, если кто -то не может это объяснить мне.


Подходит ли это всем нуждается?

Стивестронг
Пн 11 сентября 2017 г. 8:29 утра
Виктор, я бы вообще не использовал тайм -ауты, просто возвращайте NR байтов успешно отправленных, потому что, если Systick не используется, то время ожидания не будет работать.

Даниэфф
Пн 11 сентября 2017 г. 8:47 утра
[victor_pv - Пн 11 сентября 2017 г. 1:14] - Подходит ли это всем нуждается?
Я в порядке с этим.

Кстати, мои эксперименты с Windows10/USBSER.Sys Driver Show, что у него есть буфер 16K. Поэтому, если программа Host PC открывает COM -порт, но вообще ничего не читает, USB STM32 сможет мгновенно отправлять данные 16K, обойдя время ожидания вашего устройства.

victor_pv
Пн 11 сентября 2017 13:48
[Стивестронг - Пн 11 сентября 2017 г. 8:29] - Виктор, я бы вообще не использовал тайм -ауты, просто возвращайте NR байтов успешно отправленных, потому что, если Systick не используется, то время ожидания не будет работать.
Возможная проблема в том, что если вы делаете много серийных.Печать в ряд, заполняя буфер. Я не думаю, что кто -то проверяет возвращаемые значения, когда они пытаются печатать информацию, но в то же время они ожидают, что это будет отправлено, и не потеряет линию здесь или там.
Как я уже сказал. Это позволило бы не использовать Systick.

Давайте попробуем согласиться с тем, как управлять возможностями. Я предлагаю использовать begin (), так как он уже там. Представьте себе следующий случай (и добавьте или измените его, пока нам все понравится). /* This function is non-blocking. * * It copies data from a usercode buffer into the USB peripheral TX * buffer, and returns the number of bytes copied. */ uint32 usb_cdcacm_tx(const uint8* buf, uint32 len) { /* Last transmission hasn't finished, so abort. */ if (usb_cdcacm_is_transmitting()) { return 0; }

Fredbox
Пн 11 сентября 2017 г. 16:04
-Если USB отключен, просто бросьте и вернитесь без тайм -аута, и не сберегайте в буфер. Возврат указывает на отправлено 0 байтов. Вот как работает Arduino Due. +1

Стивестронг
Пн 11 сентября 2017 г. 16:09
Просто манекеня идея: как насчет
Сериал.начинать(<Baudrate>, Блокировка Bool = 1 или 0); // 0 за дефолт
В основном используйте второй параметр, чтобы указать опцию блокировки/не блокировки.

Кстати, Libmaple F4 USB Serial имеет эти 2 функции: #define VIDEO_FRAME_SIZE 6144 #define VIDEO_BUFFER_SIZE VIDEO_FRAME_SIZE * 2 uint8 videoBuffer[VIDEO_BUFFER_SIZE]; uint8 dmaBuffer[1028*2]; void setup() { Serial.begin(115200); while (!Serial) {} Serial.println(videoBuffer[0]); // Forcing linker to include the buffer on RAM for demo Serial.println(dmaBuffer[0]); // Forcing linker to include the buffer on RAM for demo } void loop() {}

Martinayotte
Пн 11 сентября 2017 г. 16:11
Верно !
Это то, что я сказал в другой ветке несколько недель назад.
UsbenableBlockingTX () может иметь новый аргумент для значения тайм -аута, а 0 или -1 могут навсегда указывать на блокирование...

victor_pv
Пн 11 сентября 2017 г. 18:08
Поэтому, если мы используем этот метод:
void setup() { } void loop() {}

Стивестронг
Вторник 12 сентября 2017 г. 8:26 утра
Поскольку я не предпочитаю тайм -аут, const int analogInPin = 11; const int pwmOutPin = PA1; int sensorValue = 0; int outputValue = 0; HardwareTimer pwmtimer(2); void setup() { pinMode(analogInPin, INPUT_ANALOG); Serial.begin(115200); pinMode(pwmOutPin, PWM); pwmtimer.pause(); pwmtimer.setPrescaleFactor(1); pwmtimer.setCount(0); //pwmtimer.setOverflow(4000); pwmtimer.setCompare(TIMER_CH2, 1000); pwmtimer.refresh(); pwmtimer.resume(); pinMode(pwmOutPin, PWM); } void loop() { sensorValue = analogRead(analogInPin); outputValue = map(sensorValue, 0, 4095, 0, 65535); pwmWrite(pwmOutPin, outputValue); Serial.print("sensor = " ); Serial.print(sensorValue); Serial.print("\t output = "); Serial.println(outputValue); }