Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Asm: Общие вопросы > Прерывание COM порта


Автор: bi0w0rm 29.12.2004, 01:24
Ситуация такая: переписал таблицу прерываний в реальном режиме, инициализировал порт, подключаю устройство, точно знаю, что байты отправляет, точно знаю его скорость, т.е. все вроде бы правильно, однако никак не могу поймать прерывание, прога не переходит на новый обработчик... даже контроллер порта принимает байты, т.к. содержимое входного регистра меняется.
Очень хотелось реализовать прерывание, однако вышел из положения банальной хитростью, заставил внешнее устройство после каждого достоверного байта отправлять фиктивный, отличный от предыдущего и от следующего... в итоге приходится постоянно опрашивать входной регистр, из-за этого не хватает быстродействия.
кто знает что-нить, помогите!!

заранее спасибо!

Автор: bel_nikita 29.12.2004, 01:34
А ось какая?

Автор: bi0w0rm 29.12.2004, 01:40
а ось - ДОСь... все в реальном режиме.

Автор: Chingachguk 5.1.2005, 04:13
Покажи, как точно ты инициализируешь порт, разрешаешь прерывания и тому подобное.

Вот как примерно я работал с портом (плюс ухищрения для 98-ой):

Код

{ base          - базовый адрес порта (3F8 для Com1)                          }
{ irq           - уровень прерывания (4 для Com1)                             }
{ opcode        - код настройки порта                                         }
{                 76543210  76543210                                          }
{                    ¦¦¦¦¦  L+++++++ код скорости (6*2**N=19200/2**N)         }
{                    ¦¦¦L+---------- код длины (00=5, 01=6, 10=7, 11=8)       }
{                    ¦¦L------------ код кадра (0=1, 1=2)                     }
{                    L+------------- код четности (00=n, 01=o, 10=n, 11=e);   }

Const
 {*** Регистры модема/порта ***}
 DAT = 0; { регистр данных }
 IER = 1; { регистр разрешения прерывания }
 IIR = 2; { регистр идентификации прерывания }
 LCR = 3; { регистр управления линией }
 MCR = 4; { регистр управления модемом }
 LSR = 5; { регистр состояния линии }
 MSR = 6; { регистр состояния модема }

Var
 LineInUse     :boolean;
 SavedExit     :pointer;

Var

 SaveOldIn1C: pointer; { Old 1Ch vector }
 Dword0087: longint; { Old 1Bh vector }
 Dword008B: longint; { Old 23h vector }
 Dword008F: longint; { Old xx  vector (com port interrupt) }
 Word0093:  Word;    { Port base address }
 Byte0095:  Byte;    { Relative com port interrupt number }
 Byte0096:  Byte;
 TimeCount: Word;    { Timeout ticks }
 Byte0099:  Byte;

Const

 IntMaskList: array[1..8] of Byte = ($01,$02,$04,$08,$10,$20,$40,$80);

Var
 { Буфер передачи }
 { Word: количество байтов в буфере }
 { Word: указатель записи (start=SendBuffer) }
 { Word: указатель извлечения (start=SendBuffer) }
 { Array[1..BufferSize] of bytes: буфер }
 SendRing: Array[1..(2+2+2+BufferSize)] of Byte;

 { Буфер приема }
 { Word: количество байтов в буфере }
 { Word: указатель записи (start=RecBuffer) }
 { Word: указатель извлечения (start=RecBuffer) }
 { Array[1..BufferSize] of bytes: буфер }
 RecvRing: Array[1..(2+2+2+BufferSize)] of Byte;

{*** local subprograms ***}
{*** Startup the RingBuffer ***}
Procedure Clear_RingBuffer(BuffAddr:Word);
 begin
 asm
 mov  si,BuffAddr
 mov  word ptr [si],0000h
 mov  bx,si
 add  bx,0006h
 mov  [si+02],bx
 mov  [si+04],bx
 end;
 end;
{*** Переместить указатель в кольцевом буфере ***}
Function IncrementRingPointer(StartPo:Word):Word;
 begin
 asm
 mov  bx,StartPo
 inc  bx
 add  si,BufferSize+6
 cmp  bx,si
 jb   @@L0AEA
 sub  bx,BufferSize
