Page 2 of 2

Posted: Wed Mar 08, 2006 6:33 pm
by Serge
COM1: "Эй, начальник! У тебя есть данные передачи для меня?"

CPU: "Нет, отстань, приказываю сбросить запрос IRQ!"

СИТЕМА: "Есть, запрос сброшен!"

прошло время текущего аппаратного цикла UART COM1, наступил момент нового (пусть несколько мкс)....

COM1: "Эй, начальник! У тебя есть данные передачи для меня?"

CPU: "Задолбал он меня, хоть бы этот порт закрыл кто! Дармоед моего времени, расточитель! Вредитель! Приказываю сбросить запрос IRQ!!!"

СИТЕМА: "Есть, запрос сброшен!"
На самом деле микросхема UART достаточно умна и не дергает CPU все время.
После чтения соответствующего Interrupt Identification Register прерывание будет сброшено.

Posted: Wed Mar 08, 2006 7:22 pm
by Mario79
VaStaNi
В том то и дело что универсальности пока не получается. Я, например, сделал обработку мыши как следует, а тут пару дней назад узнал от человека, что модем перестал работать, придется совмещать старый и новый код, так как менять все и сразу тяжело.

Heavyiron
Хех ну ты сказанул! Когда два чела не имеющих отношения к компам начинают обсуждать третьего, который комперами занимается, то одним кручением у виска дело не ограничивается. Что уж говорить о том, что говорят нормальные продвинутые юзвери про нас маньяков железа и кода. ;-)

Posted: Thu Mar 09, 2006 2:21 pm
by VaStaNi
Serge wrote: На самом деле микросхема UART достаточно умна и не дергает CPU все время.
После чтения соответствующего Interrupt Identification Register прерывание будет сброшено.
ЕДИНОЖДЫ! Единожды ДА, сброшено, что и отображено в первой части "действия в лицах" :). Хочешь разобраться или проверить, так давай! Только факты приводи, ссылки, детали и все станет на свои места. А если сразу непонятно, с первого раза, так я не отказываюсь "резжевать" любой подробный момент, ничего зазорного и стыдного в том нет. Когда то давным давно, мой любимый преподаватель физики приводил цитату: "Если ты знаешь, ЧТО не понимаешь, то это первый шаг к пониманию!".
А про "ум" UART, это перебор! Тупой он и прямой... ну как пробка! :)

Posted: Thu Mar 09, 2006 6:53 pm
by Serge
О тупости UART

When the CPU accesses the IIR. the UART freezes all interupts
and indicates the higest priority pending interrupt
to the CPU. While this CPU access is occuring, the UART records new
interrupts, but does not change its current indication until the access
is complete.

говоря по-русски:
когда мы обрабатываем прерывание UART надо

1. считать IIR, проверить бит 0, если он установлен в 1
то есть прерывание UART, если 0 то обработку можно закончить

2. проверяем биты 1,2,3 и обрабатываем исключения.

3. возвращаемся к п.1

если бит 1 установлен в 1, а биты 2 и 3 в 0 то Transmitter Holding
Register пуст ( или опустело FIFO передатчика в FIFO режиме)
прерывание сбрасывается чтением IRR (что уже произошло) или записью
байта в THR (или FIFO передатчика). В следующий раз прерывание от
THR (FIFO) появится только после того как в него будут записаны данные и он
снова опустеет.

Источники:

National Semiconductor
PC16550D Universal Asynchronous Reciever/Transmitter with FIFOs

качать с http://www.datasheetarchive.com в строке поиска набрать PC16550D

Posted: Thu Mar 09, 2006 9:24 pm
by VaStaNi
Во! Уже пошел интересный творческий, я надеюсь, диалог (не люблю споры).
Итак. Сложилось впечатление непонимания именно с твоей стороны. Аргументирую.
1. Я говрил именно о ПРИЧИНЕ периодических запросов IRQ к процессору, причем указав, конкретно, что речь и проблематика, именно с режимом прерывания опустошение буфера Tx UART.
2. Описывал общую временную статистику состояния этого буфера.
3. Берем мануалы. У меня нет конкретно National Semiconductor, у меня сейчас под рукой, Texas Instruments и EXARвские, но суть от этого не пострадает. Итак, IIR - не что иное, как регистр статуса, причины прерывания, который можно рассматривать как флаговый прерываний.
По отношению к данному вопросу это флаг "1" в бите 1 этого регистра. Т.е. грамотно писаный обработчик прерываний от UART (COM) в самом начале кода (после всех сохранений, PUSH и инитов нужного) сортирует, вернее сказать анализирует эти биты В ПОРЯДКЕ ПРИОРИТЕТОВ IIR как флаги.
Мануал гласит (у меня открыта сводная таблица по IIR это "Table 5. Interrupt Control Functions")

INTERRUPT TYPE_|_INTERRUPT SOURCE_|__INTERRUPT RESET METHOD
______________|_________________|_________________________
Transmitter_____| Transmitter_______|_Reading the interrupt identification
holding________|__holding__________|_register (IIR) (if source of interrupt)
register________|_register__________|_or writing into the transmitter
empty_________|__empty__________|_holding register (THR)

