Просмотр полной версии : Z80 PIO не генерирует прерывание
fromzero2infinity
16.08.2021, 01:52
Всем здраствуте.
Вот изобретаю спой велосипед с нуля для разминки мозга.
Столкнулся с проблемой при подключении PS/2 клавы.
Перепробовал все... 2 недели шаманю, а воз и ныне там. Хоть бросай все.
Вот сама схемка (неммного упрощенная). ~STB даю кнопкой а не с HC595 как в оригинале... Что б избежать конфлита LS и HC серии. Все на LS.
https://zx-pk.ru/attachment.php?attachmentid=75966&d=1629067257
Вот что на осцилографе (желтый - ~STB строб, красный - ~INT)
https://zx-pk.ru/attachment.php?attachmentid=75967&d=1629067267
Для уверенности в самом начале гружу в А 55H, что и видно на порту А.
https://zx-pk.ru/attachment.php?attachmentid=75968&d=1629067273
Вот собственно ПЗУ прошито этим.
0001 0000 ; Test #08
0002 0000 ; Test PIO interrupt on port B
0003 0000
0004 0000 PORTA .equ 80h ; port A data
0005 0000 CNTRLA .equ 81h ; port A control
0006 0000 PORTB .equ 82h ; port B data
0007 0000 CNTRLB .equ 83h ; port B control
0008 0000
0009 0000 .org 0h ; RESET
0010 0000 31 F0 FF ld sp, 0fff0h
0011 0003
0012 0003 ED 5E im 2 ; cpu interrupt mode 2 (vectored)
0013 0005 3E 00 ld a, 0h
0014 0007 ED 47 ld i, a
0015 0009
0016 0009 3E 0F ld a, 0fh ; output
0017 000B D3 81 out (CNTRLA), a
0018 000D
0019 000D 3E 4F ld a, 4fh ; input
0020 000F D3 83 out (CNTRLB), a
0021 0011
0022 0011 3E 28 ld a, 28h ; vector address
0023 0013 D3 83 out (CNTRLB), a
0024 0015
0025 0015 3E 87 ld a, 10000111b ; 87h, 83h - enable interrupts 10000111b
0026 0017 D3 83 out (CNTRLB), a
0027 0019
0028 0019 3E 55 ld a, 55h
0029 001B 21 00 80 ld hl, 8000h
0030 001E 77 ld (hl), a
0031 001F
0032 001F FB ei
0033 0020
0034 0020 7E MAIN: ld a, (hl)
0035 0021 D3 80 out (PORTA), a
0036 0023 C3 20 00 jp MAIN
0037 0026
0038 0026
0039 0028 .org 28h
0040 0028 08 ex af, af' ; save A, FLAGS
0041 0029 7E ld a, (hl)
0042 002A 3C inc a
0043 002B 77 ld (hl), a
0044 002C 08 ex af, af' ; restore A, FLAGS
0045 002D FB ei
0046 002E ED 4D reti
0047 0030
0048 0030 .END
Схему саму прозвонил раз 20, все правильно (соответствует задуманной).... Код тоже перепробовал разный... 87h, 83h для включения прерываний.
По адресам тоже вроде, как видно в .lst файле.
Если написать без прерываний, просто выдавать входной порт на выходной - работает.
Посмотрите свежим глазом, может я какого-нить костыля не вижу... глаз замылился?
fromzero2infinity, по адресу 0x38 попробуй воткнуть обработчик прерываний либо используй свой вектор, но в IM2 режиме.
Serg6845
16.08.2021, 11:18
0039 0028 .org 28h
0040 0028 08 ex af, af' ; save A, FLAGS
0041 0029 7E ld a, (hl)
0042 002A 3C inc a
0043 002B 77 ld (hl), a
0044 002C 08 ex af, af' ; restore A, FLAGS
0045 002D FB ei
0046 002E ED 4D reti
0047 0030
0048 0030 .END
Посмотрите свежим глазом, может я какого-нить костыля не вижу... глаз замылился?
картинки не видно - грузится gif 1x1 pixel
ну и в IM2 Z80 не переходит по адресу вектора, а берет по этому адресу 16-битный адрес перехода, по которому уже идет дальше. то есть при такой прошивке улетит на адрес 0x7e08.
берет по этому адресу 16-битный адрес перехода
там немного не так. мы привыкли, что на Спектруме, когда задаём таблицу векторов для im2, то мы задаём как правило только старшую часть адреса. Для Z80PIO, когда мы указываем контроллеру адрес вектора для прерываний, мы указываем младшую часть. Таким образом, для примера, мы установили вектор на адрес #a000 (условно, конечно, адрес будет выглядеть как #a0a0), а для PIO адрес #10, то при приходе прерываний будет обращение по адресу #a010. Проц возьмёт от туда 2 байта и выполнит туда jp.в итоге может быть так, что экранные прерывания прилетают на im2 вектор, который мы указали процу, а прерывания от PIO прилетают по другому вектору, но в диапазоне 256.
т.е. в данном примере:
im 2 ; cpu interrupt mode 2 (vectored)
ld a, 0h
ld i, a
ld a, 0fh ; output
out (CNTRLA), a
ld a, 4fh ; input
out (CNTRLB), a
ld a, 28h ; vector address
out (CNTRLB), a
будет вектор по адресу #0028, что в примере и указано, но в примере по этому адресу должны лежать 2 байта, что то вроде
.org 28h
dw procedure_addr
проц берёт этот адрес и делает jp
fromzero2infinity
16.08.2021, 20:54
Cпасибо за ответы. Проблеск надежды появился.
При програмировании четко следовал этому - https://zilog.com/docs/z80/UM0080.pdf
стр. 34
В hex файле вот это:
:2000000031F0FFED5E3E00ED473E0FD3813E4FD3833E28D38 33E87D3833E5521008077FB02
:110020007ED380C320000000087E3C7708FBED4D00A5
:00000001FF
Первая инструкция обработчика - ex af, af' ; save A, FLAGS (08h) - по адреcу 0028H. При RESET адрес таблицы в I сбрасывается в 0H, но я дле перестраховки явно туда 0h положил.
Смущает пока что при всем при том, я не вижу прерывания по восходящему фронту ~BSTB, что по документации должно происходить. По негативному фронту - латч в порт, по восходящему - ~INT для процессора.
Вот осцилограмма - https://zx-pk.ru/attachment.php?attachmentid=75967&d=1629067267
Я допустил бы, что неисправен PIO, но не 5 из имеющихся, что я опробовал.
Конечно, можно запилить на avr8 входной порт, но это уже отход от РЕТРО компьютера :)
Serg6845
17.08.2021, 10:04
Cпасибо за ответы. Проблеск надежды появился.
При програмировании четко следовал этому - https://zilog.com/docs/z80/UM0080.pdf
стр. 34
ну там все правильно написано. только понято неправильно...
вот другими словами то же самое:
https://zilog.com/docs/z80/UM0081.pdf
стр. 199
Первая инструкция обработчика - ex af, af' ; save A, FLAGS (08h) - по адреcу 0028H.
а должна быть не по адресу 0028H, а по адресу, равному слову, лежащему по адресу 0028H. примерно так:
.org 0028
dw isr_start
...
isr_start: ex af,af'
...
Смущает пока что при всем при том, я не вижу прерывания по восходящему фронту ~BSTB, что по документации должно происходить. По негативному фронту - латч в порт, по восходящему - ~INT для процессора.
Вот осцилограмма - https://zx-pk.ru/attachment.php?attachmentid=75967&d=1629067267
а со схемой все нормально? картинки не открываются (4 разных ОС, разные браузеры)
в частности вход IEI куда зацеплен?
fromzero2infinity
18.08.2021, 06:45
Вот жеж... И впрямь на стр. 199 по PIO разговор про ТАБЛИЦУ. Но... редкая птица долетит до 199 страницы мануала :) СПАСИБО, что подняли мне веки :)
Это огромный прогресс по выходу из тупика.
Переписал на вот такое:
.org 0h ; RESET
ld sp, 0fff0h
im 2 ; cpu interrupt mode 2 (vectored)
ld a, 0h
ld i, a
ld a, 0fh ; output
out (CNTRLA), a
ld a, 4fh ; input
out (CNTRLB), a
ld a, 40h ; vector address
out (CNTRLB), a
ld a, 10000111b ; 87h, 83h - enable interrupts 10000111b
out (CNTRLB), a
ld a, 55h
ld hl, 8000h
ld (hl), a
ei
MAIN: ld a, (hl)
out (PORTA), a
jp MAIN
.org 28h
ex af, af' ; save A, FLAGS
ld a, (hl)
inc a
ld (hl), a
ex af, af' ; restore A, FLAGS
ei
reti
.org 40h
INTTBL: .WORD 0028h
Пока результат тот же... не пашет... IEI зацеплен на +5В.
https://zx-pk.ru/attachment.php?attachmentid=75972&d=1629257943
https://zx-pk.ru/attachment.php?attachmentid=75974&d=1629259330
Красный - ~INT идет на ~INT CPU (пин16) подтянутый 1КОм на питание, желтый - ~BSTB
ld a, 40h ; vector address
ld a, 10000111b ; 87h, 83h - enable interrupts 10000111b
поменяй эти 2 строчки местами. надо сначала включить прерывание, а потом уже вектор кидать, а ты наоборот сделал, кинул вектор при выключенных прерываниях.
fromzero2infinity
18.08.2021, 19:31
Поменял.... пока так же....
Пока поэтапно тестировал сигналы, обнаружил, что клава шлет селф-тест последовательности при подаче питания. Присмотрелся - да.. вроде ~INT по ~STB + фронту... Какой-то короткий, но все же получается есть. Масштаб = 10uS, значит ~INT примерно 2 uS.
Генерится только при первом ~STB, потом хоть выспись - жми 100 раз - ничего на ~INT.
Что,похоже свидетельствует о програмной ошибке.
https://zx-pk.ru/attachment.php?attachmentid=75977&d=1629305309
fromzero2infinity,
ну можно слегка поэксперементировать...
org 0h ; RESET
ld sp,0fff0h
im 1 ; cpu interrupt mode 1 (vectored)
ld a,0x30 ;error reset, select WR0
out (CNTRLA),a
ld a,0x18 ;channel reset
out (CNTRLA),a
ld a,0
out (CNTRLA),a
ld a,0x38
out (CNTRLA),a
ld a,1 ;select WR1
out (CNTRLA),a
ld a,0 ;no INT`s on CH_A
out (CNTRLA),a
ld a,3 ;select WR3
out (CNTRLA),a
ld a,0xc1 ;RX 8 bit`s, RX enabled
out (CNTRLA),a
ld a,4 ;select reg4
out (CNTRLA),a
ld a,7 ;Parity enabled, parity odd (?), 1 stop bit
out (CNTRLA),a
ld a,5 ;select reg5
out (CNTRLA),a
ld a,0x60 ;TX 8 bit/Character
out (CNTRLA),a
ld a,55h
ld hl,8000h
ld (hl),a
ei
MAIN: ld a,(hl)
out (PORTA),a
jp MAIN
ds 38h-$ ;вместо org
ISR0: push af
in a,(CNTRLA)
bit 0,a
jr z,_exit_isr
in a,(SIO_DATA_A) ;получить данные от клавы
_exit_isr: ld (hl),a
pop af
ret
прерывания обычные, прилетают на 38h. на каждом прерывании чтение статуса клавы. если бит0 есть, значит есть данные. протести этот вариант, что там будет...
Serg6845
19.08.2021, 10:06
Поменял.... пока так же....
логично. в доке нигде не сказано что вектор надо писать при включенных прерываниях, да и здравый слысл подсказывает что разрешать прерывания при неустановленном векторе - как-то неправильно.
Пока поэтапно тестировал сигналы, обнаружил, что клава шлет селф-тест последовательности при подаче питания. Присмотрелся - да.. вроде ~INT по ~STB + фронту... Какой-то короткий, но все же получается есть. Масштаб = 10uS, значит ~INT примерно 2 uS.
~INT снимается по подтверждению прерывания процессором, длительность зависит в т.ч. от тактовой частоты. с виду нормально.
Генерится только при первом ~STB, потом хоть выспись - жми 100 раз - ничего на ~INT.
а вот это похоже на то что PIO зависает в состоянии "under service" - то есть "мое прерывание обрабатывают но еще не обработали". выход из этого состояния - по команде RETI на шине данных.
можно засинхронизироваться от ~INT и посмотреть что на IEO происходит.
Что,похоже свидетельствует о програмной ошибке.
а возможно и нет. CLK куда зацеплен? если отличается от CLK процессора - возможны нюансы. а еще возможно влияют длинные провода на которых все собрано или контакт где-то не очень...
https://zx-pk.ru/attachment.php?attachmentid=75968&d=1629067273
fromzero2infinity
20.08.2021, 18:13
Кажется я где-то близко, Вашими молитвами.
Поюнул на все, разобрал.
Собрал свои портики. Выходной и взодной. Выходной ничего интересного, а вот входной, где по кнопочке генерится INT. Немного мудрено, но это что б микросхемок поменьше.
https://zx-pk.ru/attachment.php?attachmentid=75987&d=1629471396
Написал тестик, где использую mod1.
; Test #05
; Test interrupt in Mode 1
PORTOUT .equ 0Fh
.org 0h ; RESET
ld sp, 0fff0h
im 1
ld a, 55h
ld hl, 8000h
ld (hl), a
ei
MAIN: ld a, (hl)
out (PORTOUT), a
jp MAIN
.org 38h
ex af, af' ; save A, FLAGS
ld a, (hl)
inc a
ld (hl), a
ex af, af' ; restore A, FLAGS
ei
ret
.END
Работает как часы... Увеличивает (HL) и отображает на выходном порту.
Цепляю к этому портику вектор (RST4).
Чутка меняю тестик.
im0 и .org 20h на обработчик..... Включаю - НЕ работает. ~INT есть, ~INTAck есть... а не работает. 55h висит на выходе и все.
И тут приходит мысль - до проца не дожодит вектор прерывания. Ну логично, если без вектора в режиме 1 работает,я тут нет.
Открываю UM0080.pdf и вижу
https://zx-pk.ru/attachment.php?attachmentid=75988&d=1629471610
~RD не уходит на низкий уровень.
А у меня на шине данных вот такой гейт стоит....
https://zx-pk.ru/attachment.php?attachmentid=75989&d=1629471615
Т.е. при ~RD = 1 он включен A->B, на шину, а не на CPU.
Вот и нету вектора к процессору.
Похоже так. Все остальное при этом b стек и субрутины работают, что дало мне чувство в правильности дизайна самой моверборд...
Пожалуйста, подтвердите ход моих мыслей или ткните где не прав. Если есть готовое решения на управление буфером шины данных - киньтесь им в меня пожалуйста.
По моему разумению надо (~RD AND ~INTack) использовать. Но может еще какие случаи есть о которых я не знаю пока. Так сказать, что б позже опять не получить такую штангу.
Пока буду думать как пилить дорожки и паяться проводками к материнке, что б проверить.
Serg6845
21.08.2021, 09:16
Кажется я где-то близко, Вашими молитвами.
Поюнул на все, разобрал.
Написал тестик, где использую mod1.
Работает как часы... Увеличивает (HL) и отображает на выходном порту.
Цепляю к этому портику вектор (RST4).
Чутка меняю тестик.
im0 и .org 20h на обработчик..... Включаю - НЕ работает. ~INT есть, ~INTAck есть... а не работает. 55h висит на выходе и все.
И тут приходит мысль - до проца не дожодит вектор прерывания. Ну логично, если без вектора в режиме 1 работает,я тут нет.
Открываю UM0080.pdf и вижу
~RD не уходит на низкий уровень.
А у меня на шине данных вот такой гейт стоит....
https://zx-pk.ru/attachment.php?attachmentid=75989&d=1629471615
Т.е. при ~RD = 1 он включен A->B, на шину, а не на CPU.
Вот и нету вектора к процессору.
Похоже так.
Семен Семеныч!
в исходной схеме буфер не показан был. естественно так работать не будет.
Все остальное при этом b стек и субрутины работают, что дало мне чувство в правильности дизайна самой моверборд...
ну они-то работают по нормальным ~RD, ~WR, обработка прерываний - особый случай.
Пожалуйста, подтвердите ход моих мыслей или ткните где не прав. Если есть готовое решения на управление буфером шины данных - киньтесь им в меня пожалуйста.
По моему разумению надо (~RD AND ~INTack) использовать.
правильно.
Но может еще какие случаи есть о которых я не знаю пока. Так сказать, что б позже опять не получить такую штангу.
сходу не припомню, разве что ~BUSRQ когда-нибудь будет задействован...
fromzero2infinity
23.08.2021, 16:35
Теперь c моими портами все работает. RST отрабатывает, обработчик считает, на out порту все отображается.
https://zx-pk.ru/attachment.php?attachmentid=76002&d=1629725305
Буду переделывать материнку, подключать PIO и обратно на im2. Думаю, что проблем не возникнет.
Поучительно...
Еще можно ~BUSACK прицепить на ~СE, но пока до DMA очень далеко... пусть так пока будет.
Друзья, Serg6845 и Sayman спасибо Вам от всего сердца.
Мало того, что железную проблему решили, так еще и спасли меня от еще одного месяца(ев) взрывания мозга с неправильно понятым мною Mode2 и таблице прерываний.
Powered by vBulletin® Version 4.2.5 Copyright © 2026 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot