информационная безопасность
без паники и всерьез
 подробно о проектеRambler's Top100
Сетевые кракеры и правда о деле ЛевинаСтрашный баг в WindowsВсе любят мед
BugTraq.Ru
Русский BugTraq
 Анализ криптографических сетевых... 
 Модель надежности двухузлового... 
 Специальные марковские модели надежности... 
 Три миллиона электронных замков... 
 Doom на газонокосилках 
 Умер Никлаус Вирт 
главная обзор RSN блог библиотека закон бред форум dnet о проекте
bugtraq.ru / форум / programming
Имя Пароль
ФОРУМ
если вы видите этот текст, отключите в настройках форума использование JavaScript
регистрация





Легенда:
  новое сообщение
  закрытая нитка
  новое сообщение
  в закрытой нитке
  старое сообщение
  • Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
  • Новичкам также крайне полезно ознакомиться с данным документом.
А непосредственно *до* этого что происходит? 22.09.03 12:04  Число просмотров: 1453
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
> Я почему про ФИФО подумал - я ведь точно не знаю как оно
> работает, потому что документация под руки не попадалась.
Если ты его не проинициализируешь - оно работать вообще не будет :-)

> Думал, что наступает ситуация, когда должно возникнуть
> прерывание, но первое еще не обработано. Оно (второе)
> встает в очередь. После обработки первого нужно проверить
> очередь на наличие в нем отложенного прерывания, а я этого
> не делаю - не знаю как. Завершаю обработку первого и выхожу
Так и есть. Чтобы проверить наличие отложенного прерывания надо прочитать IIR еще раз. То есть делать это в цикле пока бит 0 не станет в 1.

> > identification register) остается в 0 и прерывание не
> > приходит, так как считается, что до сих пор
> обрабатывается
> > старое.
>
> А вот здесь чуть поподробнее.
Приоритеты прерываний в порядке убывания следующие: RLS, RDA, CTI, THR, MS. А теперь по русски:

RLS - Line error
RDA - Char received
CTI - Timeout (только для FIFO)
THR - Char transmitted
MS - Modem status changed

Как сбрасываются ты знаешь. После сброса прерывания с более высоким приоритетом нужно проверить нет ли прерывания с меньшим. Для этого нужно повторно прочитать IIR.
<programming>
"Зависает" СОМ-порт 19.09.03 15:31  
Автор: DPP <Dmitry P. Pimenov> Статус: The Elderman
<"чистая" ссылка>
Перестают идти прерывания. Может какие-то хитрости с ФИФО? Если с ней, то как ее программировать? Какие установки по-умолчанию?
Могу свои наработки предложить ... (DOS-ие, BC++ 3.x) 20.09.03 22:43  
Автор: oleaster Статус: Незарегистрированный пользователь
Отредактировано 22.09.03 22:50  Количество правок: 1
<"чистая" ссылка>
// Инициализация вектора и контроллера
_asm { cli
mov ax, 0
mov tes, es
mov es, ax

mov ax, word ptr es:[COM_1_INTERR*4]
mov old_ofs_com1, ax
mov ax, word ptr es:[COM_1_INTERR*4+2]
mov old_seg_com1, ax

mov word ptr es:[COM_1_INTERR*4], offset COM_1
mov word ptr es:[COM_1_INTERR*4+2], seg COM_1
}

InitCOMport (0);

_asm {

in al, 21h
and al, 11100111b
out 21h,al

////////////////
in al, 0xA1
and al, 0
out 0xA1,al
////////////////
mov al, 0x20
out 0x20, al
out 0xa0, al

mov ax, tes
mov es, ax
sti
}

------------------------------------


// Инициализация порта

#define COM_1_INTERR 0x0C
#define COM_1_BASREG 0x3f8

#define init_com1_0_del 12//12//0x06
#define init_com1_1_del 0x00
#define init_com1_1_upr 0x03
#define init_com1_3_nor 0x1B

void InitCOMport (char comPos,
unsigned char a=init_com1_0_del,
unsigned char b=init_com1_1_del,
unsigned char c=init_com1_3_nor,
unsigned char d=init_com1_1_upr,
unsigned char e=0x08) {

AdressCOM0=BasAdrCOM[comPos]; // массив с базовыми адресами портов
AdressCOM1=AdressCOM0+1; AdressCOM2=AdressCOM0+2;
AdressCOM3=AdressCOM0+3; AdressCOM4=AdressCOM0+4;
AdressCOM5=AdressCOM0+5; AdressCOM6=AdressCOM0+6;

_asm {

mov al, 0
mov dx, AdressCOM1
out dx, al

mov dx, AdressCOM4
out dx, al

mov dx, AdressCOM5
in al, dx

mov dx, AdressCOM0
in al, dx

mov dx, AdressCOM6
in al, dx


mov al, 0
mov dx, AdressCOM2
out dx, al

---------------

mov al, 0x80
mov dx, AdressCOM3
out dx, al

mov al, a
mov dx, AdressCOM0
out dx, al

mov al, b
mov dx, AdressCOM1
out dx, al

mov al, c
mov dx, AdressCOM3
out dx, al
}


_asm {
mov al, 1011b //e
mov dx, AdressCOM4
out dx, al

mov al, d // 1111b
mov dx, AdressCOM1
out dx, al
}

}



