[i] Начало работы с контроллером прерываний CLIC в МК MDR1206(A)FI, MDR1215LGI

ID статьи: 58988
Дата последнего изменения: 05.09.2025 10:20:35
Core-Local Interrupt Controller (CLIC) — это контроллер прерываний, разработанный специально для архитектуры RISC-V. Он представляет собой расширение привилегированной архитектуры, которое обеспечивает гибкие и эффективные механизмы управления прерываниями.

На момент середины 2025 года спецификация CLIC не ратифицирована - Fast Interrupts, в связи с чем функционал CLIC всё ещё дорабатывается и изменяется (работа ведется в репозитории riscv-fast-interrupt). Таким образом при работе с контроллером CLIC требуется точно знать версию спецификации, на основании которой был разработан контроллер.

В МК MDR1206(A)FI и MDR1215LGI реализован контроллер CLIC на основе спецификации "Smclic" Core-Local Interrupt Controller (CLIC) RISC-V Privileged Architecture Extension", версия 0.9-12/21/2021. Подробное описание данной версии контроллера CLIC приведено в спецификации микроконтроллер.

В данной статье рассмотрены особенности работы с контроллером прерываний CLIC, реализованном в МК MDR1206(A)FI и MDR1215LGI, а также описаны особенности работы с CLIC при использовании библиотеки MDR32VF0xI.

Содержание

1. Ключевые особенности CLIC
2. Программная конфигурация CLIC
    2.1 Глобальные настройки CLIC
    2.2 Индивидуальные настройки прерываний в CLIC
3. Режим захват входного сигнала прерывания
4. Векторизация прерываний
    4.1 Обработка исключений и невекторных прерываний
    4.2 Обработка векторных прерывания
5. Уровни, приоритеты и вытеснение прерываний
    5.1 Настройка уровней и приоритетов прерывания
    5.2 Обработка невекторных и векторных прерываний без использования горизонтальных вытеснений
    5.3 Обработка невекторных и векторных прерываний с использованием горизонтальных вытеснений
6. Особенности работы с CLIC при использовании библиотеки MDR32VF0xI
    6.1 Базовая конфигурация CLIC в SystemInit()
    6.2 Определение обработчиков прерывания в зависимости от режима векторизации и горизонтального вытеснения
        6.2.1 Невекторный режим работы прерываний
        6.2.2 Векторный режим работы прерываний


1. Ключевые особенности CLIC

CLIC спроектирован как улучшение базовой системы прерываний RISC-V, которое интегрируется непосредственно в ядро, заменяя часть базового функционала.

Основные особенности CLIC:
  1. Режимы привилегированности: для каждого прерывания можно настроить, в каком режиме привилегированности будет выполняться его обработчик - в режиме Machine (M) или User (U).
  2. Режим захвата прерывания: захват входного сигнала прерывания может быть настроен программно - по уровню (высокому/низкому) или по фронту (положительному/отрицательному). Этот функционал позволяет настраивать CLIC для работы с различными типами периферийных устройств.
  3. Векторизация прерываний: поддерживается как обработка прерываний с помощью общего обработчика, так и векторная обработка прерываний. Настройка векторизации выполняется индивидуально для каждого прерывания.
  4. Приоритет и уровень прерывания: каждому прерыванию можно программно назначить приоритет и уровень прерывания. Количество доступных приоритетов и уровней конфигурируется программно.
  5. Вытеснение прерываний: текущий обработчик прерывания может быть прерван (вытеснен) новым прерыванием, которое имеет более высокий уровень прерывания.

2. Программная конфигурация CLIC

Обширные возможности CLIC неизбежно приводят к повышенной сложности его программной настройки. Помимо настройки каждого отдельного прерывания, разработчику также требуется выполнить глобальную настройку CLIC.

2.1 Глобальные настройки CLIC

Первоначально требуется настроить глобальные настройки CLIC, которые применимы ко всем прерываниям, а именно:

2.2 Индивидуальные настройки прерываний в CLIC

Каждому прерыванию i соответствует набор из 4-х регистров, позволяющих установить:

3. Режим захвата входного сигнала прерывания

Для работы с различными типами периферийных устройств CLIC позволяет для каждого прерывания индивидуально настроить режим захвата сигнала прерывания. Данная настройка осуществляется в поле trig регистра clicintattr[i] и реализует 4 варианта, при которых сигнал прерывания считается активным: Важно отметить, что прерывания, выбранные для работы по уровню, должны обеспечивать активное состояние сигнала прерывания до тех пор, пока прерывание не будет взято в обработку. То есть такие прерывания должны сбрасываться программно в обработчике прерывания. Если сигнал прерывания может быть сброшен аппаратно до входа в обработчик прерывания, то для такого прерывания необходимо выбирать захват по фронту, иначе запрос может не успеть взяться в обработку и будет пропущен.

В МК MDR1206(A)FI и MDR1215LGI все прерывания, кроме DMA, EXT_INTx и системного таймера, рекомендуется настраивать в режим захвата по высокому уровню. Прерывания от DMA и системного таймера рекомендуется настраивать в режим захвата по положительному фронту. Настройка прерывания от EXT_INTx зависит от внешнего устройства, которое формирует сигнал прерывания:

4. Векторизация прерываний

Согласно спецификации RISC-V (The RISC-V Instruction Set Manual Volume I: Unprivileged Architecture), аппаратные события, прерывающие нормальный поток выполнения, делятся на две категории: При возникновении исключения управление всегда передается общему обработчику. При возникновении прерываний обработка будет зависеть от настройки режима векторизации в CLIC:

4.1 Обработка исключений и невекторных прерываний

При возникновении исключения или невекторного прерывания управление передается общему обработчику. Адрес общего обработчика устанавливается в поле BASE CSR-регистра mtvec/utvec. Настройка прерывания i в невекторный режим работы осуществляется в регистре clicintattr[i], бит shv = 0. В общем обработчике необходимо предусмотреть алгоритмы обработки исключений и прерываний. Спецификация RISC-V предполагает выполнение обработки с помощью анализа CSR-регистра mcause/ucase, в котором хранятся: После определения события дальнейшая обработка может быть выполнена любым требуемым способом, однако для универсальности, как правило, реализуется программный трамплин, который на основании номера события и таблиц векторов исключений и прерываний вызывает соответствующий обработчик. Для случая реализации программного трамплина в CLIC предусмотрен CSR-регистр mnxti/unxti, который позволяет ускорить передачу управления обработчику прерывания. При этом реализация программного трамплина для исключений остается с использованием mcause/ucase.
Для работы с mnxti/unxti необходимо предварительно определить таблицу векторов прерываний и записать её адрес в CSR-регистр mtvt/utvt. При чтении CSR-регистра mnxti/unxti выполняется аппаратный поиск подходящего ожидающего прерывания: Активное прерывание считается подходящим к обработке, если выполнены все следующие условия: Если имеется несколько подходящих прерываний, то очередность обработки определяется уровнем и приоритетом прерывания. Подробнее в разделе 5.

Немного остановимся на последнем пункте про предыдущий уровень прерывания. Значение в mcause.pil/ucause.pil обновляется только при аппаратном вызове обработчика прерывания. Если работа выполняется без горизонтального вытеснения и в рамках одного режима привилегированности, то вход в общий обработчик всегда будет осуществляться из основного потока, который имеет уровень прерывания 0. Таким образом все прерывания с уровнем 1 и более будут иметь уровень больше, чем предыдущий уровень прерывания (основного потока).
При работе с горизонтальным вытеснением прерываний при чтении CSR-регистра mnxti/unxti будут возвращаться только прерывания, уровень которых больше, чем основной поток (0) или вытесненное прерывание.