@@L0AEA:
 sub  si,BufferSize+6
 mov  @Result,bx
 end;
 end;
{*** Put data byte into ring buffer ***}
Procedure PutDataIntoRingBuff(SendData: Byte; RingAddr:Word);
 begin
 asm
 mov  si,RingAddr
 cmp  word ptr [si],BufferSize
 jnb  @@BufferFull
 inc  word ptr [si]
 mov  bx,[si+02]
 mov  al,SendData
 mov  [bx],al
 push bx
 call IncrementRingPointer
 mov  [si+02],ax
@@IsData:
 clc
 jmp  @@Done
@@BufferFull:
 stc
@@Done:
 end;
 end;
{*** Get byte from ring buffer ***}
Function GetByteFromRingBuffer(RingAddr:Word):Byte;
 begin
 asm
 mov  si,RingAddr
 cmp  word ptr [si],0000
 jz   @@BuffEmpty
 dec  word ptr [si]
 mov  bx,[si+04]
 mov  al,[bx]
 push ax
 push bx
 call IncrementRingPointer
 mov  [si+04],ax
 pop  ax
 jmp  @@IsData
@@IsData:
 mov  @Result,al
 clc
 jmp  @@Done
@@BuffEmpty:
 mov  @Result,0
 stc
@@Done:
 end;
 end;
{*** Запись в порт=Base(Word0093)+Register байта OutByte ***}
{*** Выполняется с задержкой ***}
Procedure OutPortByte(OutByte:Byte; Register:Byte);
 begin
 asm
 pusha
 mov  dx,Word0093
 add  dl,Register
 adc  dh,0
 mov  al,OutByte
 {Задержка}
 mov  cx,0FFFFh
@@WaitDevice:
 loop @@WaitDevice
 out  dx,al
 popa
 end;
 end;
{*** Чтение из порта=Base(Word0093)+Register байта ***}
{*** Выполняется с задержкой ***}
Function InPortByte(Register:Byte):Byte;
 begin
 asm
 pusha
 mov  dx,Word0093
 add  dl,Register
 adc  dh,0
 {Задержка}
 mov  cx,0FFFFh
@@WaitDevice:
 loop @@WaitDevice
 in   al,dx
 mov  @Result,al
 popa
 end;
 end;

{$F+}
procedure OpenLine(base,irq,opcode:word);
 begin
 asm
 mov  ax,base
 mov  Word0093,ax
 {Prepare Line ?}
 { Wr[IER],0 }
 push 0
 push IER
 call OutPortByte
 { Wr[LCR],80h }
 push 80h
 push LCR
 call OutPortByte
 { Wr[DAT],cl }
 mov  cx,opcode
 xor  ax,ax
 mov  al,cl
 push ax
 push DAT
 call OutPortByte
 { Wr[LCR],ch }
 xor  ax,ax
 mov  al,ch
 push ax
 push LCR
 call OutPortByte
 { Rd[LSR] }
 push LSR
 call InPortByte
 { Rd[DAT] }
 push DAT
 call InPortByte

 mov  ax,irq
 and  al,07h
 mov  Byte0095,al
 { Save old int 1Ch }
 mov  ax,351Ch
 int  21h
 mov  word ptr SaveOldIn1C,bx
 mov  word ptr SaveOldIn1C+2,es
 { Save old int 1Bh }
 mov  ax,351Bh
 int  21h
 mov  word ptr Dword0087,bx
 mov  word ptr Dword0087+2,es
 { Save old int 23h }
 mov  ax,3523h
 int  21h
 mov  word ptr Dword008B,bx
 mov  word ptr Dword008B+2,es
 { Save old int xxh - com port line }
 mov  al,Byte0095
 add  al,08h
 mov  ah,35h
 int  21h
 mov  word ptr Dword008F,bx
 mov  word ptr Dword008F+2,es
 { Clear Send buffer }
 push offset SendRing
 call Clear_RingBuffer
 { Clear Receive buffer }
 push offset RecvRing
 call Clear_RingBuffer
 { Set new vector for int 1Ch }
 push ds
 push cs
 pop  ds
 mov  dx,offset @@Proc0B9D
 mov  ax,251Ch
 int  21h
 { Set new vector for int 1Bh }
 mov  dx,offset @@L0BB1
 mov  ax,251Bh
 int  21h
 { Set new vector for int 23h }
 mov  dx,offset @@L0BB1
 mov  ax,2523h
 int  21h
 pop  ds
 { Wr[IER],0 }
 push 0
 push IER
 call OutPortByte
 { Set new vector for int xx - com port line }
 mov  dx,offset @@Proc0B03
 mov  al,Byte0095
 add  al,08h
 mov  ah,25h
 push ds
 push cs
 pop  ds
 int  21h
 pop  ds
 cli
 mov  cx,opcode
 { Wr[LCR],80h }
 push 80h
 push LCR
 call OutPortByte
 { Wr[DAT],cl }
 xor  ax,ax
 mov  al,cl
 push ax
 push DAT
 call OutPortByte
 { Wr[LCR],ch }
 xor  ax,ax
 mov  al,ch
 push ax
 push LCR
 call OutPortByte
 { Rd[LSR] }
 push LSR
 call InPortByte
 { Rd[DAT] }
 push DAT
 call InPortByte
 mov  al,0Ch
 mov  Byte0099,al
 { Wr[MCR],0Ch }
 mov  ah,0
 push ax
 push MCR
 call OutPortByte
 { Rd[LSR] }
 push LSR
 call InPortByte
 { Rd[DAT] }
 push DAT
 call InPortByte
 push 0Fh
 push IER
 call OutPortByte
 mov  al,Byte0095
 mov  bx,offset IntMaskList
 xlat
 mov  Byte0096,al
 not  al
 mov  ah,al
 in   al,21h
 and  al,ah
 out  21h,al
 sti
 jmp  @@SkipHandlers
 {*** Handlers Area ***}
 { Int xxh handler at 0B03 }