------------------------------------


// Обработчки прерывания
void interrupt COM_1 () {

COMfunction(0); // Функция обработчика

_asm {
mov al, 0x20
out 0x20, al
//out 0xa0, al
}
}



// Заточено под прием-передачу байт
void COMfunction (int e) {
unsigned char BytePrich, ByteInf, BytePhact, Cikl=100;
int AdressCOM0, AdressCOM2, AdressCOM5, AdressCOM6;

AdressCOM0=BasAdrCOM[e]; AdressCOM2=AdressCOM0+2;
AdressCOM5=AdressCOM0+5; AdressCOM6=AdressCOM0+6;

repeat: if ((--Cikl)==0) return;

_asm {
mov dx, AdressCOM2
in al, dx
and ax, 00000111b
mov BytePrich, al
and ax, 00000001b
mov BytePhact, al

mov dx, AdressCOM0
in al, dx
mov ByteInf, al
}

if (BytePhact==1) return;

if (!BytePrich) {
_asm {
mov dx, AdressCOM5
in al, dx
}
}

if (BytePrich&4) {
// Принятый байт Записывается в некоторый буфер
COM_BUF_IN[e][P_in_buf[e]]=ByteInf; if ((++P_in_buf[e])>69) P_in_buf[e]=0;

}

if (BytePrich&2) {
if (P_out_buf[e]!=0) {
ByteInf=COM_BUF_OUT[e][P_stat_buf[e]]; P_stat_buf[e]++; P_out_buf[e]--;

// Байт может быть передан
/*
if (Param2==0) {
_asm {
mov al, ByteInf
mov dx, AdressCOM0
out dx, al
}
} else
{
Param2_buf [e]=ByteInf;
Param2_IDENT[e]=TIMECOMINTERR;
}
*/
}
}

if (BytePrich&6) {
_asm {
mov dx, AdressCOM6
in al, dx
}
}
goto repeat;

}
Все разработки, по большему счету, схожи. 22.09.03 11:11  
Автор: DPP <Dmitry P. Pimenov> Статус: The Elderman
Отредактировано 22.09.03 11:17  Количество правок: 2
<"чистая" ссылка>
> // Инициализация вектора и контроллера
Поскипано 13 строк...
Я на С писал, выглядит это примерно так:
    disable();
    oldinterrupt = getvect( com_port_hardware_interrupt_vector + 8 );
    setvect( com_port_hardware_interrupt_vector + 8, &newinterrupt );
    enable();

---
> InitCOMport (0);
>
> _asm {
>
> in al, 21h
> and al, 11100111b
> out 21h,al
У меня:
#define com_port_hardware_interrupt_vector 4
#define com_port_hardware_number 0x3f8
    com_port_hardware_interrupt_mask = inp( 0x21 ) & ( 1 << com_port_hardware_interrupt_vector );
    outp( 0x21, inp( 0x21 ) & ~( 1 << com_port_hardware_interrupt_vector ) );

---
просто запоминаю предыдущее состояние
> ////////////////
Зачем второй контроллер дергать?
> in al, 0xA1
> and al, 0
> out 0xA1,al
> ////////////////
> mov al, 0x20
> out 0x20, al
> out 0xa0, al
>
> mov ax, tes
> mov es, ax
> sti
> }
>
> ------------------------------------
>
>
> // Инициализация порта
Поскипано 68 строк...
#define com_port_receiving_register ( com_port_hardware_number + 0 )
#define com_port_interrupt_control_register ( com_port_hardware_number + 1 )
#define com_port_interrupt_identification_register ( com_port_hardware_number + 2 )
#define com_port_line_control_register ( com_port_hardware_number + 3 )
#define com_port_modem_control_register ( com_port_hardware_number + 4 )
#define com_port_line_status_register ( com_port_hardware_number + 5 )
#define com_port_modem_status_register ( com_port_hardware_number + 6 )

    com_port_line_control_mask = inp( com_port_line_control_register );
    com_port_interrupt_control_mask = inp( com_port_interrupt_control_register );
    com_port_modem_control_mask = inp( com_port_modem_control_register );
    outp( com_port_line_control_register, 0x80 );
    outp( com_port_receiving_register, 0x01 );
    outp( com_port_interrupt_control_register, 0x00 );
    outp( com_port_line_control_register, 0x03 );
    outp( com_port_interrupt_control_register, 0x0f );
    outp( com_port_modem_control_register, 0x0f );
    com_port_modem_status_mask = inp( com_port_modem_status_register );

---
Сначала сохраняю предыдущее состояние порта, чтобы потом все восстановить.
> // Обработчки прерывания
> void interrupt COM_1 () {
>
> COMfunction(0); // Функция обработчика
>
> _asm {
> mov al, 0x20
> out 0x20, al
> //out 0xa0, al
> }
> }
Обработчик выглядит примерно так:
    com_port_interrupt_identification_mask = inp( com_port_interrupt_identification_register );
    if( com_port_interrupt_identification_mask & 1 )
        _chain_intr( oldinterrupt );
    switch( ( com_port_interrupt_identification_mask >> 1 ) & 3 ){
        case 0:
            time0 = ticks() / freq;
            com_port_modem_status_mask = inp( com_port_modem_status_register );
            break;
        case 1:
//            outp( com_port_receiving_register, 0 );
            break;
        case 2:
            inp( com_port_receiving_register );
            break;
        case 3:
            inp( com_port_line_status_register );
            break;
        default:
            break;
    }
    outp( 0x20, 0x20 );

---
Не забываю подтверждение контроллеру. Читать состояние, если изменилось состосние, читать данные, если пришли данные...
Если это 4 прерывание, но не от СОМпорта, передаю его дальше по цепочке.
Тогда мне только оправдаться остается ;) 22.09.03 19:13  
Автор: oleaster Статус: Незарегистрированный пользователь
Отредактировано 22.09.03 22:51  Количество правок: 1
<"чистая" ссылка>
1. В своих "наработках" я выдернул участок кода из своей проги (сама прога большая и "нечитабельная"), которая обслуживает 14 СОМ портов (2 стандартных+8-портовая плата+4-портовая плата) ,- поэтому там "проскочил" второй контроллер.

2. Я свою первую прогу для СОМ порта написал только 4 месяца назад - со всеми вытекающими отсюда ....
Но кое-какие проблемы могу осветить:
- была ситуация, когда не шли прерывания , если не очищать FIFO-буфер перед началом (я себе это так представил).
Сюжет примерно следующий - сначала загружается прога, работающая с СОМ-портом без прерываний, а затем моя (с прерываниями) - прерывания у меня не шли. Причем если после перезагрузки загрузить первой мою прогу ,- прерывания шли нормально.
- была ситуация, когда при одной разводке кабеля ("без готовности") программа работала, а при другой нет ("с готовностью") ,- не шли прерывания на прием.

В настоящее время все эти проблемы у меня решены.

3. Я полностью в работе порта не разбирался (заработало у меня и ладно) + теоретик из меня никудышный ... ,- благо есть amirul, который и мне в свое время помог с СОМ портом разобраться.
Не обидешься, если я скажу, что не стал разбираться в твоих исходняках ;)
Если у тебя так и не заработает "свое", просто попробуй "мое" ,- оно проверено на нескольких "железках" и вроде работает.
Тогда мне только оправдаться остается ;) 23.09.03 10:43  
Автор: DPP <Dmitry P. Pimenov> Статус: The Elderman
<"чистая" ссылка>
> Но кое-какие проблемы могу осветить:
> - была ситуация, когда не шли прерывания , если не очищать
> FIFO-буфер перед началом (я себе это так представил).
> Сюжет примерно следующий - сначала загружается прога,
> работающая с СОМ-портом без прерываний, а затем моя (с
> прерываниями) - прерывания у меня не шли. Причем если после
> перезагрузки загрузить первой мою прогу ,- прерывания шли
> нормально.
> - была ситуация, когда при одной разводке кабеля ("без
> готовности") программа работала, а при другой нет ("с
> готовностью") ,- не шли прерывания на прием.

Судя по всему в этом вышесказанном ФИФО и был виноват.

> 3. Я полностью в работе порта не разбирался (заработало у
> меня и ладно) + теоретик из меня никудышный ... ,- благо
> есть amirul, который и мне в свое время помог с СОМ портом
> разобраться.
> Не обидешься, если я скажу, что не стал разбираться в твоих
> исходняках ;)
> Если у тебя так и не заработает "свое", просто попробуй
> "мое" ,- оно проверено на нескольких "железках" и вроде
> работает.

"Свое" я привел только для того, чтобы показать, что оно от "Вашего" почти ни чем не отличается.

"Мое" вроде как делает вид, что вроде как заработало. Помогли повторные опросы идентификации прерывания.
Варианты 22.09.03 20:04  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
> 2. Я свою первую прогу для СОМ порта написал только 4
> месяца назад - со всеми вытекающими отсюда ....
> Но кое-какие проблемы могу осветить:
> - была ситуация, когда не шли прерывания , если не очищать
> FIFO-буфер перед началом (я себе это так представил).
> Сюжет примерно следующий - сначала загружается прога,
> работающая с СОМ-портом без прерываний, а затем моя (с
> прерываниями) - прерывания у меня не шли. Причем если после
> перезагрузки загрузить первой мою прогу ,- прерывания шли
> нормально.
Возможно прерывания были просто запрещены. А если разрешены, то например FIFO был заполнен (или в случае отключенного FIFO - регистр RBR), и прерывание, сигнализирующее о приеме данных уже и так pend-илось и не срабатывало повторно (это я уже написал в другом посте). В виндовых дриверах, чтобы перезапустить пендящиеся прерывания используется следующий метод (рекомендую к использованию в собственных разработках):

ЗАПРЕТИТЬ ВСЕ ПРЕРЫВАНИЯ
РАЗРЕШИТЬ ВСЕ ПРЕРЫВАНИЯ

При разрешении запускаются прерывания, которые ждут обработки. Запрещение/разрешение производится через регистр IER (Interrupt Enable Register).

> - была ситуация, когда при одной разводке кабеля ("без
> готовности") программа работала, а при другой нет ("с
> готовностью") ,- не шли прерывания на прием.
А тут возможно не шли не прерывания, а сами данные. Не могу сказать точно, но если есть DTR-DSR или RTS-CTS и при этом приемник показывает что он не готов, то большинство передатчиков просто не будут посылать данные. И ясное дело не будет никаких прерываний. Возможно нужно было поднять DTR и CTS.

> 3. Я полностью в работе порта не разбирался (заработало у
> меня и ладно) + теоретик из меня никудышный ... ,- благо
> есть amirul, который и мне в свое время помог с СОМ портом
> разобраться.
Дык, я тоже не особо заморачивался - почитал Михаила Гука "Энциклопедия периферийных устройств PC" - там все понятно написано, хотя и сжато.
Вот об этом я и говорил. 22.09.03 11:20  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
> Обработчик выглядит примерно так:
>     com_port_interrupt_identification_mask = inp(
> com_port_interrupt_identification_register );
>     if( com_port_interrupt_identification_mask & 1 )
> 	_chain_intr( oldinterrupt );
>     switch( ( com_port_interrupt_identification_mask
> >> 1 ) & 3 ){
> 	case 0:
> 	    time0 = ticks() / freq;
> 	    com_port_modem_status_mask = inp(
> com_port_modem_status_register );
> 	    break;
> 	case 1:
> //	      outp( com_port_receiving_register, 0 );
> 	    break;
> 	case 2:
> 	    inp( com_port_receiving_register );
> 	    break;
> 	case 3:
> 	    inp( com_port_line_status_register );
> 	    break;
> 	default:
> 	    break;
>     }
>     outp( 0x20, 0x20 );
> 

---
> Не забываю подтверждение контроллеру. Читать состояние,
> если изменилось состосние, читать данные, если пришли
> данные...
> Если это 4 прерывание, но не от СОМпорта, передаю его
> дальше по цепочке.

Обработалось одно прерывание и выход. На самом деле нужно нечто типа

while (!(com_port_interrupt_identification_mask & 1)) {
// Здесь идет switch обработчика и выставляется флаг, что было обработано прерывание от порта
}
// Если флаг не установлен - передать по цепочке

---
А непосредственно *до* этого что происходит? 19.09.03 16:43  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
> Перестают идти прерывания. Может какие-то хитрости с ФИФО?
> Если с ней, то как ее программировать? Какие установки
> по-умолчанию?
ФИФО на прерывания никак не влияет насколько мне известно (в том смысле, что отличие только в размере буфера 1 байт и 16). Влияет только регистр IER (interrupt enable register) и бит OUT2 в MCR (modem control register).

Но. Возможно ты неправильно обрабатываешь само прерывание. Прерывание срабатывает только один раз и пока не будет обработано - следующее такое не придет. А в сочетании с приоритезацией прерываний, возможно ты обрабатываешь только самое высокоприоритетное прерывание и выходишь из обработчика. Бит 0 (No Interrupt Pending) в IIR (interrupt identification register) остается в 0 и прерывание не приходит, так как считается, что до сих пор обрабатывается старое.

А вообще, опиши подробнее, что ты вообще делаешь - будет легче понять что ты делаешь не так.
А непосредственно *до* этого что происходит? 22.09.03 11:36  
Автор: DPP <Dmitry P. Pimenov> Статус: The Elderman
<"чистая" ссылка>
> ФИФО на прерывания никак не влияет насколько мне известно
> (в том смысле, что отличие только в размере буфера 1 байт и
> 16). Влияет только регистр IER (interrupt enable register)
> и бит OUT2 в MCR (modem control register).

Я почему про ФИФО подумал - я ведь точно не знаю как оно работает, потому что документация под руки не попадалась. Думал, что наступает ситуация, когда должно возникнуть прерывание, но первое еще не обработано. Оно (второе) встает в очередь. После обработки первого нужно проверить очередь на наличие в нем отложенного прерывания, а я этого не делаю - не знаю как. Завершаю обработку первого и выхожу из обработчика. Все остальные сигналы продолжают вставать в очередь за вторым...

> Но. Возможно ты неправильно обрабатываешь само прерывание.
> Прерывание срабатывает только один раз и пока не будет
> обработано - следующее такое не придет. А в сочетании с
Подтверждение контроллеру посылаю. Если прерывание от изменения состояния порта - читаю регистр состояния, прерывание по получению данных - считываю их....
> приоритезацией прерываний, возможно ты обрабатываешь только
> самое высокоприоритетное прерывание и выходишь из
> обработчика. Бит 0 (No Interrupt Pending) в IIR (interrupt
> identification register) остается в 0 и прерывание не
> приходит, так как считается, что до сих пор обрабатывается
> старое.

А вот здесь чуть поподробнее.

> А вообще, опиши подробнее, что ты вообще делаешь - будет
> легче понять что ты делаешь не так.

Задача была следующая:
==================================================================
Нужен микропроцессорный контроллер. Два логических входа, один логический выход. На выход выставляется логическая единица при обнаружении логической единицы с первого логического входа. Время, в течение которого на выходе присутствует логическая единица, прямо пропорционально зависит от частоты сигналов на втором логическом входе.
Полезно иметь возможность менять микрокод перепрошивкой ПЗУ (флэш-память желательно). Так же полезно иметь возможность менять параметры: минимальное время присутствия логической единицы на логическом выходе и соотношение частоты логических сигналов на втором логическом входе и времени присутствия логической единицы на логическом выходе.
Минимальный интервал сигналов на первом входе ~5 миллисекунд, на втором ~1 миллисекунда. Максимальная дискретность выходных сигналов ~1 микросекунда. Минимальная частота обработки 1 мегагерц.
Предусмотреть выключение питания, стабилизатор питания от сети постоянного тока 12 вольт, сохранение работоспособности при питающем напряжении в диапазоне от 8 до15 вольт.
Интерфейс: Выход – напряжение питания, ток 3 ампера (до 5 ампер - уточняется), индуктивная нагрузка. Первый вход – 12 вольт активное состояние, управление по фронту, предусмотреть фильтрацию помехи (уточняется). Второй вход потребует усиление до ТТЛ, индуктивный датчик или слаботочный датчик, напряжение милливольты, ток микроамперы.
Возможен вариант: Время логической единицы на выходе имеет фиксированную величину (тоже предусмотреть возможность изменения), если сигнал с третьего логического входа имеет активное состояние, которое равно логическому нулю (замкнут на «землю»).
==================================================================
Перед тем как железяку делать, хотелось бы на писюке отладить.
Взял СОМпорт - есть два сигнала на вход, которые вызывают прерывание, два на выход, хотя хватает одного.
Перепрограммировал таймер под бОльшую частоту. Разумеется во столько же раз реже передаю таймерное прерывание старому обработчику. Ведется свой счетчик. При прерывании от СОМпорта вычитаю разницу счетчиков. В основной программе вывожу эту разницу - сколько раз тикнуло между прерываниями от СОМ порта. На СОМпорт подал сигнал от датчика вращения кулера (как раз 12 вольт и частота нормальная). Примерно в течение секунды чиселки на экране бегут (изменяются около какого-то значения), потом не изменяются ни на единичку.
А непосредственно *до* этого что происходит? 22.09.03 12:04  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
> Я почему про ФИФО подумал - я ведь точно не знаю как оно
> работает, потому что документация под руки не попадалась.
Если ты его не проинициализируешь - оно работать вообще не будет :-)

