Любая помощь приветствуется.
Таким образом, публикуя эту болтовню в качестве ответа, потому что раздел комментариев раздражает меня ограничением длины плюс форматированием, а ваш «вопрос» выше делает такой «ответ» законным.
Согласно 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).
person
Ped7g
schedule
27.08.2018
.db FillScreen & 0ffh, FillScreen >> 8 & 0ffh, FillScreen >> 16 & 0ffh, 00
(или у него нет какой-то директивы для определения 32 бита, как ожидалось бы.dd FillScreen
исходящий из мира x86) - на основе чтения PDF-документа «Настройка прерываний», стр. 13 (10 на бумаге), главы «Отображение местоположения ISR в таблице векторов прерываний». Также у вашего устройства действительно есть процессор eZ80F91? (только тот, у которого 16-битный регистрI
). - person Ped7g   schedule 27.08.2018.dl
для 3 байта LE (которую я тоже пробовал), но для 4 байт ничего не нашел. Согласно [wiki.tiplanet.org/TI-84_Plus_CE], процессор eZ80F91- нравится. - person Benjy Wiener   schedule 27.08.2018im 2
? (Кроме того, в сообщении упоминалось об удалении прерываний из цепочки инструментов CE, возможно, я пройдусь по ревизиям и попытаюсь увидеть, что именно было удалено, может быть полезно.) - person Benjy Wiener   schedule 28.08.2018res onInterrupt,(iy+onFlags)
, чтобы пользователь не получил ошибку Err: Break при выходе. - person Zeda   schedule 29.08.2018