interrupt
Различия
Показаны различия между двумя версиями страницы.
| Следующая версия | Предыдущая версия | ||
| interrupt [2026/10/15 20:30] – создано gecko | interrupt [2026/10/25 17:06] (текущий) – gecko | ||
|---|---|---|---|
| Строка 9: | Строка 9: | ||
| * SR (cop0r12) - статусный регистр; | * SR (cop0r12) - статусный регистр; | ||
| - | * Cause (cop0r13) - регистр причины прерывания. Предоставляет битовые флаги линий прерываний и код, идентифицирующий тип последнего прерывания. Регистр имеет 8 линий: 2 для исключений (биты 8–9) и 6 для аппаратных прерываний (биты 10-15). PlayStation использует только одну линию аппаратных прерываний (бит 10), все остальные всегда нулевые. | + | * Cause (cop0r13) - регистр причины прерывания. Предоставляет битовые флаги линий прерываний и код, идентифицирующий тип последнего прерывания. Регистр имеет 8 линий: 2 для исключений (биты 8-9) и 6 для аппаратных прерываний (биты 10-15). PlayStation использует только одну линию аппаратных прерываний (бит 10), все остальные всегда нулевые. |
| * EPC (cop0r14) - содержит адрес инструкции, | * EPC (cop0r14) - содержит адрес инструкции, | ||
| Строка 24: | Строка 24: | ||
| Перед загрузкой игры BIOS отключает обработку прерываний, | Перед загрузкой игры BIOS отключает обработку прерываний, | ||
| - | Функции BIOS, относящиеся к обработке прерываний: | + | BIOS создает четыре очереди обработчиков прерываний: |
| + | |||
| + | * 0 - Системные исключения - syscall, деление на ноль, переполнение памяти; | ||
| + | * 1 - Прерывания от системных таймеров и [[VBlank]]; | ||
| + | * 2 - Зарезервировано; | ||
| + | * 3 - Обработчики аппаратных прерываний периферии. | ||
| + | |||
| + | Перед вызовом очереди BIOS сохраняет все регистры общего назначения (GPR) в специальный буфер, так что самостоятельно это делать не нужно. | ||
| + | |||
| + | ===== Установка пользовательских обработчиков ===== | ||
| + | |||
| + | Обработчики прерываний добавляются функцией BIOS SysEnqIntRP и убираются функцией SysDeqIntRP. Обе функции принимают вторым аргументом указатель на следующую структуру: | ||
| + | |||
| + | <code c> | ||
| + | struct IntRP | ||
| + | { | ||
| + | struct IntRP* next; // следующий элемент IntRP в связном списке, | ||
| + | void* func2; // указатель на функцию, | ||
| + | void* func1; // указатель на функцию, | ||
| + | int flag; // зарезервированное значение, | ||
| + | }; | ||
| + | </ | ||
| + | |||
| + | Обработчик вызывается следующим образом: | ||
| + | * func2(func1()), | ||
| + | * func1(), если присутствует первая функция, | ||
| + | * В иных случаях ничего не вызывается. | ||
| + | |||
| + | Чтобы безопасно поместить элемент в очередь, | ||
| + | |||
| + | BIOS по цепочке вызывает все зарегистрированные обработчики прерываний. Каждый обработчик должен проверить нужный бит регистра I_STAT и подтвердить его, записав в него ноль. Например: | ||
| + | |||
| + | <code c> | ||
| + | int irqVBlank() | ||
| + | { | ||
| + | if ((*I_STAT & IRQ0) && (*I_MASK & IRQ0)) | ||
| + | { | ||
| + | // Reset VBlank bit | ||
| + | *I_STAT = ~IRQ0; | ||
| + | } | ||
| + | return 0; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Поскольку такой подход может привести к конфликтам, | ||
| + | |||
| + | ===== Функции BIOS, относящиеся к обработке прерываний | ||
| + | |||
| + | * С(02h) - SysEnqIntRP(priorityIndex, | ||
| + | |||
| + | * С(03h) - SysDeqIntRP(priorityIndex, | ||
| + | |||
| + | * B(18h) - ResetEntryInt() - удаляет все пользовательские обработчики. | ||
| * int EnterCriticalSection(), | * int EnterCriticalSection(), | ||
interrupt.1792096200.txt.gz · Последнее изменение: — gecko
