Страниц: [1] 2
  Печать  
Автор Тема: devc-ser8250 отложеные прерывания  (Прочитано 17843 раз)
qnxloder
Sr. Member
****
Offline Offline

Сообщений: 292


Просмотр профиля
« : Июня 19, 2007, 11:29:22 am »

Добрый день всем!
Есть 2 комп. соединеные по СОМ порту и передающие(асинхронно) друг другу данные. Через некоторое время (зависит от темпа передачи данных) поток, который пишит данные блокируется на write() и контроллер начинает передавать данные по 1 байту с периодом 150мсек(это время установлено в драйвере), пока не очистится выходной буфер драйвера(2048К)(прием соотв. тоже прекращается). После этого данные не передаются, пока не перезапустить драйвер. Проанализировав исходники devc-ser8250, стало понятно, что это связано с потерей прерываний и последующей их(потеряных) обработкой. Ну ладно прерывания теряются и фиг с ними - данные вадаются одни и теже периодически и содержат контрольную сумму, но почему прекращается выдача? Подскажите как можно подправить драйвер, чтобы он пусть и терял прерывания, но выдача не прекращалась и поток не блокировался.
Записан
qnxloder
Sr. Member
****
Offline Offline

Сообщений: 292


Просмотр профиля
« Ответ #1 : Июня 19, 2007, 11:31:54 am »

Да, еще драйвер запускаю так:devc-ser8250 -T8 -t8 -u1 0x3F8,4 &
Заранее благодарю.
Записан
Ivan
Участник
*
Offline Offline

Сообщений: 23


Просмотр профиля
« Ответ #2 : Июня 19, 2007, 06:58:40 pm »

Записан
Ivan
Участник
*
Offline Offline

Сообщений: 23


Просмотр профиля
« Ответ #3 : Июня 19, 2007, 07:00:31 pm »

Да и у меня была такая байда.

Как я понял проблема в том, что в обработчике прерывания нет цикла на состояние прихода нового символа. Получается, что в прерывании обрабатывается только 1 символ, а если за время работы обработчика придет еще один, то он теряется.

ПОчему при этом впадает в ступор передатчик я так и не выяснил.

Чтобы не переписывать весь драйвер целиком, хотя, наверное, стоило бы, я связался с "демоном непереносимости" 8о) : добавил для devc-ser8250 еще одну команду, которая посылается ему через devctl, обработчик этой команды вызывает :

void recovery( TTYDEV *ttydev )
{
    DEV_8250 *dev = (DEV_8250 *)ttydev;
    unsigned char tmp;
    write_8250(dev->port[REG_IE], 0);  // Disable all interrupts
    tmp = read_8250(dev->port[REG_LS]);  // Clear Line Status Interrupt
    tmp = read_8250(dev->port[REG_RX]);  // Clear RX Interrupt
    tmp = read_8250(dev->port[REG_TX]);  // Clear TX Interrupt
    tmp = read_8250(dev->port[REG_MS]);  // Clear Modem Interrupt
    write_8250(dev->port[REG_IE], 0x0f);     // Enable ALL interrupt sources.
};


select c таймаутом жду готовности дескриптора, если происходит таймаут - взбадриваю devc-ser8250.

Может у кого-то есть более корректное решение, поделитесь.
Записан
PoP
Sr. Member
****
Offline Offline

Сообщений: 336


Просмотр профиля
« Ответ #4 : Июня 20, 2007, 12:00:46 am »

Может, сказать ему безусловно -F? Ну, если com не полный. Если полный - посмотреть, не сняты ли CLS и DTR.
Записан
ArtemS
Участник
*
Offline Offline

Сообщений: 3


Просмотр профиля
« Ответ #5 : Июня 20, 2007, 11:33:13 am »

Для 6.2.1 в свое время был выпущен
Experimental fix for the 8250 serial driver

Fixes a workaround for buggy 16xxx FIFOs so that a  timeout doesn't take 10-13 seconds
Записан
qnxloder
Sr. Member
****
Offline Offline

Сообщений: 292


Просмотр профиля
« Ответ #6 : Июня 20, 2007, 02:56:13 pm »

Спасибо всем откликнувшимся. Проблему "решил", как посоветовал Ivan - добавлением команды сброса контролера (девцтл), по таймауту чтения из этого порта.
Экспериментальный драйвер не помог.
Конечно хотелось бы подправить драйвер, но даже не знаю каким образом. Если есть идеи, попробую...
Записан
AlexDon
Участник
*
Offline Offline

Сообщений: 0


Просмотр профиля
« Ответ #7 : Июня 22, 2007, 12:02:49 pm »

Не знаю, по теме ли это. У меня на новых компьютерах перестал работать TD.EXE 3- версии через RS232. Проблема была в ложных прерываниях по вводу. Удалось вылечить следующей заплаткой:

    mov dx,base+2
    in al,dx
    test al,1
    jne M_21
    mov dx,base+5
    in al,dx
    mov dx,base
    in al,dx

 которую вставил после обработки прерывания.

 А вообще-то правильно в обработчике опрашивать base+2, пока младший бит не станет равным 0.
Записан
qnxloder
Sr. Member
****
Offline Offline

Сообщений: 292


Просмотр профиля
« Ответ #8 : Июня 22, 2007, 02:07:27 pm »

В обработчике прерываний отсутствует обработка II_NOINTR, кто знает, что в этом случае нужно делать?
Записан
qnxloder
Sr. Member
****
Offline Offline

Сообщений: 292


Просмотр профиля
« Ответ #9 : Июня 22, 2007, 04:46:07 pm »

прочитал:
http://bugtraq.ru/library/programming/rs232.html?k=9#3

соглано этому описанию обработчик прерывания написан корректно.
сделал так:
в обработчике, вместо switch(iir) {.......}
поставил:
[code]
         if (iir & II_RX)      // Receive data
            do {
               status |= tti(&dev->tty, read_8250(port[REG_RX]));
               lsr = read_8250(port[REG_LS]);
               status |= process_lsr(dev, lsr);
            } while(lsr & LSR_RXRDY);
         else
         if (iir & II_TX)      // Transmit buffer empty
            {
            fifo_counter = 0;

            do {
               dev->tty.un.s.tx_tmr = 0;
               // The override causes tto to ignore the check on tx buffer empty
               // since we know that the entire fifo is empty when the interrupt fires
               //status |= tto(&dev->tty, TTO_DATA, dev->fifo_override);
               status |= tto(&dev->tty, TTO_DATA, FIFO_XMIT_OVERRIDE);
               } while( (++fifo_counter < dev->tx_fifo) && (dev->tty.obuf.cnt > 0) );
            }
         else
         if (iir & II_MS)      // Modem change
            {
            msr = read_8250(port[REG_MS]);

            if(msr & MSR_DDCD)
               status |= tti(&dev->tty, (msr & MSR_DCD) ? TTI_CARRIER : TTI_HANGUP);
               
            if((msr & MSR_DCTS)  &&  (dev->tty.c_cflag & OHFLOW))
               status |= tti(&dev->tty, (msr & MSR_CTS) ? TTI_OHW_CONT : TTI_OHW_STOP);
            }
         else
         if (iir & II_LS)      // Line status change
            {
            lsr = read_8250(port[REG_LS]);
            status |= process_lsr(dev, lsr);
            }
         else
            break;

[code]

пока вроде работает...

похоже надо обрабатывать ситуацию, когда обрабатывать нечего(бит 1 рег. base+2 = 1) похоже по какойто причине он "залипает"...

Есть идеи?
Записан
qnxloder
Sr. Member
****
Offline Offline

Сообщений: 292


Просмотр профиля
« Ответ #10 : Июня 22, 2007, 05:48:21 pm »

Данное решение подходит, если прерывание контроллера одно на один порт и только для этого порта, и драйвер запущен  для этого порта, например:
будет работать:
devc-ser8250 -u1 0x3E8,11 &
devc-ser8250 -u2 0x2E8,10 &

не будет:
devc-ser8250 -u1 0x3E8,11 -u2 0x2E8,11 &
Записан
qnxloder
Sr. Member
****
Offline Offline

Сообщений: 292


Просмотр профиля
« Ответ #11 : Июня 25, 2007, 11:28:04 am »

Вот что ответили в СВД:
-----------------------------------------
> Вот обсуждение этой проблемы:
> http://qnx.org.ru/viewthread13n4960.html

Учитывая, что исходники на драйвер devc-ser8250 в состав Character DDK входят,
и суть проблемы, да и пути ее решения - с точки зрения доработки драйвера, уже
известны, могу сказать, что все в ваших руках. Могу лишь добавить, что есть
смысл попробовать подойти к решению проблемы и со стороны прикладной
программы, т.е. делать не просто write() в устройство драйвера
последовательного порта, а использовать комбинацию select()/ionotify() и уже
потом write(). Выдержка из документации,

http://www.qnx.com/developers/docs/6.3.0SP3/neutrino/prog/resmgr.html#HANDLING_ionotify


"A client uses ionotify() and select() to ask a resource manager about the
status of certain conditions (e.g. whether input data is available). The
conditions may or may not have been met. The resource manager can be asked to:


    * check the status of the conditions immediately, and return if any have
been met
    * deliver an event later on when a condition is met (this is referred to
as arming the resource manager)".

Вполне возможно, что использование этой связки (когда select()/ionotify()
заряжаются на output contitions) позволит драйверу devc-ser8250 не затыкаться
на передачах потоков данных.

Игорь Мазанов
Служба технической поддержки
---------------------------------------
Переделать на IO_NOTIFY... IO_WRITE проблематично, по причине количества каналов, да и не использовал это никогда...
Что думаете, может это помочь?
Благодарю.
Записан
AlexDon
Участник
*
Offline Offline

Сообщений: 0


Просмотр профиля
« Ответ #12 : Июня 25, 2007, 11:43:10 am »

Да вспомнил еще одну вещь: если строить обработчик прерываний через постоянный опрос регистра IIR, то можно не закрывать маску для прерываний TX bufer empty. В этом случае ложное прерывание сработает всего один раз.
Записан
qnxloder
Sr. Member
****
Offline Offline

Сообщений: 292


Просмотр профиля
« Ответ #13 : Июля 02, 2007, 11:26:08 am »

Да уж: исправление драйвера, написаное мною выше с точки зрения логики бредовое. Тесты показали, что драйвер стал всего лишь немногим дольше не затыкаться. Остается использовать решение предложеное Иваном.
Пару раз переписал обработчик по спецификации -- не помогло. Наверное действительно это проблема библиотеки io-char.
Записан
qnxloder
Sr. Member
****
Offline Offline

Сообщений: 292


Просмотр профиля
« Ответ #14 : Июля 04, 2007, 03:24:22 pm »

<i>Ivan
<i>select c таймаутом жду готовности дескриптора, если происходит таймаут - взбадриваю devc-ser8250.

Может у кого-то есть более корректное решение, поделитесь.
</i></i>


Ясделал так:
io-char->timer.c->timer_tick(...)


Было:
if(dev->un.s.tx_tmr  &&  --dev->un.s.tx_tmr == 0) {
tto(dev, TTO_DATA, 0);
}


Стало:
if(dev->un.s.tx_tmr  &&  --dev->un.s.tx_tmr == 0) {
tto(dev, TTO_DATA, 0);
#ifdef PM_DEBUG
printf("!RESET UART!";
#endif
recovery(dev);
}


Добавил
devc-ser8250->tto.c
void recovery( TTYDEV *ttydev )
{
DEV_8250 *dev = (DEV_8250 *)ttydev;

write_8250(dev->port[REG_IE], 0);  // Disable all interrupts
write_8250(dev->port[REG_IE], 0x0f);     // Enable ALL interrupt sources.
};



Ну ворнинг при компиляции io-char возникает, но не надо править h файлы и дописывать devctl.

День протестировал - работает (в момент, когда драйвер затыкался теряется несколько байт).
Записан
Страниц: [1] 2
  Печать  
 
Перейти в: