- Лекция 14. Подсистема прерывания
- Содержание
- Определение
- Передача управления при прерывании
- Классификация событий прерывания
- Основные характеристики прерываний
- Допустимые моменты прерывания программы
- Способы выявления прерывания
- Схемы реализации контроллера прерываний
- Control and Status Register RISC-V
- Подсистема прерываний для RISC-V
- Программа, реализующая прерывания на ассемблере
- Основные материалы лекции
- Дополнительные материалы к лекции для саморазвития
Прерывание — событие, на которое реагирует процессор.
Пример: Перемещение мыши. Если бы не было прерываний, то процессор был бы вынужден постоянно обращаться к мыши с целью узнать: изменилось ли её положение или нет, стоит ли перерисовать курсор. А это очень ресурсоёмко. Такой подход называется сканирование входов.
Сканирование входов — последовательный программный опрос входных сигналов. Этот подход используется в суперкомпьютерах, т.к. у них неразвитая периферия. В таком случае подсистема прерываний не нужна.
В случае, если во время выполнения программы произошло событие прерывания, процессор останавливает выполнение основной программы и начинает выполнять подпрограмму обработки прерывания. Завершив обработку прерывания, процессор возвращается к исполнению основной программы.
Рис. 1. Схема передачи управления при прерывании.
- Прерывания — события, сигнал о которых приходит извне. Это события происходит асинхронно фронту тактового импульса. Пример: перемещение мыши.
- Маски́руемые — прерывания, которые процессор может игнорировать. Например: нажатие клавиши на клавиатуре. Аппаратная реализация будет продемонстрирована чуть позже.
- Немаски́руемые — прерывания, которые процессор не может игнорировать. Например: сигнал от датчика температуры о перегреве процессора.
- Исключения — события, происходящие вследствие выполнения какой-то инструкции. Эти события происходят синхронно фронту тактового импульса.
- Ошибки. Например: обращение в несуществующую область памяти.
- Ловушки. Например: деление на 0.
- Отказы. Например: ситуации, которые никак нельзя устранить. Зачастую приводят к выключению/перезапуску процессора.
-
Время реакции прерывания, Tреакции
Это время, между запросом на прерывание и переходом к прерывающей программе (см. рис. 2)
-
Затраты времени на переключение программ, Tзагрузки и Tвостановления
Это время, которое требуется программе выполнить сервисные инструкции (см. рис. 2). Например: узнать причину прерывания, сохранить данные на стек прерывания и др.
-
Эффективность прерывания
Это время эффективной работы программы. Т.е. отношение "полезных" (не сервисных) инструкций программы прерывания ко всем инструкциям прерывания.
Рис. 2. Характеристики прерывания.
-
Глубина прерывания
Это кол-во прерываний, которые могут произойти во время обработки прерывания (см. рис. 3). Например: если процессор, находясь внутри прерывания, не способен прерваться на другое, то говорят что глубина прерывания n=1. Также программы могут неограниченно прерывать друг друга, в таком случаем, есть ограничение по памяти.
Рис. 3. Глубина прерываний.
В зависимости от архитектуры процессора могут быть использованы различные методы, определяющие когда прерывание становится возможным:
-
Метод помеченного оператора
Внутри какой-нибудь инструкции добавляется бит, отвечающий за прерывание. Допустим, если этот бит равен 1 и есть сигнал на прерывание, то процессор запустит обработчик прерывания.
-
Покомандный метод
Этот метод относится к многотактным архитектурам. Процессор начинает реагировать на сигнал прерывания, только после завершения инструкции.
-
Метод быстрого реагирования
Этот метод позволяет реагировать на прерывание на любом такте.
Маска прерывания — это регистр, отвечающий за разрешение на прерывание (см. рис. 4). Эта маска побитово перемножается с запросами на прерывание других устройств/модулей. Если в результате перемножения получилась хотя бы одна 1, то формируется сигнал interrupt
, который подаётся на блок управления процессора.
Рис. 4. Аппаратная реализация маски́рования прерывания.
-
Обзорная система прерывания
Каждый запрос на прерывание запускает одну и ту же подпрограмму, которая определяет, кто отправил запрос, а затем запускает конкретную программу обработчика прерывания. Работает такая система сравнительно дольше, но реализация её проще.
-
Векторная система прерывания
В векторной системе есть участок памяти — таблица векторов прерывания. В таблице лежат вектора прерывания — адрес начала подпрограммы обработчика прерывания. После обращения к таблице будет запущена нужная подпрограмма. Работает такая система быстрее, но реализовать её сложнее.
Контроллер прерывания — устройство, которое отвечает за передачу сигнала прерывания процессору и формирование кода причины прерывания.
-
Цепочечная схема
От процессора идет сигнал подтверждения
ПДТ
, который приходит только тогда, когда процессор готов обработать какое-то прерывание (см. рис. 5.). Этот сигнал приходит на вход первого устройства, которое, в случае необходимости, выдаёт процессору сигнал на прерывание и вектор прерывания. Если же в прерывании от первого устройства нет необходимости, то сигнал подтверждения передаётся на следующее устройство и т.д. Цепочечная схема проста в реализации, но очень медленная. К тому же в этой схеме некоторые устройства имеют приоритет на другими в очерёдности обработки запроса на прерывание. Также существует вероятность, что до последних устройств никогда не дойдёт сигнал подтверждения, и процессор не обработает их запрос на прерывание.
Рис. 5. Цепочечная схема.
-
Схема с циклическим опросом
Каждый раз, когда в счётчик
СТ
приходит сигналC
(тактирование), он увеличивает своё значение (см рис. 6). Затем это значение подаётся на вход дешифраторуDC
, который только на одном выходе выдаёт 1. И каждый такт меняется номер выхода от 0 до N. Если во время обхода всех выходов появится сигнал на прерывание, то этот сигнал отправится на RS триггер, который затем отправитinterrupt
сигнал процессору. А на входC
счётчикаCT
будет отправлен 0. В таком случае счётчик перестанет суммировать, и он будет иметь значение кода номера прерывания.
Рис. 6. Циклическая схема.
-
Дейзи-цепочка
Рассмотрим дейзи-цепочку (см. рисунок 7). Эта схема будет работать только тогда, когда вход
Приоритет
равен 1. Если на первый запрос пришла 1, то на соответствующий выход y1 будет подана 1, которая будет говорить о том, что именно первое устройство сделало запрос на прерывание. На выходINT
также будет передана 1, которая отправится процессору для оповещения о прерывании. На остальные же выходы y2...yn будет передан 0. Т.е. на выходе y1...yn будет получена только одна 1 от запроса с наивысшим приоритетом. Дейзи-цепочка часто используется в определении наиболее приоритетного запроса.
Рис. 7. Дейзи-цепочка.
Теперь рассмотрим, как выглядит контроллер прерывания. (см. рис. 8) По каналу ПДТ
поступает сигнал от процессора, разрешающий прерывание. Этот сигнал поступает на регистры запроса прерывания. Затем с помощью маски прерывания определяются, каким устройствам разрешён запрос на прерывание. Сигналы на прерывания попадают в схему определения наиболее приоритетного запроса
(например: дейзи-цепочка), где определяется самый приоритетный запрос. С помощью формирователя номера запроса
формируется некоторое число, отвечающее за степень приоритета запроса. В схеме сравнения приоритетов
сравнивается это число с приоритетом текущего прерывания (приоритет текущего прерывания записан в регистры порога прерывания
). Если число, хранимое в регистрах "порога прерывания" меньше, то в порог прерывания
записывается новое число, а на процессор по каналу ЗП
пойдёт сигнал о новом прерывании.
Рис. 8. Схема контроллера прерывания.
Это набор регистров, связанных с блоками процессора, с помощью которых можно управлять ими или узнавать информацию о них.
Минимальный набор для поддержания прерывания в 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 |
Рис. 9. Микроархитектура RISC-V с CSR.
Теперь рассмотрим отдельно блок CSR:
Рис. 10. Схема CSR.
Рассмотрим схему CSR (см. рис. 10). На ней красным прямоугольником (номер 1) отмечены регистры CSR. К нему подключены мультиплексор и демультиплексор для считывания и записи данных с регистров (номер 2 и 3). С помощью входа A
, определяется к какому регистру будет применена запись/чтение. Теперь рассмотрим нижнюю часть схемы (см. рис. 11):
Рис. 11. Нижняя часть схемы CSR.
Она нужна для оперативного обновления значений регистров mepc
и mcause
. Вход OP[2]
— это сигнал о возникновении прерывания. Если сигнал на прерывание равен 1, то значения mepc
и mcause
изменятся. Осталось рассмотреть верхнюю часть схемы (см. рис. 12):
Рис. 12. Верхняя часть схемы CSR.
Она нужна для реализации инструкций для работы с CSR. В зависимости от нужной инструкции у выхода WD
будет своё значение. На нулевой вход мультиплексора поступают нули, если не требуется запись в регистры.
Отдельно стоит отметить, что значение регистра причины прерывания mcause
берётся из контроллера прерывания. А значение регистра маски прерывании mie
, которое мы устанавливаем в блоке CSR, отправляется в контроллер прерывания. Давайте рассмотрим устройство контроллера прерывания. У него будет схема с циклическим опросом (см. рис. 13):
Рис. 13. Контроллер прерывания с циклическим опросом.
На вход в контроллер прерывания подаются регистры маски прерывания mie[31:0]
, запросы на прерывание int_req[31:0]
. Если бит маски и бит запроса будут равны 1 и если в этот момент времени счётчик (красный прямоугольник на рисунке 13) будет соответствовать данному запросу на прерывание, то счётчик будет заблокирован, и будет сформирован сигнал INT
, который сообщит о прерывании. Значение регистра mcause
будет соответствовать значению остановленного счётчика.
Такое состояние будет, пока не придёт сигнал с INT_RST
. Также после получения сигнала INT_RST
периферийному устройству, чей сигнал обрабатывался, будет передана 1 через регистр int_fin
, сигнализирующий о том, что обработка прерывания окончена.
В целом схема подключения выглядит так (см. рис. 14):
Рис. 14. Схема подключения подсистемы прерывания.
Программа обрабатывает два прерывания, имеющие коды 5 и 19. При пятом прерывании некоторое число из памяти делится на 2. При девятнадцатом прерывании к некоторому числу из памяти прибавляется 3.
# Инициализируем начальные значения регистров
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)
- Ссылка на видеозапись лекции