Любая помощь очень ценится.
Таким образом, публикация этого чата в качестве ответа, потому что раздел комментариев раздражает меня ограничением длины плюс форматирование, и ваш "вопрос" выше делаетэтот тип «ответа» является законным.
Согласно PDF-документу «Установка прерываний», на стр. 13 32-битный формат адреса прост, в случае адреса 0x123456 память должна содержать байты 56 34 12 00
(не уверен, что последний 00
может быть любым мусором или должен быть нулем, я думаю, что для будущей совместимости ноль лучше, хотя я предполагаю, что eZ80F91 будет использовать только 24 бита, игнорируя последние 8).
Так что определение в вашем исходном вопросе, скорее всего, неверно, 00
должно быть после 3 байтов, а не впереди.
Трехбайтового .dl
должно быть достаточно с дополнительными дополнительныминежелательный байт тоже .db
(чтобы избежать разложения меток вручную на байты).
Я знаком только с классическим Z80, поэтому не имею точного представления о том, что не так с вашим кодом, но общие принципыи вещи, которые, вероятно, стоит проверить:
проверить, действительно ли устройство имеет eZ80F91 ("-подобный" ??? кто еще производит какой-то его клон? Я думаю, это либо оригинальноиз Zilog или нет, «подобный» вариант невозможен), поскольку любой другой вариант eZ80 имеет только 8-битный регистр I
и требует другой настройки таблицы прерываний и обработки прерываний (возможно, попробуйте ld hl,0x1234
ld i,hl
ld hl,0
ld hl,i
и проверьте значение в hl
, если оно вернулось к 0x1234
).
проверьте созданный двоичный файл или в отладчике, пока код инициализирует таблицу векторов, чтобы памятьсодержит ожидаемые значения
проверьте описание устройства (если доступно), какие прерывания срабатывают и когда, почему вы действительно ожидаете, что кнопка «вкл» вызовет прерывание?(например, ZX Spectrum - машина Z80, с которой я знаком - не имеет прерывания клавиатуры, клавиатура должна опрашиваться кодом, единственное прерывание сработало при запуске вертикального обратного хода луча дисплея, то есть на частоте ~ 50 Гц с PAL / SECAMМодели ZX и примерно ~ 60 Гц с американскими вариантами NTSC, что заставляет игры работать чуть быстрее на американских клонах ZX ... IIRC Калькуляторы TI имеют прерывание по таймеру, как 100 Гц, но я никогда не изучал их подробно, так что это можетбыть абсолютно неверной информацией)
убедитесь, что вы находитесь в режиме "ADL", а не в режиме совместимости "Z80".
ваш "FillScreen«подпрограмма пытается вернуться, но, похоже, у нее нет правильного пролога / эпилога, подобного прерыванию, поэтому, куда бы она ни вернулась, она повредила содержимое регистров и не возвращается через reti
.
вы также возвращаетесь из подпрограммы SetInterrupt
во что-то ... что выполняется между тем, пока установлено ваше прерывание?
Сначала вы можете попробовать«эйЧтобы обработать прерывание, например
FillScreen:
ei ; not sure if there's implicit DI - if yes, EI needed
reti
, можно проверить, работает ли код, выполняемый в основном потоке (и работает ли ваш обработчик прерываний).Имейте в виду, если это обычный обработчик калькулятора, и для его работы требуется собственный обработчик прерываний, то просто установка пустого прерывания уже подорвет функциональность ... возможно, вам никогда не следует возвращаться из своего кода (основной поток,например, где вызывается setInterrupt) и выполняйте свой собственный бесконечный основной цикл).
Если вы хотите сделать больше в своем прерывании, вы должны сохранить значения регистров для кода в основном потоке, например, если вы знаетеосновной поток НЕ использует альтернативные регистры, тогда вы можете быстро переключать регистры с помощью
interruptHandler:
di ; disable interrupts until done
; (especially if you know your interrupt may take longer to run)
; preserve current register values (by switching to alternate ones)
ex af,af
exx
; do your stuff here (destroying alternate register values)
; which is OK, if your interrupt handler is the only code using them
...
; restore the register values back (by switching to original ones)
exx
ex af,af
; return from interrupt
ei
reti
или, если вы знаете, что в стеке всегда достаточно места, вы используете push/pop
для сохранения исходных значений регистров.
Или, если пространство стека может быть слишком напряженным, но у вас есть отдельный блок памяти, который можно использовать в качестве стека обработчика прерываний, вы можете сначала переключиться на него:
interruptHandler:
di
; preserve current stack pointer (self-modify code)
ld (interruptHandler_SP+1),sp
ld sp,top_of_interrupt_stack
; preserve registers as needed (AF with flags being a MUST)
push ...
; do your stuff here
...
; restore registers as needed
pop ...
; restore stack pointer
interruptHandler_SP:
ld sp,0x123456 ; this will be overwritten at start of handler
; return from interrupt
ei
reti
Если подумать, ваш обработчик прерываний, очевидно, не является обработчиком прерываний, поэтому, даже если он будет работать один раз правильно, это будет последней правильной вещью, происходящей на вашем устройстве.
Также заполнение экрана немногонеудачный выбор (так как это займет много времени, и его трудно увидеть дважды).
Возможно, в качестве быстрого теста сделайте что-то вроде:
testInterrupt:
di
push af
; increment first byte of video ram to make some visible "noise"
ld a,(vRam)
inc a
ld (vRam),a
; restore flags, enable interrupts, return back to main code
pop af
ei
reti
И обычно обработчики прерываний должныбыть очень быстрым и крошечным, выполнение задачи, такой как очистка vram, должно быть оставлено основному коду, прерывание, вероятно, должно просто установить некоторый глобальный флаг, что очистка vram требуется (чтобы завершиться в течение нескольких T циклов), и тогда основной код может в циклепроверить наличие различных флагов событий и отреагировать на флаг "clear vram", очистив vram.В обработчиках не должно быть какой-либо серьезной «бизнес-логики», а только сбор состояния / данных, которые неизбежны (например, данные по вводу-выводу последовательной шины), в некоторые флаги / буферы и возможность обработки основного кода вне прерывания.такие флаги / буферы с полной логикой.
Возможно, даже стоит попробовать сначала какой-нибудь классический Z80, если вы действительно не хотите eZ80F91 сильно.У классического Z80 есть тонна доступных материалов, с различными машинами и эмуляторами, так как это был очень популярный процессор (например, я своего рода «эксперт» Z80, благодаря компьютеру ZX Spectrum, я написал несколько демо-версий и игр для него в прошлом).1991-1996 годы).Так что с этим будет легче справиться (кажется, этот вопрос оставался без ответа достаточно долго, чтобы догадаться, что не так уж много людей пишут код для eZ80F91).