Библиотека Ethernet: фрагментированные отправленные пакеты

Фоно
Сб 24 сентября 2016 г. 8:50 утра
Привет,
У меня странное поведение с Seeed W5200 Щит
У меня есть приложение с использованием платы Olimex STM32 и W5200 Ethernet Shield, где я общаюсь в TCP с внешней системой.
Приложение было написано с помощью Maple IDE и работает довольно хорошо, за исключением случайных ошибок общения, которые я не исследовал.
Я переношу это в Arduino IDE, и у меня есть многочисленные ошибки, которые я исследовал.
Что происходит, так это то, что внешняя система ожидает, что кадры TCP в режиме символов, и каждая команда должна содержаться в одном кадре, которые будут правильно декодированы на внешней системе. Примеры:
Запрос на статус - «FPR».
Команда "fpr remote = on".
Что происходит так часто (каждый раз !) команда вырезана в двух, например:
"F" тогда "PR"
Другой пример:
"FPR Remot", затем "E = ON".
Я имею в виду, что команда отправляется в два последовательных кадра TCP (проверила это как с внешним приложением, которое протестует о усеченных командах, а также путем анализа трафика с использованием Wireshark).
В обеих средах программирования оператор, который отправляет команду:
Клиент.println ("fpr remote = on");
Странный ! У кого есть идея?
заранее спасибо.

Фоно
Ср. 05 октября 2016 г., 19:19
Всем привет,
С момента моего последнего поста я дополнительно исследовал использование Wireshark, чтобы попытаться увидеть, в чем разница между рамками Ethernet, отправленными в обоих случаях: при компиляции с Maple IDE и при компиляции с добавлением Arduino+STM32.
Я действительно удивлен тем, что вижу.
С Maple IDE, когда я отправляю строку, такую ​​как «Hello World \ r \ n», я получаю 3 кадра:
"Привет, мир", затем "\ r", затем "\ n".
Что уже сомнительно.
Но когда я компилируюсь с Arduino IDE, я получаю ровно одну кадр для каждого персонажа !!
Я сравнил библиотеки Ethernet в обеих средах, и в основном они делают то же самое, и они инициализируют W5200 с одинаковыми параметрами.
Ну и что??

Rogerclark
Ср. 05 октября 2016 г., 19:48
Время?

Попробуйте внести некоторые задержки и замедлить SPI до более медленной тактовой частоты, как это возможно, что модуль не настроен на то же самое

В последнее время у меня была аналогичная проблема, где на Maple Mini, на другом модуле, где требовалась задержка между CS, и передачи SPI.
Также мне нужно было поместить разрыв между каждым байтом SPI, так как модуль не смог справиться с командой Readgister, следовавшей сразу же SPI.переводы для чтения данных.

Он почти работал без изменений, но, как ни странно, он сбросил 1 бит входящих данных, возможно, MSB в 32 -битном регистре чтения.

Фоно
Солнце 09 октября 2016 г. 15:53
Всем привет,
Я засел на обнаружение глубокой причины проблемы сообщений, разбросанных по нескольким кадрам Ethernet.
Механизм заключается в следующем.
Класс EthernetClient имеет 23 метода Print (), которые он унаследовал от класса печати после цепочки наследства в будущем:
Print - Stream - Client - EthernetClient.
Есть 3 метода записи (), также унаследованные от печати. Они были перегружены тремя методами, определенными в классе EthernetClient. К сожалению, метод из класса EthernetClient определяется:
size_t write (const uint8_t *buf, size_t size);
Принимая во внимание, что соответствующий метод из класса печати определен:
size_t write (const void *buf, uint32 len);
В результате перегрузка не работает.
В любом случае, это не причина. Он заключается в том, что каждый из 23 методов Print () в конечном итоге вызывает
size_t print (char);
от класса печати, который, в свою очередь, позвонит
size_t write (uint8_t);
от класса EthernetClient,
Последний метод вызывается один раз для каждого из символов, созданных выбранным вариантом из 23 методов print ().
Этот метод строит один полный кадр Ethernet каждый раз, когда он вызывается, таким образом, любой вызов любого метода print () будет разбросан на столько кадров, как и количество символов, которые будут отправлены.
Это приводит к очень неэффективной передаче, и в моем случае, к системе, полностью нарушенной и непригодным для использования.
Правильный способ сделать это - открыть буфер, поместить в него все сгенерированные символы (включая окончательный CR LF для методов Println), а затем отправить эту строку в метод
size_t write (const uint8_t *buf, size_t size);
от класса EthernetClient.
Тем не менее, я не вижу никаких простых средств для этого, за исключением перегрузки почти всех методов Print () в классе EthernetClient.
Что ты об этом думаешь?
Не могли бы вы порекомендовать использовать унаследованные методы печати, когда производительность не возникает проблемы, и явно используйте Sprintf + Write (BUF, LEN) в другом случае? Или вы думаете, что должен быть написан новый набор методов печати?