> Думал, что наступает ситуация, когда должно возникнуть
> прерывание, но первое еще не обработано. Оно (второе)
> встает в очередь. После обработки первого нужно проверить
> очередь на наличие в нем отложенного прерывания, а я этого
> не делаю - не знаю как. Завершаю обработку первого и выхожу
Так и есть. Чтобы проверить наличие отложенного прерывания надо прочитать IIR еще раз. То есть делать это в цикле пока бит 0 не станет в 1.

> > identification register) остается в 0 и прерывание не
> > приходит, так как считается, что до сих пор
> обрабатывается
> > старое.
>
> А вот здесь чуть поподробнее.
Приоритеты прерываний в порядке убывания следующие: RLS, RDA, CTI, THR, MS. А теперь по русски:

RLS - Line error
RDA - Char received
CTI - Timeout (только для FIFO)
THR - Char transmitted
MS - Modem status changed

Как сбрасываются ты знаешь. После сброса прерывания с более высоким приоритетом нужно проверить нет ли прерывания с меньшим. Для этого нужно повторно прочитать IIR.
Вроде как заработало! 23.09.03 11:00  
Автор: DPP <Dmitry P. Pimenov> Статус: The Elderman
<"чистая" ссылка>
> Если ты его не проинициализируешь - оно работать вообще не
> будет :-)

А как это ФИФО инициализировать?
Старые ДОСовские проги спокойно работают на 16550А, и даже не "догадываются" про наличие ФИФО. Они-то это ФИФО не инициализируют.
Может же моя програмка поступать так же?

> Так и есть. Чтобы проверить наличие отложенного прерывания
> надо прочитать IIR еще раз. То есть делать это в цикле пока
> бит 0 не станет в 1.

Попробовал вчера вечером - есть эффект!

> Приоритеты прерываний в порядке убывания следующие: RLS,
> RDA, CTI, THR, MS. А теперь по русски:
>
> RLS - Line error
> RDA - Char received
> CTI - Timeout (только для FIFO)
> THR - Char transmitted
> MS - Modem status changed
>
> Как сбрасываются ты знаешь. После сброса прерывания с более
> высоким приоритетом нужно проверить нет ли прерывания с
> меньшим. Для этого нужно повторно прочитать IIR.

Долго погонять не удалось - времени было мало - поздно приехал. Может быть разок зависало, или мне показалось. Раньше и секунды не работало. Вчера несколько раз по минутке гонял - судя по всему помогло.
Спасибо большое за подсказку. А то я во всяких МАНах и ФАКах ковырялся - ничего об этом не было, видимо старые были, еще про 16450. В некоторых ошибки были - не было указано, что нужно OUT2 установить, чтобы прерывания шли.
Один вопрос остался - как узнать, что это именно 16550А, как установить длину очереди или запретить очередь, как после закидывания байта в передатчик понять, что туда еще один влезет (в очереди еще есть место)?
Вроде как заработало! 23.09.03 12:01  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
> > Если ты его не проинициализируешь - оно работать
> вообще не
> > будет :-)
>
> А как это ФИФО инициализировать?
> Старые ДОСовские проги спокойно работают на 16550А, и даже
> не "догадываются" про наличие ФИФО. Они-то это ФИФО не
> инициализируют.
> Может же моя програмка поступать так же?
Запросто. Когда я говорил, что фифо не будет работать я имел в виду ИМЕННО фифо. То есть порт будет работать как старый 16450 (или как его так, у которого фифо вообще нет).

> Спасибо большое за подсказку. А то я во всяких МАНах и
> ФАКах ковырялся - ничего об этом не было, видимо старые
> были, еще про 16450. В некоторых ошибки были - не было
В 16450 это точно так же сделано. Вообще большую часть инфы о работе порта я почерпнул из чтения сырцов виндового дривера.

> указано, что нужно OUT2 установить, чтобы прерывания шли.
> Один вопрос остался - как узнать, что это именно 16550А,
Вот как это делается в виндовом дривере:
#define SERIAL_IIR_FIFOS_ENABLED 0xc0

        DISABLE_ALL_INTERRUPTS(Extension->Controller);

	WRITE_MODEM_CONTROL(
		Extension->Controller,
		(UCHAR)SERIAL_MCR_OUT2
		);

        //
        // See if this is a 16550.  We do this by writing to
        // what would be the fifo control register with a bit
        // pattern that tells the device to enable fifo's.
        // We then read the iterrupt Id register to see if the
        // bit pattern is present that identifies the 16550.
        //

        WRITE_FIFO_CONTROL(
            Extension->Controller,
            SERIAL_FCR_ENABLE
            );

        regContents = READ_INTERRUPT_ID_REG(Extension->Controller);

        if (regContents & SERIAL_IIR_FIFOS_ENABLED) {
// ФИФО присутствует, это 16550(А)
        }

---

> как установить длину очереди или запретить очередь, как
Очередь запрещена по умолчанию. Если ее не включать - будет работать только RBR (receive buffer register - можно считать однобайтной очередью). Включается в FCR (FIFO control register). Но кроме того придется выставлять еще highwater (порог срабатывания прерывания) и т.д..

> после закидывания байта в передатчик понять, что туда еще
> один влезет (в очереди еще есть место)?
Если работаешь на прерываниях, то тебе придет прерывание, когда он освободится. Если же предпочитаешь поллить, читай LSR (line status register) там два бита THRE (transmit holding register empty) и TEMPT (transmitter empty). THRE ставится в 1, когда очередной байт из буфера ушел в передатчик (но передатчик может еще работать), а TEMPT - когда передатчик не работает.
Вроде как заработало! 23.09.03 14:14  
Автор: DPP <Dmitry P. Pimenov> Статус: The Elderman
<"чистая" ссылка>
> Запросто. Когда я говорил, что фифо не будет работать я
> имел в виду ИМЕННО фифо. То есть порт будет работать как
> старый 16450 (или как его так, у которого фифо вообще нет).

Дык почему мне приходится ИИР пулить, если фифо по-умолчанию выключено? После загрузки голого ДОСа запускается только моя прога - никто ФИФО не включает.

> Очередь запрещена по умолчанию. Если ее не включать - будет
> работать только RBR (receive buffer register - можно
> считать однобайтной очередью). Включается в FCR (FIFO
> control register). Но кроме того придется выставлять еще
> highwater (порог срабатывания прерывания) и т.д..

Что же у меня в очередь вставало? Я то ФИФО не трогал.

> Если работаешь на прерываниях, то тебе придет прерывание,
> когда он освободится. Если же предпочитаешь поллить, читай
> LSR (line status register) там два бита THRE (transmit
> holding register empty) и TEMPT (transmitter empty). THRE
> ставится в 1, когда очередной байт из буфера ушел в
> передатчик (но передатчик может еще работать), а TEMPT -
> когда передатчик не работает.

Прерывание, разумеется, должно произойти, когда буфер (transmit holding register) опустошится, т.е. после закидывания первого байта, если очередь не равна нулю, а потом (после заполнения очереди) с периодом передачи байтиков?

Еще я заметил, что СОМпорт "нежная" вещь. Припаял провода (~3м) к сигналам готовности. Подаю сигнал на один - и во втором тоже сигнал появлялся. Распрямил (скрученные колечком) провода и разнес друг от друга - наводка пропала.
Ты похоже не совсем правильно понял 23.09.03 15:32  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
> > Запросто. Когда я говорил, что фифо не будет работать
> я
> > имел в виду ИМЕННО фифо. То есть порт будет работать
> как
> > старый 16450 (или как его так, у которого фифо вообще
> нет).
>
> Дык почему мне приходится ИИР пулить, если фифо
> по-умолчанию выключено? После загрузки голого ДОСа
> запускается только моя прога - никто ФИФО не включает.
Приоритеты прерываний не имеют вообще никакого отношения к фифо и были, кажется еще в первых UART-ах. А то, что одновременно может несколько прерываний пендиться - могут не обязательно приходить одни и те же прерывания (в частности прерывание "готовы данные"). А если все таки фифо включается, то скорее всего его включает досовский дривер ком порта (устройства COM1:-COM4:, LPT:, AUX: и пр. даже не требуют ничего прописывать в config.sys). Для выключения просто запиши ноль в FCR.
А вообще это не должно тебе мешать - при уже пришедшем прерывании в любом случае нужно читать IIR пока не включится указанный флаг (бит 0). А если так, то включено FIFO или нет, для тебя все будет происходить прозрачно.

> Что же у меня в очередь вставало? Я то ФИФО не трогал.
Могут прийти сразу много прерываний, например есть данные и готов к отправке.


> Прерывание, разумеется, должно произойти, когда буфер
> (transmit holding register) опустошится, т.е. после
> закидывания первого байта, если очередь не равна нулю, а
> потом (после заполнения очереди) с периодом передачи
> байтиков?
В случае с FIFO все иначе. Там есть такая штука как порог срабатывания прерывания. То есть все данные, пришедшие/посылаемые в/из UART-а по прежнему попадают в очередь. Но в зависимости от установки прерывание может происходить когда в очереди 1, 4, 8 и 14 байт.

> Еще я заметил, что СОМпорт "нежная" вещь. Припаял провода
> (~3м) к сигналам готовности. Подаю сигнал на один - и во
> втором тоже сигнал появлялся. Распрямил (скрученные
> колечком) провода и разнес друг от друга - наводка пропала.
Ну это уже железные проблемы. Я свой провод не паял никогда, благо продается куча заводских.
Не то,ч тобы не совсем правильно, но не полностью. 26.09.03 10:44  
Автор: DPP <Dmitry P. Pimenov> Статус: The Elderman
Отредактировано 26.09.03 10:46  Количество правок: 1
<"чистая" ссылка>
> В случае с FIFO все иначе. Там есть такая штука как порог
> срабатывания прерывания. То есть все данные,
> пришедшие/посылаемые в/из UART-а по прежнему попадают в
> очередь. Но в зависимости от установки прерывание может
> происходить когда в очереди 1, 4, 8 и 14 байт.

А ФИФО что, только на прием/передачу работает? Я-то думал, что все прерывания/события встают в очередь, когда обработчик занят обработкой предыдущего события. Или, скажем, процессор временно запретил прерывания (cli), или обрабатывает другое прерывание, или прерывание от того же СОМпорта. В это время изменяется состояние модемных сингалов. Потом оно меняется на первоначальное. Потом разрешаются прерывания от СОМпорта. Вопрос: прерывания не произойдут, потому, что модемные линии вернулись в исходное состояние? прерывание будет, но обработчик ничего не "увидит" в модемных линиях? прерывание будет, но обработчик "узнает" о том ,что линии изменились в одно из состояний? прерывание будет, и опросами портов обработчик "узнает" об обоих изменениях линий?
Похоже 24.09.03 09:56  
Автор: DPP <Dmitry P. Pimenov> Статус: The Elderman
<"чистая" ссылка>
> Приоритеты прерываний не имеют вообще никакого отношения к
> фифо и были, кажется еще в первых UART-ах. А то, что
> одновременно может несколько прерываний пендиться - могут
> не обязательно приходить одни и те же прерывания (в
> частности прерывание "готовы данные"). А если все таки фифо
> включается, то скорее всего его включает досовский дривер
> ком порта (устройства COM1:-COM4:, LPT:, AUX: и пр. даже не
> требуют ничего прописывать в config.sys). Для выключения
> просто запиши ноль в FCR.

Адрес портика ФЦР какой?

> Могут прийти сразу много прерываний, например есть данные и
> готов к отправке.

Да я, в общем-то, только CTS/DSR дергал...

> В случае с FIFO все иначе. Там есть такая штука как порог
> срабатывания прерывания. То есть все данные,
> пришедшие/посылаемые в/из UART-а по прежнему попадают в
> очередь. Но в зависимости от установки прерывание может
> происходить когда в очереди 1, 4, 8 и 14 байт.

Обалдеть... Получается, если длина очереди больше 1, то при приходе одного байтика обработчик об этом и не узнает.

> Ну это уже железные проблемы. Я свой провод не паял
> никогда, благо продается куча заводских.

Мне-то для своей железяки заводской не подходит.
ntddk/src/kernel/serial/serial.h 24.09.03 11:30  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
> > просто запиши ноль в FCR.
>
> Адрес портика ФЦР какой?
// Offsets from the base register address of the
// various registers for the 8250 family of UARTS.
//
#define RECEIVE_BUFFER_REGISTER    ((ULONG)((0x00)*SERIAL_REGISTER_STRIDE))
#define TRANSMIT_HOLDING_REGISTER  ((ULONG)((0x00)*SERIAL_REGISTER_STRIDE))
#define INTERRUPT_ENABLE_REGISTER  ((ULONG)((0x01)*SERIAL_REGISTER_STRIDE))
#define INTERRUPT_IDENT_REGISTER   ((ULONG)((0x02)*SERIAL_REGISTER_STRIDE))
#define FIFO_CONTROL_REGISTER      ((ULONG)((0x02)*SERIAL_REGISTER_STRIDE))
#define LINE_CONTROL_REGISTER      ((ULONG)((0x03)*SERIAL_REGISTER_STRIDE))
#define MODEM_CONTROL_REGISTER     ((ULONG)((0x04)*SERIAL_REGISTER_STRIDE))
#define LINE_STATUS_REGISTER       ((ULONG)((0x05)*SERIAL_REGISTER_STRIDE))
#define MODEM_STATUS_REGISTER      ((ULONG)((0x06)*SERIAL_REGISTER_STRIDE))
#define DIVISOR_LATCH_LSB          ((ULONG)((0x00)*SERIAL_REGISTER_STRIDE))
#define DIVISOR_LATCH_MSB          ((ULONG)((0x01)*SERIAL_REGISTER_STRIDE))
#define SERIAL_REGISTER_SPAN       ((ULONG)(7*SERIAL_REGISTER_STRIDE))

