x86 timer2 8254/8253: всегда создает 1s вместо wave

# #assembly #timer #x86 #masm #real-mode

Вопрос:

Я пытаюсь сделать аппаратную задержку, используя счетчик 2 из 8254 микросхем, создав квадратную волну и подсчитав, сколько раз значение квадратной волны получало 1:

 
mov al, 10101110B
out 43H, al
        
mov al, 33h
out 42H, al
mov al, 05h
out 42H, al
        
;;enable the port
in AL, 61H
push ax
OR AL, 00000011B ;;enable PB0 and PB1
out 61h, al
        
mov cx, 200
;;make delay
        
waitf1:
        in al, 62H ;; Reads from 62H The result is always 20h
        and al, 20h 
        cmp al, ah
        je waitf1
            
        mov ah, al
        loop waitf1
            
        
        

pop ax
out 61h, al

 

программа работает в цикле, так как значение, считываемое с порта 62h , равно alwas 20h ( PC5 всегда равно 1), в то время как я ожидал, что это будет квадратная волна.

Ответ №1:

Мне интересно, имеет ли значение, находится ли таймер в режиме 2 или нет. Вот старый ассемблерный код, который я использовал, чтобы получить точное время из timer0 с помощью MSDOS. Короткие задержки jmp в размере $ 2 были необходимы, возможно, потому, что процессор работал немного быстрее, чем шина ISA. Поскольку этот код получает 16-битное количество от таймера, бит 15 может быть использован для шаблона прямоугольной волны. Количество прерываний, считанное в dx в этом коде, не требуется для исходного вопроса.

 TMR     equ     040h
Tmrgt0: cli
        mov     dx,IntCnt               ;get current int count
        mov     al,0c2h                 ;output read channel 0 cmd
        out     TMR 3,al
        jmp     short $ 2
        in      al,TMR                  ;get bit  (15  )
        test    al,2                    ;br if in mode 2
        jz      Tmrgt1
        shl     al,1
        jmp     short $ 2
        in      al,TMR                  ;get bits ( 7-0) << 1
        mov     ah,al
        jmp     short $ 2
        in      al,TMR                  ;get bits (14-8) << 1
        sti
        xchg    al,ah                   ;ax = bits 15-0
        rcr     ax,1
        test    ax,07fffh               ;if bits (14-0) == 0 re-get
        jz      Tmrgt0
        cmp     dx,IntCnt               ;if int occured re-get
        jne     Tmrgt0
        neg     ax                      ;make count positive
        ret

Tmrgt1: in      al,TMR                  ;get bits ( 7-0)
        mov     ah,al
        jmp     short $ 2
        in      al,TMR                  ;get bits (15-8)
        sti
        xchg    al,ah                   ;ax = bits 15-0
        cmp     dx,IntCnt               ;if int occured re-get
        jne     Tmrgt0
        neg     ax                      ;make count positive
        ret
 

Комментарии:

1. Это тоже не работает с режимом 3. Я также меняю частоту на минимально возможную (значение в 42 часа на 0xFFFF ), но без изменений. Кажется, что квадратная волна не генерируется, но выход всегда равен 1

2. @Pouria — Я рекомендую использовать один из битов подсчета, полученных в приведенном выше коде, для прямоугольной волны. Для timer0 в одном из режимов вы получаете прямоугольную волну, в другом режиме вы просто получаете импульс, и это один из переходов, который соединен с выводом прерывания, управляемым краем, обычно используемым для тикера 18,2 Гц. Для чего вы инициализируете значение перезагрузки для счетчика?