LINUX.ORG.RU

Проблема с одновременным асинхронным чтением из порта и терминала

 ,


0

1

Для отладочной работы с железякой я сварганил простейший велосипед. Никаких потоков: просто поочередный опрос (select) терминала и cdc-acm с чтением, если есть данные. На малых размерах посылки это работает, а вот на больших почему-то нет-нет, да происходит косяк: считываются данные из первого буфера (64 символа — размер буфера USB cdc-acm), а второй пропускается. И получается обрезанный вывод данных.

Я уже время задержки опроса терминала до 500мкс уменьшил (чтобы было явно меньше времени между опросами USB), но все равно получаются пропуски.

Неужто никак не обойтись без потоков (т.е. слушать USB одним потоком, запихивая данные куда-нибудь в очередь)?

☆☆☆☆☆

одновременным
Никаких потоков

Молодец, сам ответил на свой вопрос:

Неужто никак не обойтись без потоков

UVV ★★★★★
()
Ответ на: комментарий от UVV

Ну так ведро ж буферизует!

Блин. Если правда нельзя без потоков, придется велосипедить ☹ Так хотелось без очередей сообщений хотя бы в такой элементарщине обойтись!

Eddy_Em ☆☆☆☆☆
() автор топика

знатный велосипед :-)

беглым взглядом в ф-ци read_tty() есть только недочёт («if (!retval) return 0» заменить на «if (retval<=0) return 0») - select умеет возращать отрицательные величины, при этом состояния наборов не определены

MKuznetsov ★★★★★
()
Ответ на: комментарий от MKuznetsov

И действительно, хоть у меня такого и не было, надо этот вариант учесть. Спасибо.

и кстати, отчего IO от консоли и USB не сведены в один select?

А и правда. Сейчас попробую.

Eddy_Em ☆☆☆☆☆
() автор топика
Ответ на: комментарий от Eddy_Em

Сделал. Однако, от потери данных это не спасло.

"СёмкиОшибки есть? а если найду??" (c)

ps/ вероятность ошибки в драйвере USB или библиотечных функциях read(),select() исчезающе мала - так что баг в твоём коде

MKuznetsov ★★★★★
()
Ответ на: комментарий от MKuznetsov

Чертовщина какая-то! Уже вроде бы вообще не осталось мест, где возможна значительная задержка. По идее, должно принимать. Если бы проблема была на стороне МК, то этот косяк был бы постоянно. А так — всплывает периодически, т.е. явно принимающая сторона виновата.

Будем искать.

Eddy_Em ☆☆☆☆☆
() автор топика

Бегло просмотрел код. Как-то ты не до конца обрабатываешь то что возвращает select(). Он может возвратить ошибку EINTR, тогда его нужно перезапустить заново. И после select ты читаешь только один раз, нужно читать пока возвращается положительное значение

anonymous
()

int mygetchar(){ // ������ getchar() ��� ������������� ���� Enter

вместо тысячи слов.

anonymous
()
Ответ на: комментарий от anonymous

P.S. У меня нет перехвата сигналов — EINTR обрабатывать не нужно.

Eddy_Em ☆☆☆☆☆
() автор топика
Ответ на: комментарий от Eddy_Em

И все равно один раз читаешь (стр. 134). Нужно вычитывать пока read возвращает положительные значения

anonymous
()
Ответ на: комментарий от Eddy_Em

что-то я сомневаюсь, что поможет

Ты не сомневайся а почитай про чтение из неблокируемых дескрипторов. Вот на SO есть даже кусок кода:

http://stackoverflow.com/questions/5616092/non-blocking-call-for-reading-desc...

int count;
char buffer[1024];
count = read(fd, buffer, 1024);
if(count < 0 && errno == EAGAIN) {
    // If this condition passes, there is no data to be read
}
else if(count >= 0) {
    // Otherwise, you're good to go and buffer should contain "count" bytes.
}
else {
    // Some other error occurred during read.
}
anonymous
()
Ответ на: комментарий от Eddy_Em

Я уже обновил файл.

добавь printf(«got %d bytes from USB\n»,L) в read_tty_and_console() - чтоб сразу видеть сколько байт пришло.

вывод %s недостаточен - можно обмануться например на строке hello\rworld, элементарно не заметить «hello» в консоле. hexdump в помощь :-)

и если есть смутные подозрения - то (хотя-бы при отладке) стоит добавить набор exfds - вдруг там чё нехорошее происходит:-)