---
Смещение 2 короче. То бишь на чтение это IIR, на запись - FCR.


> > происходить когда в очереди 1, 4, 8 и 14 байт.
>
> Обалдеть... Получается, если длина очереди больше 1, то при
> приходе одного байтика обработчик об этом и не узнает.
Именно. И кстати это хорошо. При пороге в 14 байт сработает одно прерывание на 14 пришедших символов, которое быстренько выгребет их из очереди (а пока обработчик разгребает очередь может прийти и еще символ другой). А при пороге в 1 байт - будет 14 прерываний (со всеми вытекающими: сохранение контекста с последующим восстановлением, причем в защищенном режиме он больше) - оверхед аднака. Хотя и не такой уж большой.
Хорошо то хорошо, да ничего хорошего. 24.09.03 14:07  
Автор: DPP <Dmitry P. Pimenov> Статус: The Elderman
<"чистая" ссылка>
> Смещение 2 короче. То бишь на чтение это IIR, на запись - FCR.

Спасобо.

> Именно. И кстати это хорошо. При пороге в 14 байт сработает
> одно прерывание на 14 пришедших символов, которое
> быстренько выгребет их из очереди (а пока обработчик
> разгребает очередь может прийти и еще символ другой). А при
> пороге в 1 байт - будет 14 прерываний (со всеми
> вытекающими: сохранение контекста с последующим
> восстановлением, причем в защищенном режиме он больше) -
> оверхед аднака. Хотя и не такой уж большой.

Это только для скорости хорошо, правда при частоте в 2-3 гигагерца ловить 11520 прерываний в секунду - мелочи.
А, вот, если надо передать один байтик, и, чтоб, принимающий комп на него СРАЗУ ЖЕ ответил... Байтик упадет в очередь, а обработчик об этом не узнает и не ответит, а компьюер приемник будет ждать. Или при длине пакета не кратного длине очереди. Точнее, если длина пакета больше 2 байт (например, 3), то при длине очереди 2, 4, 8 и 14 эта бяка произойдет.
Все еще немного хуже... 24.09.03 16:05  
Автор: leo <Леонид Юрьев> Статус: Elderman
<"чистая" ссылка>
> Это только для скорости хорошо, правда при частоте в 2-3
> гигагерца ловить 11520 прерываний в секунду - мелочи.
> А, вот, если надо передать один байтик, и, чтоб,
> принимающий комп на него СРАЗУ ЖЕ ответил... Байтик упадет
> в очередь, а обработчик об этом не узнает и не ответит, а
> компьюер приемник будет ждать. Или при длине пакета не
> кратного длине очереди. Точнее, если длина пакета больше 2
> байт (например, 3), то при длине очереди 2, 4, 8 и 14 эта
> бяка произойдет.

Это не совсем так, при включеном FIFO и паузе в передаче, прерывание будет сгенерированно даже при незаполненном FIFO. Этот "таймаут" равет удвоенному времени передачи одного символа (если я не ошибаюсь).

На многих новых чипсетах FIFO отключается только "слегка". Варианты самые разные. Например на передачу "в очередь" можно поставить больше одного байта, даже если FIFO выключено.
При приеме тоже возможны "хитрости", например если вовремя не вычитать данные то будет overrun в статусе линии, но при этом из регистра данных приемника можно считывать принятые и не "затерные" overrun-ом байты. И в некоторых случаях (на некоторых чипах) приемник "не видит" одного принятого байта до таймаута, либо до стартовых битов следующей посылки.

С прерываниями по статусу модема все еще хуже. Почти все чипы допускают "потерю" прерывания по статусу модема, если одновременно с этим возникает еще какое-либо событие (прерывание).

Удачи!
http://leo.yuriev.ru/SerialXP
Все еще немного хуже... 25.09.03 10:30  
Автор: DPP <Dmitry P. Pimenov> Статус: The Elderman
<"чистая" ссылка>
> Это не совсем так, при включеном FIFO и паузе в передаче,
> прерывание будет сгенерированно даже при незаполненном
> FIFO. Этот "таймаут" равет удвоенному времени передачи
> одного символа (если я не ошибаюсь).
Это радует.
Я просто хотел "таймер" на порте организовать: после передачи байтика "в никуда" в обработчике еще один туда же запихнуть.
> На многих новых чипсетах FIFO отключается только "слегка".
> Варианты самые разные. Например на передачу "в очередь"
> можно поставить больше одного байта, даже если FIFO
> выключено.
> С прерываниями по статусу модема все еще хуже. Почти все
> чипы допускают "потерю" прерывания по статусу модема, если
> одновременно с этим возникает еще какое-либо событие
> (прерывание).
Прерывания модемные, надеюсь.

А вот это очень неприятно, если это действительно так. Не хочется события терять.

> Удачи!
> http://leo.yuriev.ru/SerialXP
1  |  2 >>  »  




Rambler's Top100
Рейтинг@Mail.ru


  Copyright © 2001-2024 Dmitry Leonov   Page build time: 1 s   Design: Vadim Derkach