Ник:
Пароль:

Контакты

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

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

User Info


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

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

Ник:
Пароль:

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

ОбновитьПодробнееВсегоВсего:6
Форум » starterkit.ru » Процессорные модули » ES-T113-NANO(-LV), SK-T113-MOD
Вопросы по схеме, SPI & UART
sasamy
Добавлено 06.03.2025 13:04 Сообщение: 11
sasamy
4.71

Пункты: 92929
Регистрация: 14.08.2009
Цитата
Еще по ttyS2: сделал тест, передает и принимает. TX замкнут на RX.
Для больших пакетов до 128 байт - правильно, далее идут ошибки.


код теста можно посмотреть? fifo описан аппаратный - нет смысла добавлять несуществующую память
Спуститься к концу Подняться к началу
Персональная информация
Hsb
Добавлено 06.03.2025 13:19 Сообщение: 12
Hsb
0

Пункты: 307
Регистрация: 18.02.2025
256 - аппаратный, но скорость большая, надо большой буфер, в несколько Кб, чтобы пользовательская программа раз в тик могла без потерь получить все принятое.
Тест (нашел какой-то прототип и доработал):
//const int MAXDATASIZE = 512;
const int MAXDATASIZE = 16*2*2*2*2;

serialfd = open( "/dev/ttyS2", O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
//serialfd = open( "/dev/tty2", O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);

if (serialfd == -1)
{
/*
* Could not open the port.
*/
printf("\t\nUnable to open port: ");
}
else
{
printf("\t\nConnected to serial port: ");

fcntl(serialfd, F_SETFL, 0);
}
struct termios options;

/*
* Get the current options for the port...
*/
tcgetattr(serialfd, &options);

/*
* Set the baud rates to 9600...
*/
cfsetispeed(&options, B4000000);
cfsetospeed(&options, B4000000);

/*
* 8N1
* Data bits - 8
* Parity - None
* Stop bits - 1
*/
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;

/*
* Disable hardware flow control
*/
options.c_cflag &= ~CRTSCTS;

/*
* Enable the receiver and set local mode...
*/
options.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
| INLCR | IGNCR | ICRNL | IXON);
options.c_oflag &= ~OPOST;
options.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);

options.c_cflag |= (CLOCAL | CREAD);
options.c_cflag &= ~(CSIZE | PARENB);
options.c_cflag |= CS8;

options.c_iflag &= ~(IXON | IXOFF | IXANY| INLCR |ICRNL);// turn off s/w flow ctrl
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // make raw
options.c_oflag &= ~OPOST; // make raw


// Flush the earlier data
tcflush(serialfd, TCIFLUSH);

/*
* Set the new options for the port...
*/
tcsetattr(serialfd, TCSANOW, &options);

while(1)
{
if(m==100)
{
m=0;
for(i=0;i<MAXDATASIZE;++i) buffer_tx[i]=i&0x7f;
write(serialfd, &buffer_tx, MAXDATASIZE);
printf("\r\n Sended=%i",n++);
}
++m;
usleep(10000*2);

bytesRead = read(serialfd, &buffer, MAXDATASIZE);
if(bytesRead == -1)
{
; //Sleep for some time and read again
// usleep(900000);
}
else
{
printf(" =%i ",bytesRead);
totalBytes += bytesRead;
for(i =0; i < bytesRead; i++)
{
printf(" %i", buffer[i]);
}

k=0; d=0;
for(i=0;i<MAXDATASIZE;++i)
{
d=i&0x7f;
if(buffer[i]!=d)
{
printf(" %i=%i ",buffer[i],d);
k=1;
}
}
if(k==0)
printf(" OK");
else
printf(" Err");

}
Спуститься к концу Подняться к началу
Персональная информация
sasamy
Добавлено 06.03.2025 14:31 Сообщение: 13
sasamy
4.71

Пункты: 92929
Регистрация: 14.08.2009
Цитата
256 - аппаратный, но скорость большая, надо большой буфер, в несколько Кб, чтобы пользовательская программа раз в тик могла без потерь получить все принятое.


внутренний буфер драйвера - страница 4 килобайта, вы пытаетесь исправить описание аппаратного fifo, это бессмысленно и кроме ошибок ничего не даст

Цитата

Тест (нашел какой-то прототип и доработал):
//const int MAXDATASIZE = 512;
const int MAXDATASIZE = 16*2*2*2*2;

serialfd = open( "/dev/ttyS2", O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);


можно компилируемый вариант чтобы я у себя мог проверить? скинньте лучше на какой нибуть файлообменник.
Спуститься к концу Подняться к началу
Персональная информация
Hsb
Добавлено 06.03.2025 16:03 Сообщение: 14
Hsb
0

Пункты: 307
Регистрация: 18.02.2025
Выложил https://cloud.mail.ru/public/oQpa/19Wx4jKmK
Тест посл.канала сделан на основе теста SPI в linux-custom/tools/spi, поэтому запуск как для теста SPI, через скрипт ts1.
Пример:
#
# ./ts1

Connected to serial port: Buffer = 256

Sended=256
bytesRead=19
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
Compare:
19=6 20=80 21=116 22=240 23=182 24=224 25=114 26=239 27=182 28=172 29
=130 30=150 31=6 32=208 33=114 34=239 35=182 36=77 37=209 38=238 39=18
...
7=0 118=0 119=0 120=40 121=92 122=149 123=190 124=129 125=26 126=68 12
7=0
Err
#

Я экспериментировал с драйвером, стало хуже - 19 байт только правильных идет, максимум было 128. Здесь - послано 256, принято 19, они выведены. Отправляется счетчик 0...127,
поскольку было подозрение, что спецсимволы обрабатываются, но потом сделал raw.
Далее сравнение - что д.б. и что в массиве, смысла в этом нет, но сначала заложил, потом не стал менять.
Спуститься к концу Подняться к началу
Персональная информация
sasamy
Добавлено 06.03.2025 20:07 Сообщение: 15
sasamy
4.71

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

Я экспериментировал с драйвером


вот мой тест

https://disk.yandex.ru/d/krAwFdPr0hcmtA

со штатным драйвером

Цитата

# ./utest
Usage: ./utest [-s srcdev] [-d dstdev] [-b baud] [-c count]
Now: srcdev /dev/ttyS2, dstdev /dev/ttyS2, baud 4000000, count 4095
send 4095 bytes
received 4095 bytes
transmitted and received data matched
00 01 02 03 04 05 06 07....

test OK
Спуститься к концу Подняться к началу
Персональная информация
Hsb
Добавлено 06.03.2025 21:40 Сообщение: 16
Hsb
0

Пункты: 307
Регистрация: 18.02.2025
Спасибо, завтра попробую, но чисто навскидку - у вас блокирующий режим, соответственно read ждет заданное кол-во байт или вылетает по таймауту. Так понятно, что будет работать. Требуется же неблокирующий, чтобы остальные процессы не тормозились. В этом случае включен O_NONBLOCK и имитируется требуемый режим работы за счет:
- передали пакет
- пауза больше времени передачи пакета
- read
Вариант неблокирующего но с частым обращением к read, чаще, чем заполнится FIFO - тоже не годится, линукс не обеспечит требуемое для этого реальное время, да и опять же неоптимально по временным затратам.
Единственный вариант - драйвер должен либо иметь очень большой буфер DMA, либо циклический буфер DMA, а этого и нет, хотя в dtsi и указаны каналы DMA для UART2.
Спуститься к концу Подняться к началу
Персональная информация
sasamy
Добавлено 06.03.2025 21:59 Сообщение: 17
sasamy
4.71

Пункты: 92929
Регистрация: 14.08.2009
Цитата
Спасибо, завтра попробую, но чисто навскидку - у вас блокирующий режим, соответственно read ждет заданное кол-во байт или вылетает по таймауту. Так понятно, что будет работать. Требуется же неблокирующий, чтобы остальные процессы не тормозились. В этом случае включен O_NONBLOCK и имитируется требуемый режим работы за счет:
- передали пакет
- пауза больше времени передачи пакета
- read
Вариант неблокирующего но с частым обращением к read, чаще, чем заполнится FIFO - тоже не годится, линукс не обеспечит требуемое для этого реальное время, да и опять же неоптимально по временным затратам.
Единственный вариант - драйвер должен либо иметь очень большой буфер DMA, либо циклический буфер DMA, а этого и нет, хотя в dtsi и указаны каналы DMA для UART2.


не понимаю честно говоря что вам надо - вы говорите противоположные вещи. Блокирующее чтение делают для того чтобы не вызывать его по нескокльо раз и никакие процессы не тормозятся, блокируется (засыпает) процесс который вызывает блокирущий ioctl до тех пор пока там не будет данных, пока он спит выполняются другие процессы, т.е. происходит решедулинг. Я поменял вызов на неблокирующий и ничего ожидаемо не измеилось потому что суть тут в другом

Цитата

if (write(srcfd, srcbuf, count) == -1) {
perror("write");
exit(1);
}

tcdrain(srcfd);

dstcount = read(dstfd, dstbuf, sizeof(dstbuf));

printf("received %i bytes\n", dstcount);


после передачи tcdrain гарантирует что все данные переданы и при любом чтении read прочитает переданный буфер целиком
Спуститься к концу Подняться к началу
Персональная информация
Hsb
Добавлено 06.03.2025 22:29 Сообщение: 18
Hsb
0

Пункты: 307
Регистрация: 18.02.2025
Процессы я имею в виду в этой же программе, она должна продолжать работу по другим задачам, а не висеть на ожидании завершения передачи и приема. Если разнести процессы по разным программам, то да, это решение сработает, но процессы тесно взаимодействуют, не пройдет. Теоретически возможно использовать thread, в одну вынеся этот обмен, но это усложнит/утяжелит программу, а хотелось бы иметь простой функционал, простую, понятную и надежную программу. thread сильно зависят от реализации, на Яве сталкивался с тем, что один поток идет на одно ядро процессора и при превышении их кол-ва программа практически останавливается. "Сложно" сделать просто, сложно сделать "просто":)
Спуститься к концу Подняться к началу
Персональная информация
sasamy
Добавлено 06.03.2025 22:58 Сообщение: 19
sasamy
4.71

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


вот мне интересно - как вы себе это представляете при одностороннем обемене, если вы в произвольный момент вызываете чтение - откуда вы можете знать что весь пакет уже передан а не передаётся или ещё может даже не начинал передаваться?
Спуститься к концу Подняться к началу
Персональная информация
Hsb
Добавлено 06.03.2025 23:25 Сообщение: 20
Hsb
0

Пункты: 307
Регистрация: 18.02.2025
В osless системах делаю кольцевой DMA буфер, каждый тик своей работы, обычно 10мс, программа забирает по его указателям принятое и обрабатывает. Передача тоже через DMA. Никаких накладных расходов в программе, все аппаратно.
Спуститься к концу Подняться к началу
Персональная информация
Форум » starterkit.ru » Процессорные модули » ES-T113-NANO(-LV), SK-T113-MOD