Ник:
Пароль:

Контакты

E-mail: info@starterkit.ru
тел.: +7 922 680-21-73
тел.: +7 922 680-21-74
Телеграм: t.me/starterkit_ru

Способы оплаты

User Info


Добро пожаловать,
Guest

Регистрация или входРегистрация или вход
Потеряли пароль?Потеряли пароль?

Ник:
Пароль:

ПользователейПользователей:1
Поисковых ботовПоисковых ботов:3
ГостейГостей:1

ОбновитьПодробнееВсегоВсего:5
Форум » starterkit.ru » Процессорные модули » SK-A40i-SODIMM
UART: крик души
incredi
Добавлено 15.04.2024 17:01
0
Сообщение: 1
incredi
0

Пункты: 3192
Регистрация: 11.12.2014
Модуль на базе китайского процессора Allwinner A40i по функциональным возможностям и интерфейсу очень близок к ранее выпущенному на базе imx6; он дешевле и меньше по габаритам, т. е. представляет альтернативный выбор и может служить хорошей заменой. К сожалению, далеко не всегда.
В нашем случае используются непревзойденные по простоте и удобству каналы UART; модуль посылает короткие команды и получает в ответ блоки данных размером чуть больше 2 Кбайт. Из-за жестких ограничений по времени устанавливается максимальная скорость - 5 МБод. Китайский модуль при соответствующей конфигурации поддерживает эту скорость, но, оказалось, что прямой доступ к памяти не работает, поэтому, несмотря на наличие довольно большого - 64 байта - буфера FIFO, при приеме он неизбежно переполняется, т. е. данные теряются. Пришлось изменить программу и пересылать данные короткими блоками, не превосходящими размер FIFO (таких блоков оказалось 34); это помогло, но не сильно. В любом случае каждая пересылка требует изменения направления транзакции для синхронизации обмена; при этом наблюдается огромная задержка передачи в модуле: от момента вызова функции write() до фактического начала передачи проходит не менее 100 мксек, в то время как пересылка 64 байтов занимает 128 мксек, т. е. пропускная способность канала используется едва на 60%. Но это еще не все: в полудуплексном режиме сигнал переключения буфера RS-485 на прием по окончании передачи команды запаздывает примерно на те же 100 мксек (у модуля на imx6 - не более 15 мксек), т. е. от пропускной способности остается 30%. И если задержка передачи команды модулем проявляется в среднем, то абонент, пересылающий данные модулю, должен держать паузу по максимально возможной задержке переключения. Такие задержки, по-видимому, обусловлены механизмом низкоприоритетных прерываний от UART.
Таким образом, каналы UART модуля на Allwinner A40i имеют неприемлемо низкую пропускную способность, причина которой не в привязанности китайских разработчиков к архаичной 8-битовой архитектуре UART, а в отсутствии нормальной системной поддержки. Нужно либо подключить прямой доступ при приеме данных каналами UART, либо на порядок уменьшить латентность обслуживания прерываний от UART. Первый вариант значительно лучше, т. к. при длинных блоках делает задержки обслуживания несущественными и не требует переделки управляющих программ. Поскольку проблема не связана с аппаратной частью, а лежит исключительно в области программирования, она может быть решена за обозримое время.
Спуститься к концу Подняться к началу
Персональная информация
sasamy
Добавлено 15.04.2024 17:36 Сообщение: 2
sasamy
4.71

Пункты: 83558
Регистрация: 14.08.2009
Цитата

Модуль на базе китайского процессора Allwinner A40i по функциональным возможностям и интерфейсу очень близок к ранее выпущенному на базе imx6


у imx6 SDMA от слов Smart DMA - это перепрограммируемый микроконтроллер со своей микропрограммой которую они адаптиовали для работы с UART

Цитата

несмотря на наличие довольно большого - 64 байта - буфера FIFO, при приеме он неизбежно переполняется


неудивительно для "скорость - 5 МБод" - Linux это не RTOS и не гарантирует быстрый отклик на прерывания. На мой взляд тут не на маленькие пакетики надо разбивать а подправить драйвер UART и вместо прерываний создать отдельный поток ядра, вычитывать в цикле данных из FIFO и отправлять в tty
Спуститься к концу Подняться к началу
Персональная информация
sasamy
Добавлено 16.04.2024 14:21 Сообщение: 3
sasamy
4.71

Пункты: 83558
Регистрация: 14.08.2009
Цитата
подправить драйвер UART и вместо прерываний создать отдельный поток ядра, вычитывать в цикле данных из FIFO и отправлять в tty


можно не так радикально а просто в обработчике прерывания принятых данных отключать прерывание от этого порта и запускать поток с поллингом в ожидании других данных, после того как данных нет (определять по счётчику пустых циклов например) завершать поллинг и включать прерывания, примерно на таком принципе работает NAPI в сетеаой подсистеме для скоростных интерфейсов.

Можно для начала не мудрить с запуском потока а поллить прямо в обработчике прерывания - на скорости 5 мбод это мне кажется не так критично.

вот тут обработчик прерывания от принятых данных

https://elixir.bootlin.com/linux/v6.1-rc6/source/drivers/tty/serial/8250/8250_port.c#L1944

вместо прямого вызова serial8250_rx_chars

https://elixir.bootlin.com/linux/v6.1-rc6/source/drivers/tty/serial/8250/8250_port.c#L1794

добавить цикл с опросом наличия данных в FIFO и вызывать serial8250_rx_chars когда чтото появилось

надо только подогнать количество пустых циклов чтобы не зависать в обработчике прерывания слишком надолго
Спуститься к концу Подняться к началу
Персональная информация
sasamy
Добавлено 16.04.2024 14:55 Сообщение: 4
sasamy
4.71

Пункты: 83558
Регистрация: 14.08.2009
Цитата

надо только подогнать количество пустых циклов чтобы не зависать в обработчике прерывания слишком надолго


и вынести обработчик этого прерывания на отдельное ядро - тогда вообще минимальный вред будет от такого поллинга в обработчике прерывания

http://starterkit.ru/html/index.php?name=forum&op=view&id=31658#31659
Спуститься к концу Подняться к началу
Персональная информация
sasamy
Добавлено 16.04.2024 18:14 Сообщение: 5
sasamy
4.71

Пункты: 83558
Регистрация: 14.08.2009
Цитата

вот тут обработчик прерывания от принятых данных

https://elixir.bootlin.com/linux/v6.1-rc6/source/drivers/tty/serial/8250/8250_port.c#L1944

вместо прямого вызова serial8250_rx_chars

https://elixir.bootlin.com/linux/v6.1-rc6/source/drivers/tty/serial/8250/8250_port.c#L1794

добавить цикл с опросом наличия данных в FIFO и вызывать serial8250_rx_chars когда чтото появилось

надо только подогнать количество пустых циклов чтобы не зависать в обработчике прерывания слишком надолго


например так

Цитата

if (status & (UART_LSR_DR | UART_LSR_BI) && !skip_rx) {
if (!up->dma || handle_rx_dma(up, iir)) {
do {
status = serial8250_rx_chars(up, status);
udelay(10); // если не конец пакета за это время должны прийти новые данные
status = serial_in(up, UART_LSR);
} while (status & (UART_LSR_DR | UART_LSR_BI));
}
}
Спуститься к концу Подняться к началу
Персональная информация
Форум » starterkit.ru » Процессорные модули » SK-A40i-SODIMM