Схематично обработка исключений и невекторных прерываний в M-режиме показана на рисунке 1.

Рисунок 1 - Обработка исключений и невекторных прерываний в M-режиме

4.2 Обработка векторных прерывания

Векторный режим работы прерывания i устанавливается в регистре clicintattr[i], бит shv = 1. При возникновении векторного прерывания из таблицы векторов прерываний аппаратно считывается адрес соответствующего обработчика прерывания, после чего ему передается управление. Ключевое преимущество данного подхода - минимальная задержка до начала выполнения обработчика прерывания, так как полностью исключается этап программной векторизации прерываний.

Схематично обработка векторных прерываний в M-режиме показана на рисунке 2.

Рисунок 2 - Обработка векторных прерываний в M-режиме

5. Уровни, приоритеты и вытеснение прерываний

В ряде приложений требуется обрабатывать сразу несколько прерываний от различных периферийных блоков и с разными режимами привилегированности. При этом для части прерываний может быть критически важным время начала обработки, поэтому такие прерывания должны обрабатываться в первую очередь. Для соответствия требованиям приложения CLIC реализует гибкую систему диспетчеризации прерываний, позволяющую выстроить необходимую очередность выполнения обработчиков прерывания.

Для настройки очередности выполнения обработчиков прерывания CLIC предоставляет следующие настройки: Для немедленной обработки высокоранговых прерываний CLIC поддерживает механизм вытеснения прерываний, позволяющий прерывать выполнение текущего обработчика. CLIC поддерживает два типа вытеснений: Вертикальные вытеснения разрешены всегда, при этом разрешение горизонтальных прерываний настраивается программно для каждого обработчика прерывания.

Очередность выполнения обработчиков прерывания в рамках одного режима привилегированности определяется уровнем и приоритетом прерывания. Сначала проверяется уровень прерывания (прерывания с большим уровнем выполняются в первую очередь), если уровни прерываний одинаковые, то далее проверяется приоритет (прерывания с большим приоритетом выполняются в первую очередь). Горизонтальные вытеснения прерываний определяются только на основании уровня прерываний, приоритет не оказывает влияния на вытеснение.

Важно отметить, что CLIC позволяет комбинировать использование невекторных и векторных прерываний с индивидуальной настройкой горизонтальных вытеснений.
При обработке вертикальных вытеснений для разных режимов привилегированности рекомендуется использовать разные стеки для избежания проблем с уязвимостями безопасности. Для хранения указателя стека при переключении между режимами привилегированности предусмотрены регистры xscratch, а также опциональные регистры xscratchcsw и xscratchcsw1.

5.1 Настройка уровней и приоритетов прерывания

CLIC предоставляет настройку количества приоритетов и уровней прерывания. Суммарно под поля настройки приоритетов и уровней прерывания i в регистре clicintctl[i] выделяется до 8 бит в зависимости от аппаратной реализации. Количество реализованных бит в регистре clicintctl[i] указывается в регистре clicinfo, поле clicintctlbits. Далее в регистре cliccfg с помощью поля nlbits программно настраивается граница полей приоритетов и уровней, которая определяет, сколько бит выделяется для настройки уровней, при этом оставшиеся реализованные биты в clicintctl[i] выделяются для настройки приоритета (clicintctlbits - nlbits).

Наглядно данная настройка представлена на рисунке 3.


Рисунок 3 - Распределение полей приоритетов и уровней прерывания в регистре clicintctl[i]
Например, в MDR1206(A)FI в регистре clicintctl[i] реализовано 4 бита (clicintctlbits), таким образом для приоритетов и уровней прерывания суммарно доступно 24 = 16 вариантов. В регистре cliccfg с помощью поля nlbits устанавливается количество бит для настройки уровней прерывания, при этом: Например, если установить nlbits = 2, то количество уровней и приоритетов будет равное - по 4 варианта.

5.2 Обработка невекторных и векторных прерываний без использования горизонтальных вытеснений

В соответствии со спецификацией RISC-V по умолчанию реализован механизм обработки прерываний без горизонтальных вытеснений - при входе в обработчик прерывания сбрасывается бит глобального разрешения прерываний mie/uie в CSR-регистре mstatus/ustatus, новые прерывания от текущего режима привилегированности запрещаются. Таким образом в рамках одного уровня привилегированности прерывания выполняются поочередно, при этом для нескольких активных прерываний выбор очередности основывается на уровне и приоритете прерываний. При этом сначала проверяется уровень прерывания, а затем, если уровни равны, то приоритет прерывания.

Схематично обработка прерываний без использования горизонтальных вытеснений приведена на рисунке 4.


Рисунок 4 - Обработка прерываний без использования горизонтальных вытеснений

Пояснения к рисунку 4:

5.3 Обработка невекторных и векторных прерываний с использованием горизонтальных вытеснений

Разрешение горизонтальных вытеснений осуществляется программным путем с помощью изменения пролога и эпилога обработчика прерывания.

По умолчанию горизонтальные прерывания выключены. Это связано с тем, что при вызове обработчика прерывания часть контекста прерванного потока аппаратно сохраняется в CSR-регистры mepc/uepc и mcause/ucause. Данные регистры не имеют аппаратного стека, поэтому вызов нового более высокоуровневого прерывания перезапишет эти регистры и контекст будет потерян. В связи с этим при вызове обработчика прерывания горизонтальные вытеснения запрещаются путем аппаратного сброса бита глобального разрешения прерываний mie/uie.

Чтобы включить горизонтальные вытеснения, в конце пролога обработчика прерывания требуется программно сохранить в стек CSR-регистры mepc/uepc и mcause/ucause, после чего разрешить глобальные прерывания. Перед выходом из обработчика прерывания в начале эпилога требуется запретить глобальные прерывания, после чего восстановить CSR-регистры mepc/uepc и mcause/ucause из стека.

Горизонтальные вытеснения прерываний определяются только на основании уровня прерываний. Если уровни прерываний равны, то обработчики прерываний выполняются поочередно на основании приоритета.

Схематично обработка прерываний с использованием горизонтальных вытеснений приведена на рисунке 5.

Рисунок 5 - Обработка прерываний без использования горизонтальных вытеснений

Пояснения к рисунку 5:

6. Особенности работы с CLIC при использовании библиотеки MDR32VF0xI

Для доступа к настройке прерываний необходимо подключить заголовочный файл system_MDR32VF0xI_it.h. Весь функционал по управлению прерываниями расположен в двух программных компонентах:
В MDR32VF0xI вер. 0.2.0 для CLIC реализована поддержка прерываний, работающих только в M-режиме.

6.1 Базовая конфигурация CLIC в SystemInit()

Базовая конфигурация контроллера прерываний CLIC может быть выполнена перед началом исполнения основной программы в функции SystemInit(). Включение конфигурация CLIC и установка параметров настройки выполняется в config-файле: По умолчанию в MDR32VF0xI_config.h/system_MDR32VF0xI_config.h включена конфигурация CLIC в SystemInit() со следующими параметрами (макроопределение CLIC_SYSTEM_INIT раскомментировано):

- глобальные настройки CLIC:
- индивидуальные настройки для всех прерываний:
Независимо от включения базовой конфигурации CLIC (макроопределение CLIC_SYSTEM_INIT) в SystemInit() всегда выполняются следующие настройки: После базовой конфигурации CLIC в основной программе можно использовать функции из драйвера core_clic для настройки отдельных параметров прерываний, аналогично работе с контроллером NVIC в системах с ARM-ядром. Настройка глобальных и индивидуальных для прерываний параметров CLIC также может быть произведена с использованием структур инициализации:

6.2 Определение обработчиков прерывания в зависимости от режима векторизации и горизонтального вытеснения

Помимо конфигурации контроллера CLIC требуется также по-разному определять обработчики прерываний в зависимости от режима векторизации и вытеснения.

В отличие от обычной функции, обработчик прерывания, который аппаратно вызывается при возникновении прерывания, должен содержать расширенный пролог/эпилог для сохранения/восстановления дополнительных регистров ядра, а также специальную инструкцию возврата из обработчика прерывания - mret/uret вместо ret.

Компиляторы GCC/IAR реализуют модификацию обычной функции в обработчик прерывания с помощью указания атрибута interrupt, при этом в таком обработчике горизонтальные вытеснения будут запрещены. Чтобы разрешить горизонтальные вытеснения, требуется дополнительно модифицировать пролог/эпилог обработчика, добавив сохранение/восстановление дополнительных CSR-регистров, хранящих часть контекста прерванного потока, и разрешение/запрещение глобальных прерываний.

Для абстрагирования от компилятора в библиотеку MDR32VF0xI введены следующие макроопределения (core_compiler.h и system_MDR32VF0xI_it.h): Важно отметить, что данные макроопределения должны применяться только для обработчика, который аппаратно вызывается при возникновении прерывания.
Для невекторного режима - это общий обработчик прерываний и исключений Trap_IRQHandler(). Индивидуальные обработчики невекторных прерываний должны быть указаны без атрибута, так как они вызываются программно из Trap_IRQHandler().
Напротив, индивидуальные обработчики векторных прерываний должны быть обязательно указаны с требуемыми вышеуказанными макроопределениями.
По умолчанию определяемые имена обработчиков должны соответствовать именам, указанным в таблицах прерываний и исключений из файла system_MDR32VF0xI_it.с. При необходимости требуемый вектор в таблицах прерываний и исключений может быть перезаписан.

6.2.1 Невекторный режим работы прерываний

Пример определения невекторного обработчика прерывания UART1 в M/U-режиме без привязки к горизонтальному вытеснению приведен в фрагменте кода 1.

Фрагмент кода 1 - Определение невекторного обработчика прерывания UART1 в M/U-режиме без привязки к горизонтальному вытеснению
void UART1_IRQHandler(void)
{
    // Some code.
}
Настройка вытеснения прерываний, работающих в невекторном режиме, выполняется в MDR32VF0xI_config.h/system_MDR32VF0xI_config.h с помощью макроопределения CLIC_TRAP_MACHINE_PREEMPTIBLE:

6.2.2 Векторный режим работы прерываний

Пример определения векторного обработчика прерывания UART1 в M-режиме с запретом горизонтального вытеснения приведен в фрагменте кода 2.

Фрагмент кода 2 - Определение векторного обработчика прерывания UART1 в M-режиме с запретом горизонтального вытеснения
__INTERRUPT_MACHINE void UART1_IRQHandler(void)
{
    // Some code.
}
Пример определения векторного обработчика прерывания UART1 в M-режиме с разрешением горизонтального вытеснения приведен в фрагменте кода 3.

Фрагмент кода 3 - Определение векторного обработчика прерывания UART1 в M-режиме с разрешением горизонтального вытеснения
__INTERRUPT_PREEMPTIBLE(UART1_IRQHandler)(void)
{
    // Some code.
}
__DECLARE_INTERRUPT_MACHINE_PREEMPTIBLE(UART1_IRQHandler);
В одном файле обработчик прерываний с разрешением горизонтального вытеснения сначала определяется c макроопределением `__INTERRUPT_PREEMPTIBLE()`, а затем объявляется c макроопределением __DECLARE_INTERRUPT_MACHINE_PREEMPTIBLE()/__DECLARE_INTERRUPT_USER_PREEMPTIBLE(). Аналогичные примеры приведены в библиотеке MDR32VF0xI, файл system_MDR32VF0xI_it.h.

Контактная информация

Сайт:https://support.milandr.ru
E-mail:support@milandr.ru
Телефон: +7 495 221-13-55