Files
APS/Lectures/14. Interrupt subsystem.md
tyrty23 e5370ffcc8 КЛ3, 14, 15. Хотфиксы
* Add corrected figure

* Update 03. Digital arithmetics.md

* Add corrected figure

* Update 03. Digital arithmetics.md

* Delete .pic/Lectures/03. Digital arithmetics/fig_08.png

* Add files via upload

* Update 15. Memory.md

Исправление синтаксических ошибок в 15 лекции

* Update 15. Memory.md

* Update 14. Interrupt subsystem.md

исправление опечатки в названии файла

* Update Lectures/03. Digital arithmetics.md

Co-authored-by: Andrei Solodovnikov <VoultBoy@yandex.ru>

* Update Lectures/03. Digital arithmetics.md

Co-authored-by: Andrei Solodovnikov <VoultBoy@yandex.ru>

* Delete .pic/Lectures/03. Digital arithmetics/fig_07.png

* Rename fig_08.png to fig_07.png

* Delete .pic/Lectures/03. Digital arithmetics/fig_07.png

* Add files via upload

---------

Co-authored-by: Andrei Solodovnikov <VoultBoy@yandex.ru>
2024-01-14 13:31:37 +03:00

275 lines
28 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Лекция 14. Подсистема прерывания
## Содержание
- [Лекция 14. Подсистема прерывания](#лекция-14-подсистема-прерывания)
- [Содержание](#содержание)
- [Определение](#определение)
- [Сканирование-входов](#сканирование-входов)
- [Передача управления при прерывании](#передача-управления-при-прерывании)
- [Классификация событий прерывания](#классификация-событий-прерывания)
- [Основные характеристики прерываний](#основные-характеристики-прерываний)
- [Допустимые моменты прерывания программы](#допустимые-моменты-прерывания-программы)
- [Маски́рование прерывания](#маски́рование-прерывания)
- [Способы выявления прерывания](#способы-выявления-прерывания)
- [Схемы реализации контроллера прерываний](#схемы-реализации-контроллера-прерываний)
- [Контроллер прерывания](#контроллер-прерывания)
- [Control and Status Register RISC-V](#control-and-status-register-risc-v)
- [Подсистема прерываний для RISC-V](#подсистема-прерываний-для-risc-v)
- [Программа, реализующая прерывания на ассемблере](#программа-реализующая-прерывания-на-ассемблере)
- [Основные материалы лекции](#основные-материалы-лекции)
- [Дополнительные материалы к лекции для саморазвития](#дополнительные-материалы-к-лекции-для-саморазвития)
## Определение
**Прерывание** — событие, на которое реагирует процессор.
ример_: Перемещение мыши. Если бы не было прерываний, то процессор был бы вынужден постоянно обращаться к мыши с целью узнать: изменилось ли её положение или нет, стоит ли перерисовать курсор. А это очень ресурсоёмко. Такой подход называется [сканирование входов](#сканирование-входов).
### Сканирование-входов
**Сканирование входов** — последовательный программный опрос входных сигналов. Этот подход используется в суперкомпьютерах, т.к. у них неразвитая периферия. В таком случае подсистема прерываний не нужна.
## Передача управления при прерывании
В случае, если во время выполнения программы произошло событие прерывания, процессор останавливает выполнение основной программы и начинает выполнять подпрограмму обработки прерывания. Завершив обработку прерывания, процессор возвращается к исполнению основной программы.
![../.pic/Lectures/14.%20Interrupt%20subsystem/fig_01.jpg](../.pic/Lectures/14.%20Interrupt%20subsystem/fig_01.jpg)
*Рис. 1. Схема передачи управления при прерывании.*
## Классификация событий прерывания
- **Прерывания** — события, сигнал о которых приходит извне. Это события происходит _асинхронно_ фронту тактового импульса. Пример: перемещение мыши.
- Маски́руемые — прерывания, которые процессор может игнорировать. _Например_: нажатие клавиши на клавиатуре. [Аппаратная реализация]( #маски́рование-прерывания) будет продемонстрирована чуть позже.
- Немаски́руемые — прерывания, которые процессор не может игнорировать. _Например_: сигнал от датчика температуры о перегреве процессора.
- **Исключения** — события, происходящие вследствие выполнения какой-то инструкции. Эти события происходят _синхронно_ фронту тактового импульса.
- Ошибки. _Например_: обращение в несуществующую область памяти.
- Ловушки. _Например_: деление на 0.
- Отказы. _Например_: ситуации, которые никак нельзя устранить. Зачастую приводят к выключению/перезапуску процессора.
## Основные характеристики прерываний
- **Время реакции прерывания**, T<sub>реакции</sub>
Это время, между запросом на прерывание и переходом к прерывающей программе (см. рис. 2)
- **Затраты времени на переключение программ**, T<sub>загрузки</sub> и T<sub>востановления</sub>
Это время, которое требуется программе выполнить сервисные инструкции (см. рис. 2). Например: узнать причину прерывания, сохранить данные на стек прерывания и др.
- **Эффективность прерывания**
Это время эффективной работы программы. Т.е. отношение "полезных" (не сервисных) инструкций программы прерывания ко всем инструкциям прерывания.
![../.pic/Lectures/14.%20Interrupt%20subsystem/fig_02.jpg](../.pic/Lectures/14.%20Interrupt%20subsystem/fig_02.jpg)
*Рис. 2. Характеристики прерывания.*
- **Глубина прерывания**
Это кол-во прерываний, которые могут произойти во время обработки прерывания (см. рис. 3). Например: если процессор, находясь внутри прерывания, не способен прерваться на другое, то говорят что глубина прерывания n=1. Также программы могут неограниченно прерывать друг друга, в таком случаем, есть ограничение по памяти.
![../.pic/Lectures/14.%20Interrupt%20subsystem/fig_03.jpg](../.pic/Lectures/14.%20Interrupt%20subsystem/fig_03.jpg)
*Рис. 3. Глубина прерываний.*
## Допустимые моменты прерывания программы
В зависимости от архитектуры процессора могут быть использованы различные методы, определяющие когда прерывание становится возможным:
- **Метод помеченного оператора**
Внутри какой-нибудь инструкции добавляется бит, отвечающий за прерывание. Допустим, если этот бит равен 1 и есть сигнал на прерывание, то процессор запустит обработчик прерывания.
- **Покомандный метод**
Этот метод относится к [многотактным архитектурам](09.%20Multicycle%20processor.md). Процессор начинает реагировать на сигнал прерывания, только после завершения инструкции.
- **Метод быстрого реагирования**
Этот метод позволяет реагировать на прерывание на любом такте.
### Маски́рование прерывания
**Маска прерывания** — это регистр, отвечающий за разрешение на прерывание (см. рис. 4). Эта маска побитово перемножается с запросами на прерывание других устройств/модулей. Если в результате перемножения получилась хотя бы одна 1, то формируется сигнал `interrupt`, который подаётся на блок управления процессора.
![../.pic/Lectures/14.%20Interrupt%20subsystem/fig_04.jpg](../.pic/Lectures/14.%20Interrupt%20subsystem/fig_04.jpg)
*Рис. 4. Аппаратная реализация маски́рования прерывания.*
## Способы выявления прерывания
- **Обзорная система прерывания**
Каждый запрос на прерывание запускает одну и ту же подпрограмму, которая определяет, кто отправил запрос, а затем запускает конкретную программу обработчика прерывания. Работает такая система сравнительно дольше, но реализация её проще.
- **Векторная система прерывания**
В векторной системе есть участок памяти — аблица векторов прерывания_. В таблице лежат **вектора прерывания** — адрес начала подпрограммы обработчика прерывания. После обращения к таблице будет запущена нужная подпрограмма. Работает такая система быстрее, но реализовать её сложнее.
## Схемы реализации контроллера прерываний
[**Контроллер прерывания**](#контроллер-прерывания) — устройство, которое отвечает за передачу сигнала прерывания процессору и формирование кода причины прерывания.
- **Цепочечная схема**
От процессора идет сигнал подтверждения `ПДТ`, который приходит только тогда, когда процессор готов обработать какое-то прерывание (см. рис. 5.). Этот сигнал приходит на вход первого устройства, которое, в случае необходимости, выдаёт процессору сигнал на прерывание и вектор прерывания. Если же в прерывании от первого устройства нет необходимости, то сигнал подтверждения передаётся на следующее устройство и т.д. Цепочечная схема проста в реализации, но очень медленная. К тому же в этой схеме некоторые устройства имеют приоритет на другими в очерёдности обработки запроса на прерывание. Также существует вероятность, что до последних устройств никогда не дойдёт сигнал подтверждения, и процессор не обработает их запрос на прерывание.
![../.pic/Lectures/14.%20Interrupt%20subsystem/fig_05.jpg](../.pic/Lectures/14.%20Interrupt%20subsystem/fig_05.jpg)
*Рис. 5. Цепочечная схема.*
- **Схема с циклическим опросом**
Каждый раз, когда в счётчик `СТ` приходит сигнал `C` (тактирование), он увеличивает своё значение (см рис. 6). Затем это значение подаётся на вход дешифратору `DC`, который только на одном выходе выдаёт 1. И каждый такт меняется номер выхода от 0 до N. Если во время обхода всех выходов появится сигнал на прерывание, то этот сигнал отправится на RS триггер, который затем отправит `interrupt` сигнал процессору. А на вход `C` счётчика `CT` будет отправлен 0. В таком случае счётчик перестанет суммировать, и он будет иметь значение кода номера прерывания.
![../.pic/Lectures/14.%20Interrupt%20subsystem/fig_06.jpg](../.pic/Lectures/14.%20Interrupt%20subsystem/fig_06.jpg)
*Рис. 6. Циклическая схема.*
- **Дейзи-цепочка**
Рассмотрим дейзи-цепочку (см. рисунок 7). Эта схема будет работать только тогда, когда вход `Приоритет` равен 1. Если на первый запрос пришла 1, то на соответствующий выход y<sub>1</sub> будет подана 1, которая будет говорить о том, что именно первое устройство сделало запрос на прерывание. На выход `INT` также будет передана 1, которая отправится процессору для оповещения о прерывании. На остальные же выходы y<sub>2</sub>...y<sub>n</sub> будет передан 0. Т.е. на выходе y<sub>1</sub>...y<sub>n</sub> будет получена только одна 1 от запроса с наивысшим приоритетом. Дейзи-цепочка часто используется в определении наиболее приоритетного запроса.
![../.pic/Lectures/14.%20Interrupt%20subsystem/fig_07.jpg](../.pic/Lectures/14.%20Interrupt%20subsystem/fig_07.jpg)
*Рис. 7. Дейзи-цепочка.*
### Контроллер прерывания
Теперь рассмотрим, как выглядит контроллер прерывания. (см. рис. 8) По каналу `ПДТ` поступает сигнал от процессора, разрешающий прерывание. Этот сигнал поступает на регистры запроса прерывания. Затем с помощью [маски прерывания](#маски́рование-прерывания) определяются, каким устройствам разрешён запрос на прерывание. Сигналы на прерывания попадают в `схему определения наиболее приоритетного запроса` (_например_: дейзи-цепочка), где определяется самый приоритетный запрос. С помощью `формирователя номера запроса` формируется некоторое число, отвечающее за степень приоритета запроса. В `схеме сравнения приоритетов` сравнивается это число с приоритетом текущего прерывания (приоритет текущего прерывания записан в регистры `порога прерывания`). Если число, хранимое в регистрах "_порога прерывания_" меньше, то в `порог прерывания` записывается новое число, а на процессор по каналу `ЗП` пойдёт сигнал о новом прерывании.
![../.pic/Lectures/14.%20Interrupt%20subsystem/fig_08.jpg](../.pic/Lectures/14.%20Interrupt%20subsystem/fig_08.jpg)
*Рис. 8. Схема контроллера прерывания.*
## Control and Status Register RISC-V
Это набор регистров, связанных с блоками процессора, с помощью которых можно управлять ими или узнавать информацию о них.
Минимальный набор для поддержания прерывания в RISC-V нужно реализовать следующие регистры:
| Номер | Привилегия | Имя | Описание |
|:------------|:-----------|:----------|:-----------------------------------------------------------|
| Ox304 | MRW | mie | Регистр маски |
| Ox305 | MRW | mtvec | Регистр вектора прерывания |
| Ox340 | MRW | mscratch | Регистр указателя на стек прерывания |
| Ox341 | MRW | mepc | Регистр адреса инструкции, на котором случилось прерывание |
| Ox342 | MRW | mcause | Регистр причины (кода) прерывания |
Инструкции для работы с CSR:
| Opcode | func3 | Тип | Инструкция | Описание | Операция |
|:----------|:------|:-----|:--------------------|:--------------------------|:------------------------|
| 1110011 | 000 | I | mret | Возврат и прерывание | PC=merc |
| 1110011 | 001 | I | csrrw rd, csr, rs1 | Чтение/запись CSR | rd = csr, csr=rs1 |
| 1110011 | 010 | I | csrrs rd, csr, rs1 | Чтение/установка бит CSR | rd = csr, csr=rs1\|rs1 |
| 1110011 | 011 | I | csrrc rd, csr, rs1 | Чтение/очистка бит CSR | rd=csr, csr=csr&~rs1 |
## Подсистема прерываний для RISC-V
![../.pic/Lectures/14.%20Interrupt%20subsystem/fig_09.jpg](../.pic/Lectures/14.%20Interrupt%20subsystem/fig_09.jpg)
*Рис. 9. Микроархитектура RISC-V с CSR.*
Теперь рассмотрим отдельно блок CSR:
![../.pic/Lectures/14.%20Interrupt%20subsystem/fig_10.jpg](../.pic/Lectures/14.%20Interrupt%20subsystem/fig_10.jpg)
*Рис. 10. Схема CSR.*
Рассмотрим схему CSR (см. рис. 10). На ней красным прямоугольником (номер 1) отмечены регистры CSR. К нему подключены мультиплексор и демультиплексор для считывания и записи данных с регистров (номер 2 и 3). С помощью входа `A`, определяется к какому регистру будет применена запись/чтение. Теперь рассмотрим нижнюю часть схемы (см. рис. 11):
![../.pic/Lectures/14.%20Interrupt%20subsystem/fig_11.jpg](../.pic/Lectures/14.%20Interrupt%20subsystem/fig_11.jpg)
*Рис. 11. Нижняя часть схемы CSR.*
Она нужна для оперативного обновления значений регистров `mepc` и `mcause`. Вход `OP[2]` — это сигнал о возникновении прерывания. Если сигнал на прерывание равен 1, то значения `mepc` и `mcause` изменятся. Осталось рассмотреть верхнюю часть схемы (см. рис. 12):
![../.pic/Lectures/14.%20Interrupt%20subsystem/fig_12.jpg](../.pic/Lectures/14.%20Interrupt%20subsystem/fig_12.jpg)
*Рис. 12. Верхняя часть схемы CSR.*
Она нужна для реализации инструкций для работы с CSR. В зависимости от нужной инструкции у выхода `WD` будет своё значение. На нулевой вход мультиплексора поступают нули, если не требуется запись в регистры.
Отдельно стоит отметить, что значение регистра причины прерывания `mcause` берётся из контроллера прерывания. А значение регистра маски прерывании `mie`, которое мы устанавливаем в блоке CSR, отправляется в контроллер прерывания. Давайте рассмотрим устройство контроллера прерывания. У него будет [схема с циклическим опросом](#схемы-реализации-контроллера-прерываний) (см. рис. 13):
![../.pic/Lectures/14.%20Interrupt%20subsystem/fig_13.jpg](../.pic/Lectures/14.%20Interrupt%20subsystem/fig_13.jpg)
*Рис. 13. Контроллер прерывания с циклическим опросом.*
На вход в контроллер прерывания подаются регистры маски прерывания `mie[31:0]`, запросы на прерывание `int_req[31:0]`. Если бит маски и бит запроса будут равны 1 и если в этот момент времени счётчик (красный прямоугольник на рисунке 13) будет соответствовать данному запросу на прерывание, то счётчик будет заблокирован, и будет сформирован сигнал `INT`, который сообщит о прерывании. Значение регистра `mcause` будет соответствовать значению остановленного счётчика.
Такое состояние будет, пока не придёт сигнал с `INT_RST`. Также после получения сигнала `INT_RST` периферийному устройству, чей сигнал обрабатывался, будет передана 1 через регистр `int_fin`, сигнализирующий о том, что обработка прерывания окончена.
В целом схема подключения выглядит так (см. рис. 14):
![../.pic/Lectures/14.%20Interrupt%20subsystem/fig_14.jpg](../.pic/Lectures/14.%20Interrupt%20subsystem/fig_14.jpg)
*Рис. 14. Схема подключения подсистемы прерывания.*
## Программа, реализующая прерывания на ассемблере
Программа обрабатывает два прерывания, имеющие коды 5 и 19. При пятом прерывании некоторое число из памяти делится на 2. При девятнадцатом прерывании к некоторому числу из памяти прибавляется 3.
```assembly
# Инициализируем начальные значения регистров
li sp, 0xFFFFFFFC # устанавливаем указатель на верхушку стека
li gp, 0x10000000 # устанавливаем указатель на глобальные данные
 
li t0, 0x00080020 # подготавливаем маску прерывания для 5 и 19 входов
csrw mie, t0 # загружаем маску в регистр маски
la t0, interrupt # аналогично li загружает число, в данном случае - адрес
csrw mtvec, t0 # устанавливаем вектор прерывания
li t0, 0xEFFFFFFC # готовим адрес верхушки стека прерывания
csrw mscratch, t0 # загружаем в указатель на верхушку стека прерывания
 
li t0, 1 # начальное значение глобальной переменной
lw t0, 0(gp) # загружаем переменную в память
 
while: # бесконечный цикл, аналогичный while (1);
beq x0, x0, while # ничего не делаем!
interrupt:
csrrw t0, mscratch, t0 # меняем местами mscratch и t0
sw t1, 0(t0) # сохраняем t1 на стек mscratch
sw t2, 4(t0) # сохраняем t2 на стек mscratch
# Переключаем адрес возврата на следующую инструкцию
csrr t2, mepc # t2 = pc в момент прерывания
addi t2, t2, 4 # увеличиваем pc на 4
csrw mepc, t2 # mepc = mepc + 4
# Проверяем регистр причины и на 5-ое прерывание
csrr t1, mcause # t1 = mcause
li t2, 5 # t2 = 5 (код одного из прерываний)
bne t1, t2, nineteen # если это не 5 прерывание, то проверяем 19
# Обработчик 5-го прерывания
lw t2, 0(gp) # загружаем переменную из памяти
addi t2, t2, 3 # прибавляем к значению 3
sw t2, 0(gp) # возвращаем переменную в память
j done # идем возвращать регистры и на выход
 
nineteen: # Проверяем на 19-ое прерывание
li t2, 19 # t2 = 19 (код другого прерывания)
bne t1, t2, done # если не 19-ое, то выходим
# Обработчик 19-го прерывания
lw t2, 0(gp) # загружаем переменную из памяти
srli t2, t2, 1 # делим число пополам сдвигом вправо
sw t2, 0(gp) # возвращаем переменную в память
j done # идем возвращать регистры и на выход
 
# Возвращаем регистры на места и выходим
done:
lw t1, 0(t0) # возвращаем t1 со стека
lw t2, 4(t0) # возвращаем t2 со стека
csrrw t0, mscratch, t0 # меняем обратно местами t0 и mscratch
mret # возвращаем управление программе (pc = mepc)
```
## Основные материалы лекции
1. [Ссылка](https://youtu.be/E21EtIasiU8?si=f_UEatkkQUow9iX5) на видеозапись лекции
## Дополнительные материалы к лекции для саморазвития