@@Proc0B03:
 sti
 push ax
 push bx
 push cx
 push dx
 push si
 push ds
 push bp
 mov  ax,seg @Data
 mov  ds,ax
@@L0B0E:
 mov  dx,Word0093
 add  dx,0002h
 in   al,dx
 and  ax,0007h
 test ax,0001h
 jz   @@L0B29
 mov  al,20h
 out  20h,al
 pop  bp
 pop  ds
 pop  si
 pop  dx
 pop  cx
 pop  bx
 pop  ax
 iret
@@L0B29:
 cmp  ax,0004h
 jb   @@L0B42
 push ax
 mov  dx,Word0093
 add  dx,0001h
 in   al,dx
 or   al,02
 mov  dx,Word0093
 add  dx,0001h
 out  dx,al
 pop  ax
@@L0B42:
 mov  bx,offset @@IntList
 add  bx,ax
 jmp  word ptr cs:[bx]
@@IntList: dw offset @@Proc0B51,offset @@Proc0B5B
          dw offset @@Proc0B81,offset @@Proc0B92
@@Proc0B51:
 mov  dx,Word0093
 add  dx,0006h
 in   al,dx
 jmp  @@L0B0E
@@Proc0B5B:
 push offset SendRing
 call GetByteFromRingBuffer
 jb   @@L0B6D
 mov  dx,Word0093
 add  dx,0000h
 out  dx,al
 jmp  @@L0B0E
@@L0B6D:
 mov  dx,Word0093
 add  dx,0001h
 in   al,dx
 and  al,0FDh
 mov  dx,Word0093
 add  dx,0001h
 out  dx,al
 jmp  @@L0B0E
@@Proc0B81:
 mov  dx,Word0093
 add  dx,0000h
 in   al,dx
 push ax
 push offset RecvRing
 call PutDataIntoRingBuff
 jmp  @@L0B0E
@@Proc0B92:
 mov  dx,Word0093
 add  dx,0005h
 in   al,dx
 jmp  @@L0B0E
{*** Прерывания от таймера ***}
{ Уменьшает значение ячейки TimeCount при каждом вызове }
@@Proc0B9D:
 push ax
 push ds
 mov  ax,seg @Data
 mov  ds,ax
 cmp  word ptr ds:TimeCount,0
 jz   @@SetZeroCount
 dec  ds:word ptr TimeCount
@@SetZeroCount:
 pop  ds
 pop  ax
@@L0BB1:
 iret
@@SkipHandlers:
 end;
 end;

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)