ps/ gdb тоже нечё-так себе тулза :-) можно например поставить breakpoint на copy_buf_to_file и найти таки ошибку :-) она скорее всего там..

MKuznetsov ★★★★★
()
Ответ на: комментарий от MKuznetsov

\r

У меня таких символов нет. Потому что железячная часть тоже мною паяна и писана.

gdb тоже нечё-так себе тулза

отладчиками я пользоваться не умею. И не хочу на них тратить время.

можно например поставить breakpoint на copy_buf_to_file и найти таки ошибку

Выхлоп в файл полностью соответствует (за исключением выбрасывания команд) выхлопу терминала.

стоит добавить набор exfds

ты имеешь в виду errorfds? Попробую.

Eddy_Em ☆☆☆☆☆
() автор топика
Ответ на: комментарий от Eddy_Em

У меня таких символов нет. Потому что железячная часть тоже мною паяна и писана.

мне бы такую уверенность в собственной безошибочности :-)

но ведь байты куда-то пропадают ?? кто-то же куда-то их теряет... может каким-нить netcat`ом или ещё чём снять протокол обмена

отладчиками я пользоваться не умею. И не хочу на них тратить время.

зря, даже элементарные вещи b/n/s экономят это самое время

MKuznetsov ★★★★★
()
Ответ на: комментарий от Eddy_Em

Эдуард, ты бы уже раз 10 мог попробовать и аргументированно показать что я неправ

anonymous
()
Ответ на: комментарий от MKuznetsov

мне бы такую уверенность в собственной безошибочности :-)

Чтобы там появился '\r', я его должен был бы ручками воткнуть. А я это не использую, т.к. не мастдайка же!

но ведь байты куда-то пропадают ?

Забавно. Я добавил вывод в stderr количества считанных данных. Т.е. данные уже приходят битыми:

readed 112 bytes, try more.. full len: 112
0 2610000 2004 2164 1 1236 1799 2063 1949 2141 3723296 3718217 3712157 3712685 3718252 3721099 3720583 3722869 
readed 128 bytes, try more.. full len: 128
0 2620000 1961 2105 2 1238 1807 2073 1958 2143 3723244 3718207 [b]30[/b] 2630000 1992 2155 1 1233 1803 2063 1959 2140 3723223 3718185 
жирным выделен кусок, где после тройки содержимое буфера "кануло в Лету".

Всем спасибо. Виновата не принимающая сторона, а передающая. Буду искать, где я там буфер переполняю.

Eddy_Em ☆☆☆☆☆
() автор топика
Ответ на: комментарий от MKuznetsov

Вот и косячок нашелся. Я отправлял буфер, не проверяя, что возвращает функция:

usbd_ep_write_packet(current_usb, 0x82, USB_Tx_Buffer, USB_Tx_ptr)
а функция эта возвращает 0, если предыдущий буфер еще в ожидании (или процессе) передачи!

Заменил на

while(USB_Tx_ptr != usbd_ep_write_packet(current_usb, 0x82, USB_Tx_Buffer, USB_Tx_ptr));
пока вроде косяков не появляется.

Eddy_Em ☆☆☆☆☆
() автор топика

эрланг пробовал уже?

anonymous
()
Ответ на: комментарий от Eddy_Em

Написал заметку в своей ЖЖшке

глянул ЖЖшку - в меру любопытно, особенно про чернику (кто об чём, а я про отпуск..)..у нас блин дождик, и грибной сезон уже практически тю-тю :(

кстати, вежливо по отношению к админам и создателям ЛОР, было-б публиковать ссылку и обратно ;-) Раз уж у тебя ЖЖ живо..

MKuznetsov ★★★★★
()
Ответ на: комментарий от MKuznetsov

грибной сезон уже практически тю-тю

У нас тоже, к сожалению. Сегодня видел уборщиц, собирающих в окрестностях телескопа грибы. Погода сегодня была хорошая, а дальше опять дожди обещают.

вежливо по отношению к админам и создателям ЛОР, было-б публиковать ссылку и обратно

На эту тему? Можно, отчего нет?

Eddy_Em ☆☆☆☆☆
() автор топика
Ответ на: комментарий от Eddy_Em

На эту тему? Можно, отчего нет?

на тему?? на тему вряд-ли..на ресурс стоит, а то без внешней поддержки он становится уныл :(

MKuznetsov ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.