То есть понимаем буквально, что источником (SOURCE) возникновения ЭТОГО бита в IIR является причина: Transmitter holding register empty т.е. пуст! А занчит IRQ будет генерироваться соответствующим выходным сигналом UART пока он ИМЕЕНО ПУСТ!, а пуст он, читать топик выше, сколько времени...
Сброс, говоришь, ну сбросил, если прочитан IIR или послал... но речь именно в том, что не посылаем мы в него постоянно, т.к. ОБЩАЯ пауза ЗНАЧИТЕЛЬНО превышает само времы передачи чего либо в UART!
А следовательно имеется состояние именно Transmitter holding register empty ---> генерация нового IRQ! Т.е. сколько не сбрасывай его (пока именно данный тип прерывания активирован) он опять спросит своим IRQ :) : "Эй, начальник! У тебя есть данные передачи для меня?" ;)
4. Ты пишешь п." 3. возвращаемся к п.1" Зачем возвращаемся????
Постоянно в еще одном кольце CPU`шных задач проверять биты IIR, чтобы он "не скучал" и дабы не пропустить момент, когда.... т.е. PIO!??? А зачем тогда вообще IRQ?
5. Я мог кое что и подзабыть, память моя далеко не идеал...+ драйвер долизывыал (все эти фичи и борьба с ними, доки...) где то пол-года назад, так что если очень надо и досконально я могу поднять работы и еще раз препроверить на реальном драйвере и реальном железе. Если очень надо или твои аргументы будут убедительны - сделаю.

Posted: Fri Mar 10, 2006 2:45 am
by Serge
1. считать IIR, проверить бит 0, если он установлен в 1
то есть прерывание UART, если 0 то обработку можно закончить
небольшая поправка.

UART сохраняет прерывания от нескольких источников и выдает их в порядке приоритетов (ошибка паритета/разрыв линии, приемник полон, таймаут в режиме FIFO, передатчик пуст, статус модема)

пока запустится обработчик IRQ может (теоретически) произойти несколько событий.
UART позваляет обработать их все за один вызов. Если бит 0 установлен в 1 то остаются еще необработанные исключения и мы можем обработать их все за один вызов. это лучше чем
mov al, EOI
out 21h, al
и мы снова получаем запрос IRQ
потому я и говорю, что UART не глупа.
То есть понимаем буквально, что источником (SOURCE) возникновения ЭТОГО бита в IIR является причина: Transmitter holding register empty т.е. пуст! А занчит IRQ будет генерироваться соответствующим выходным сигналом UART пока он ИМЕЕНО ПУСТ!, а пуст он, читать топик выше, сколько времени...
в том то и дело что не пока он ИМЕННО ПУСТ. THR генерирует прерывание не все время пока пуст,а только один раз - когда становится пустым . Прерывание сбрасывается чтением IRR (оно третье в списке по приоритету и может понадобится несколько считываний - см. выше) или записью байта в THR
в следующий раз прерывание появится только после того как THR будет заполнен и снова опустеет. Фактически это прерывание наступает по фронту события а не по уровню.

Posted: Fri Mar 10, 2006 8:03 pm
by VaStaNi
Serge wrote:UART сохраняет прерывания от нескольких источников и выдает их в порядке приоритетов (ошибка паритета/разрыв линии, приемник полон, таймаут в режиме FIFO, передатчик пуст, статус модема) пока запустится обработчик IRQ может (теоретически) произойти несколько событий.
UART позваляет обработать их все за один вызов. Если бит 0 установлен в 1 то остаются еще необработанные исключения и мы можем обработать их все за один вызов. это лучше чем
mov al, EOI
out 21h, al
и мы снова получаем запрос IRQ
потому я и говорю, что UART не глупа.
Да я и не против такой обработки, тем более что это демонстрируют хорошие исходники, хотя я 0 бит не считаю нужным использовать, я анализирую и обрабатываю в порядке приоритета все остальные флаги при любои входе в обработчик. Ну ладно, раз это интеллект UART, ты считаешь, пусть будет так. :)
Serge wrote:
То есть понимаем буквально, что источником (SOURCE) возникновения ЭТОГО бита в IIR является причина: Transmitter holding register empty т.е. пуст! А занчит IRQ будет генерироваться соответствующим выходным сигналом UART пока он ИМЕЕНО ПУСТ!, а пуст он, читать топик выше, сколько времени...
в том то и дело что не пока он ИМЕННО ПУСТ. THR генерирует прерывание не все время пока пуст,а только один раз - когда становится пустым . Прерывание сбрасывается чтением IRR (оно третье в списке по приоритету и может понадобится несколько считываний - см. выше) или записью байта в THR
в следующий раз прерывание появится только после того как THR будет заполнен и снова опустеет. Фактически это прерывание наступает по фронту события а не по уровню.
Где про одноразовость, несколько считываний, фронт можно прочитать? Это реально пробовал или по докам цитируешь?
То что ты описал, пожалуй триггерным эффектом зовётся, а не фронтом. Т.е. хош сказать раз погасил и взведется он снова только после записи в порт и ег дальнейшего опустошения. Я был бы очень рад такому его поведению, хотя я мог что то и упустить и не понять, т.к. мой инглиш very bad! :) Но что то смутно мне подсказывают воспоминания при отладке, что не зря я это таким макаром порешил с режимом этим общаться. Вероятно перепроверить придется таки...

Posted: Fri Mar 10, 2006 11:48 pm
by Serge
Практика критерий истины.
Вот маленькая програмка.
отправляет строку АТ комманд модему и принимает ответ

cmd_str - АТ команды для модема
можно пробовать разные варианты

мдем подлючен к сом1 прерывание по дефолту

запускать можно в WIN и в DOS но в WIN результаты могут отличаться
в конце дает статистику сколько байт отправлено и сколько THR_пуст прерываний было
FIFO отключен специально

0х0а в конце АТ команды используется как терминатор строки для
функции send

include 'proc32.inc'

format MZ
heap 0
stack 8000h
entry main:start


THR equ 0x3f8 ;0x2F8
IER equ 0x3f9 ;0x2F9
IIR equ 0x3fa ;0x2Fa
LCR equ 0x3FB ;0x2FB
MCR equ 0x3FC ;0x2FC
IRQ_VEC equ 0x0C ;0x0B

RATE equ 12; 9600 bps

IDLE equ 0;
TRANSMIT equ 1;

segment main use16

use16

start:
mov ax,_data
mov ds, ax
mov es, ax

mov ss,ax
mov sp, 0x2000
mov bp, sp

mov dx,_logo
mov ah,9
int 21h

call disable_uart_intr
call disable_FIFO
call set_mode

lea ax, [inp_buffer]
mov [inp_ptr], ax

call set_handler

call enable_uart_intr
call enable_com_irq

lea ax, [inp_buffer]
mov [inp_ptr], ax
xor ax, ax
mov [inp_count], ax
mov [out_count], ax
mov [trhe_count], ax

lea ax, [cmd_str]
call send_str

mov dx, _trans
mov ah,9
int 21h
mov dx, cmd_str
mov ah,9
int 21h
mov dx, _rec
mov ah,9
int 21h
mov dx, _anykey
mov ah,9
int 21h

mov ah, 0
int 16h
call restore_handler

mov dx, _msg_rec
mov ah,9
int 21h
mov dx, inp_buffer
mov ah,9
int 21h

mov dx, _t_bytes
mov ah,9
int 21h
mov di, inp_buffer
mov bx, [out_count]
call word2str
mov dx, inp_buffer
mov ah,9
int 21h

mov dx, _msg_trhe
mov ah,9
int 21h
mov di, inp_buffer
mov bx, [trhe_count]
call word2str
mov dx, inp_buffer
mov ah,9
int 21h

mov ah,4ch
int 21h

align 4
proc disable_uart_intr

mov edx, IER
xor eax,eax
out dx, al
ret
endp

align 4
proc enable_com_irq
cli
in al, 21h
and al, 011100111b ;размаскируем irq3 и irq4
out 21h, al
sti
ret
endp

align 4
proc enable_uart_intr
mov dx, IER
mov ax, 0x03 ;приемник полон передатчик пуст
out dx, al
ret
endp

proc set_mode

mov dx, LCR
in al, dx
or al, 80h
out dx, al

mov dx, THR
mov al, RATE
out dx, al

inc dx
xor al, al
out dx, al

mov dx, LCR
mov al, 3
out dx, al

mov dx, MCR
mov al,0bh
out dx, al

ret
endp

proc set_handler

push es
mov ax, 0
mov es, ax

mov bx, IRQ_VEC
shl bx, 2

mov ax, [es:bx]
mov [old_offset], ax
mov ax, [es:bx+2]
mov [old_seg], ax

cli
lea ax, [com_handler]
mov [es:bx], ax
mov ax, cs
mov [es:bx+2], ax
sti

pop es

ret
endp

proc restore_handler

push es
mov ax, 0
mov es, ax

mov bx, 0x30

cli
mov ax, [old_offset]
mov [es:bx], ax

mov ax, [old_seg]
mov [es:bx+2], ax
sti

pop es

ret
endp

align 4
proc send_str

mov [out_ptr], ax
mov [out_count], 0
mov [mode], TRANSMIT
mov si, ax
mov al, [si]
mov dx, THR
out dx, al

sti

.l1: cmp [mode], TRANSMIT ;надо вставить проверку на таймаут
jnz .l2
hlt
jmp .l1

.l2:

ret
endp

align 4
proc send

add [trhe_count], 1
cmp [mode], TRANSMIT
jne .exit

mov si, [out_ptr]
add si, 1
mov [out_ptr], si
add [out_count], 1
mov al, [si]
cmp al, 0ah
jz .trans_end

mov dx, THR
out dx, al

.exit:
ret

.trans_end:
mov [mode], IDLE

ret
endp

align 4
proc recieve

mov si,[inp_ptr]
mov dx, THR
in al, dx
mov [si], al
add [inp_ptr], 1
add [inp_count], 1

ret
endp

align 4
proc com_handler
cli
pusha
push ds
push es

mov ax,_data
mov ds, ax

xor ax, ax
mov dx, IIR
in al, dx
mov [iir_save], al

and ax, 0110b

cmp ax, 2 ;передатчик пуст
jnz .m1

call send

jmp .l2

.m1:
cmp ax, 4 ; приемник заполнен
jnz .l2
call recieve
jmp .l2


.l2:
mov al, 20h
out 20h, al

pop es
pop ds
popa
sti
iretw
endp

align 4
proc disable_FIFO
mov dx, IIR
xor al, al
out dx, al
ret
endp

proc word2str

rol bx, 4
call conv
rol bx, 4
call conv
rol bx, 4
call conv
rol bx, 4
call conv
mov byte [di], 24h
ret
endp

proc conv
mov al, bl
and ax, 0x0f
aaa
adc al, 0x30
db 0xd5
db 0x10
mov [di], al
add di, 1
ret
endp

segment _data use16
align 4
old_offset dw ?
old_seg dw ?
row dw 0

mode dd 0
out_ptr dw 0
out_count dw 0
iir_save db 0

trhe_count dw 0

inp_ptr dw 0
inp_count dw 0

align 4
inp_buffer dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24000000h

_logo db ' init uart... ',0Dh, 0Ah,24h

cmd_str db 'AT', 0Dh, 0ah,24h
;cmd_str db 'ATQ0V1E0', 0dh, 0ah , 24h
;cmd_str db 'AT+GMM', 0dh, 0ah, 24h

_trans db 0dh, 0ah,' transmit command $'
_rec db 0dh, 0ah, ' recieve data... please wait, then$'
_anykey db 0dh, 0ah, ' press any key...$'
_msg_rec db 0dh, 0ah, ' recieve message',0dh,0ah, 24h
_t_bytes db 0dh, 0ah, ' bytes transmitted $'
_msg_trhe db 0dh, 0ah, ' total trhe interrupts $'

Posted: Mon Mar 13, 2006 2:03 pm
by VaStaNi
Serge, беру свои словесные выкладки назад по поводу ПОВТОРНОГО и ПОВТОРЯЮЩЕГОСЯ запроса IRQ по причине пустого буфера Tx. На выходных поднял, слапал еще более упрощенный вариант чем у тебя, правда был, и убедился. Да, ты прав, БОЛЬШОЕ СПАСИБО за такой интересный нюанс, поправку!!! Это вообще отлично.
Еще поправлюсь, кажется выше я говорил про дефолтный обьем FIFO=16байтам, так вот, я перепутал. При настройках исходно он оказался =1 байту, т.е. аналого самого тупого UART времен XT(ох и любят они эту совместимость с динозаврами). Доки в принципе все говорят КАК сделать иное, но беглое решение тем, кто интересуется могу привести, коль уж тут про всякие подробности потрохов пошло... Итак, обьем FIFO устанавливается, так же, как и скорость, т.е. с предваритеьным включением доступа в порту 0x..FB кратко и лениво, напраимер, так:
mov dx, 0x3F8 ;COM1 base port
add dx, 3 ;=0x3FB
mov al, 0x80
out dx, al ; включить доступ
dec dx ;=0x3FA
mov al, 0xF1 ;включить МАКСИМАЛЬНЫЕ FIFO обьемы в обоих направлениях
out dx, al
; далее следеут классика установки скоростной константы делителя в портах 0x..F8 и 0x..F9

Posted: Mon Mar 13, 2006 8:17 pm
by Serge
VaStaNi

Почитал еще раз мануалы.

FIFO включается установкой в 1 бита 0 в регистр 0x..FA а биты 6 и 7
задают порог при котором выдается прерывание приемник полон

биты 7 6 уровень триггера

0 0 1 байт
0 1 4 байт
1 0 8 байт
1 1 14 байт

запись 1 в бит 1 очищает FIFO приемника
запись 1 в бит 2 очищает FIFO передатчика
биты 4 и 5 зарезервированы, но это может зависить от
реализации

ещё FIFO приемника может выдавать прерывание по таймауту
если в буфере есть данные, а мы их не читали (или не было принято
данных) за время необходимое для передачи 4 байт

бит 7 в регистре 0x..FB - это защелка для установки делителя
частоты устанвливаем в 1 пишем в 0x..F8 0x..F9 делитель
частоты и снова сбрасываем в 0.

И еще раньше писал про бит 0 в IIR оказалось все наоборот
если он 0 то есть прерывание, а если 1 то нет. Странная логика.

Posted: Tue Mar 14, 2006 11:09 am
by VaStaNi
Serge wrote: Странная логика.
:) да, уж! Как говорит один мой знакомый в таких случаях: "Курите, Шура мануалы!" (как ни странно люди на перкурах много мыслят бывает, общаются, перетирают интересующие темы...) :)