Rogerclark
Вт 11 октября 2016 г., 8:50 вечера
Является ли аргумент void *BUF в функции печати Libmaple, отличающийся от официального кода Arduino E E.глин. Для плат AVR или SAM, я думаю, это может быть?

Вы пробовали изменить void *, в печати, чтобы увидеть, собирает ли Libmaple, я.E Есть ли места в Либмапле, которые проходят void * к этой функции, которые дают ошибку или предупреждение, если функция печати изменена ?

Фоно
Вт 11 октября 2016 г., 21:03
Класс печати Libmaple идентичен группу Arduino, за исключением того, что в версии Arduino каждая функция возвращает количество печатных символов, тогда как функции Libmaple имеют тип void.
Таким образом, такая же проблема существует в любом случае: один персонаж в одном кадре.

Rogerclark
Вт 11 октября 2016 г., 21:20
ХОРОШО

Я помню, что я исправил некоторые серийные функции Libmaple, которые не вернули количество написанных байтов и т. Д., Но я, должно быть, не заметил их всех

Если вы измените функцию на возвращение номера байтов, исправит ли она вашу проблему ?

Если это так, можете ли вы создать PR с необходимыми изменениями?

Фоно
Вт 11 октября 2016 г., 21:42
Проблема не имеет ничего общего с возвращающимися функциями или нет количество печатных символов.
Как я уже сказал:
Он заключается в том, что каждый из 23 методов Print () в конечном итоге вызывает
size_t print (char);
от класса печати, который, в свою очередь, позвонит
size_t write (uint8_t); от класса EthernetClient
Этот метод отправляет кадр каждый раз, когда его называют, только для одного символа.
Таким образом, любой призыв к любому методу print () будет разбросан на столько кадров, сколько и количества отправленных символов.
Такое поведение хорошо для печати символов, но неуместно для отправки сообщений Ethernet, которые могут содержать более 1000 символов в одном кадре.
Что нам нужно, так это то, что призывы к печати (char) не активируют отправку кадры, а просто храните произведенные символы в буфере, пока вызов специального метода не отправит буфер сразу.
Тем не менее, я не вижу, как это сделать без изменения класса печати, который принадлежит ядро. Как вы думаете, нам разрешено сделать это (ради совместимости с текущими разработками Arduino, я имею в виду)?

Rogerclark
Вт 11 октября 2016 г., 22:42
@Phono

Будет ли библиотека Ethernet сделать то же самое, если бы она была запущена на досках Arduino Sam или AVR, или их код отличается, поэтому у него нет этой проблемы?

Я не склоняюсь к изменению класса печати в соответствии с Arduino Sam Core, (хотя и до тех пор, пока это не вызывает огромного волнового эффекта по всему Libmaple_

Стивестронг
Вт 11 октября 2016 г., 22:53
Странно, у меня есть Arduino, совместимая с модулем Atmega128a и Wiz5500 над SPI, она отправляет несколько байтов (я использую до 150) в одном пакете TCP...

Фоно
Ср 12 октября 2016 г. 6:54
Хорошо, я думаю, что есть двусмысленность в именах библиотек.
Когда я говорю о Libmaple, я говорю о том, что поставляется с Maple IDE. Когда я говорю код Arduino, я имею в виду это с пути
D: \ arduinoforstm32 \ arduino-1.6.9 \ ardware \ arduino_stm32-master \ stm32f1 \
Методы print () из класса печати отличаются только от того факта, что в исходном IDE все методы print () ничего не возвращают.
Что касается замечания Стивестронга, я посмотрел на класс печати из AVR Core.
Вы печатали струны в Ethernet?
Вот иначе. Методы печати (*char) и все его варианты фактически включают в себя следующий вызов
написать ((const uint8_t *) str, strlen (str));
Метод записи (*buf, длина) перегружен одним из класса EthernetClient, который фактически отправляет строку сразу, а затем отправляет кадр Ethernet.
Так что это основное различие, которое не сложно изменить в Libmaple.
Однако это относится только к строкам. При печати номера (целочисленное или плавание) они преобразуются в символы и отправляют по одному символу за раз, то есть по одному рамке Ethernet для каждого символа. Это верно как для оригинальной библиотеки Arduino, так и для Libmaple.
Подводя итог, легко решить проблему в Libmaple для строк, но проблема остается для печати номеров.
Я думаю, что это очень грубый способ справиться с коммуникацией Ethernet, который тогда не более быстрее, чем просто серийная ссылка.
Конечно, можно использовать Sprintf (буфер, формат, переменная, ...) Затем распечатайте буфер, используя поставляемый метод печати. Но все же, я думаю, что жаль есть методы печати, которые делают вещи неэффективно.

Стивестронг
Ср 12 октября 2016 г. 8:57
В моем коде я использую обе версии: eth.print(*buf);

Фоно
Чт 17 ноября 2016 г., 10:03
Я удивлен, что призыв eth.print(*buf);