Установка прерывания на TI-84 Plus CE - PullRequest
0 голосов
/ 27 августа 2018

Я пытаюсь установить прерывание для перехвата нажатий кнопки ON.

Пока это мой код:

SetInterrupt:
 di
  ; copy the 4 bytes from InterruptVectorTable to cursorImage
  ; (I chose cursorImage because it's on a 512-byte boundary, 0E30800h)
 ld   hl, InterruptVectorTable
 ld   de, cursorImage
 ld   bc, 4
 ldir
  ; clone the same 4 bytes into the rest of the 256-byte interrupt vector table
 ld   hl, cursorImage
 ld   de, cursorImage + 4
 ld   bc, 252
 ldir
  ; load the address of the new interrupt vector in the i register
  ;  and set interrupt mode to 2
 ld   hl, cursorImage >> 8 & 0ffffh
 ld   i, hl
 im   2
 ei
 ret
FillScreen:
  ; fills the screen with black pixels
 ld a, 0
 ld hl, vRam
 ld bc, 320*240*2
 call _MemSet
 ret
InterruptVectorTable:
  ; try to call FillScreen whenever there's an interrupt
 .db 00, FillScreen & 0ffh, FillScreen >> 8 & 0ffh, FillScreen >> 16 & 0ffh

Однако это просто замораживает мой калькулятор (так какя не могу использовать какие-либо клавиши для остановки программы).

Я считаю, что проблема в InterruptVectorTable.Я не очень понимаю, как таблица должна быть отформатирована.Замечание по применению ez80, на которое я ссылаюсь ниже, гласит: «Каждый вектор - это 4-байтовый адрес, указывающий на сегмент __vectptr», но ez80 использует 24-битные адреса, поэтому я не уверен, как структурировать каждый вектор.

Любая помощь очень ценится.


Ссылки, которые я читал / пытался прочитать:

1 Ответ

0 голосов
/ 27 августа 2018

Любая помощь очень ценится.

Таким образом, публикация этого чата в качестве ответа, потому что раздел комментариев раздражает меня ограничением длины плюс форматирование, и ваш "вопрос" выше делаетэтот тип «ответа» является законным.

Согласно 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).

...