ADSP-BF538: обработка событий (прерывания, исключения)
Добавил(а) microsin
[Обработка событий]
Контроллер событий процессора Blackfin обрабатывает все асинхронные и синхронные события для процессора. Обработка процессором событий поддерживает как настройку приоритетов, так и их вложенность. Вложенность позволяет быть активными сразу нескольким обработчикам прерываний (событий). Приоритезация гарантирует, что обслуживание события с самым большим приоритетом имеет преимущество перед обслуживанием события с меньшим приоритетом. При этом прерывание с меньшим приоритетом может быть вытеснено прерыванием более высоким приоритетом (более приоритетное прерывание окажется вложенным в менее приоритетное).
Примечание: здесь приведен перевод части документации [1], посвященной обслуживанию прерываний. Незнакомые термины и сокращения см. в разделе "Словарик" статьи [2], а также во врезках статьи [2] и этой статьи.
Обратите внимание, что под словом "событие" (event) подразумеваются все типы активности процессора. Контроллер событий всего поддерживает 5 различных событий: Emulation, Reset, NMI, Exception, и 7 шт. Interrupt. Всего имеется 16 событий, с номерами от 0 до 15, и соответствующие им регистры векторов событий EVT0 .. EVT15.
Event №
Класс события
Мнемоника
События ядра
EVT0
Emulation (отладчик JTAG)
EMU
EVT1
Reset (сброс)
RST
EVT2
NMI (не маскируемое прерывание)
NMI
EVT3
Exception (исключение)
EVX
EVT4
Зарезервировано
GBLDIS
EVT5
Hardware Error (аппаратная ошибка)
IVHW
События прерываний
EVT6
Прерывание группы приоритета 6
IVG6
EVT7
Прерывание группы приоритета 7
IVG7
EVT8
Прерывание группы приоритета 8
IVG8
EVT9
Прерывание группы приоритета 9
IVG9
EVT10
Прерывание группы приоритета 10
IVG10
EVT11
Прерывание группы приоритета 11
IVG11
EVT12
Прерывание группы приоритета 12
IVG12
EVT13
Прерывание группы приоритета 13
IVG13
EVT14
Прерывание группы приоритета 14
IVG14
EVT15
Прерывание группы приоритета 15
IVG15
"Прерывание" (interrupt) это событие, которое меняет нормальный ход выполнения программы (не сбрасывая его), асинхронно с последовательностью её выполнения. Это отличает прерывание от исключения (exception), которое привязано к ходу выполнения программы (возникает синхронно с потоком выполнения команд).
Это подпрограмма, отличающаяся от обычной только тем, что для её обработки используется отдельный стек (стек супервизора), и для возврата используется другой регистр (RETI вместо регистра RETS).
Для удобства написания подпрограмм прерываний в среде VisualDSP имеются специальные макросы EX_INTERRUPT_HANDLER и EX_REENTRANT_HANDLER, определенные в заголовочном файле Blackfin\include\sys\exception.h (находится в каталоге установки VisualDSP). Отличие этих макросов в том, что в первый макрос EX_INTERRUPT_HANDLER определяет обработчик прерывания с отключенной вложенностью прерываний (т. е. этот обработчик нельзя ничем прервать, даже прерыванием с более высоким приоритетом), а второй макрос EX_REENTRANT_HANDLER определяет обработчик, который можно прерывать прерыванием с более высоким приоритетом.
Контроллер предоставляет поддержку 5 отдельных типов событий:
Emulation – переводит процессор в режим эмуляции (отладка), что позволяет посылать процессору специальные команды и управлять им через интерфейс JTAG, и получать из процессора отладочную информацию.
Reset – сбрасывает процессор.
Nonmaskable Interrupt (NMI) – программный сторожевой таймер или входной сигнал NMI генерирует для процессора это событие. Событие NMI часто используется как сигнал выключения системы, что позволяет правильно и последовательно выполнить процедуру отключения.
Exceptions (исключения) – события, синхронные с потоком выполнения программы. При этом исключение происходит перед тем, как будет разрешено выполнение инструкции, которая вызвала исключение. Исключения могут вызвать такие события, как нарушение выравнивания данных или неопределенная инструкция.
Interrupts (прерывания) – события, асинхронные по отношению к выполнению программы. Они вызываются сигналами их входных портов, таймеров и других периферийных устройств.
Каждое событие имеет связанный с ним регистр для хранения адреса возврата и связанной инструкции возврата из события. Когда сработало событие, состояние процессора сохраняется в стек супервизора.
Режим супервизора - это когда ядро процессора выполняет код обработки прерывания. Стек супервизора - стек кода обработки прерываний (для обработки прерываний используется отдельный стек).
Контроллер событий процессора состоит из 2 стадий: System Interrupt Controller (SIC) и Core Event Controller (CEC). SIC работает совместно с CEC для обеспечения приоритезации и управления всеми событиями системы. Концептуально архитектура устроена так, что прерывания от периферийного устройства попадают в SIC, и далее напрямую перенаправляются в прерывания общего назначения CEC.
System Interrupt Controller (SIC). Системный контроллер прерываний (System Interrupt Controller) предоставляет привязку и маршрутизацию событий от множества источников прерываний от периферийных устройств на приоритезированные входы прерываний общего назначения CEC ("общего назначения" отражает тот факт, что они могут обрабатывать прерывания от любого аппаратного периферийного устройства - в зависимости от того, как это настроит программист). Хотя процессор предоставляет привязку по умолчанию (которая сама настраивается после сброса), пользователь может поменять привязку (и тем самым приоритет обработки) сигналов прерываний от периферии путем записи подходящих значений в регистры назначения прерываний (Interrupt Assignment Registers, IAR).
Core Event Controller (CEC). Контроллер событий ядра (Core Event Controller) поддерживает 9 прерываний общего назначения (general-purpose interrupts, IVG15–7) в дополнение к выделенному (не настраиваемому) прерыванию и событиям исключения. Из прерываний общего назначения есть 2 прерывания с самым низким приоритетом (IVG15, IVG14), которые рекомендуется резервировать для обработчиков программных прерываний, оставляя входы 7 более приоритетных прерываний (IVG13-IVG7) для поддержки периферийных устройств.
В регистрах SIC_IARx после старта системы автоматически прописывается привязка периферийных устройств к системным прерываниям (событиям), и следовательно назначаются их приоритеты.
Таблица 4-6. Привязка системных прерываний от периферийных устройств к событиям ядра (System and Core Event Mapping).
Источник события
Вектор EVT
PLL Wake-Up Interrupt
IVG7
DMA Controller 0 Error
DMA Controller 1 Error
PPI Error Interrupt
SPORT0 Error Interrupt
SPORT1 Error Interrupt
SPORT2 Error Interrupt
SPORT3 Error Interrupt
SPI0 Error Interrupt
SPI1 Error Interrupt
SPI2 Error Interrupt
UART0 Error Interrupt
UART1 Error Interrupt
UART2 Error Interrupt
CAN Error Interrupt
Прерывания Real-Time Clock
IVG8
DMA0 Interrupt (PPI)
DMA1 Interrupt (SPORT0 Rx)
IVG9
DMA2 Interrupt (SPORT0 Tx)
DMA3 Interrupt (SPORT1 Rx)
DMA4 Interrupt (SPORT1 Tx)
DMA8 Interrupt (SPORT2 Rx)
DMA9 Interrupt (SPORT2 Tx)
DMA10 Interrupt (SPORT3 Rx)
DMA11 Interrupt (SPORT3 Tx)
DMA5 Interrupt (SPI0)
IVG10
DMA14 Interrupt (SPI1)
DMA15 Interrupt (SPI2)
DMA6 Interrupt (UART0 Rx)
DMA7 Interrupt (UART0 Tx)
DMA16 Interrupt (UART1 Rx)
DMA17 Interrupt (UART1 Tx)
DMA18 Interrupt (UART2 Rx)
DMA19 Interrupt (UART2 Tx)
Прерывания Timer0, Timer1, Timer2
IVG11
Прерывания TWI0, TWI1
CAN Receive Interrupt
CAN Transmit Interrupt
Прерывания A и B порта F GPIO
IVG12
MDMA0 Stream 0 Interrupt
IVG13
MDMA0 Stream 1 Interrupt
MDMA1 Stream 0 Interrupt
MDMA1 Stream 1 Interrupt
Software Watchdog Timer
Очищать тетрады регистров SIC_IARx удобно с помощью макроса PX_IVG_CLR (Peripheral Interrupt ID). Здесь Peripheral Interrupt ID это идентификатор периферийного устройства (можно посмотреть в таблице 4-7). Макрос PX_IVG_CLR определен в заголовке VisualDSP 5.0\Blackfin\include\defBF532.h. Пример использования:
// Очищает уровень IVG периферийного устройства 11 (это SPORT1 RX):
*pSIC_IAR1 &= PX_IVG_CLR(11);
Пример кода очистки всех приоритетов прерываний и привязки к периферийным устройствам:
Кроме программирования привязки, отдельные источники прерывания могут быть маскированы (запрещены) в SIC.
[Обработка прерываний системой]
На рис. 4-4 показано, как генерируется прерывание (Interrupt A) для периферийного устройства (подразумевается, что для него разрешено прерывание).
Рис. 4-4. Блок-диаграмма обработки прерывания.
Примечание: в скобках показаны имена MMR (регистров, отображенных на пространство памяти процессора).
Вот описание обработки прерывания (Interrupt A) по шагам:
1. В регистрах SIC_ISR запоминается запрос, и делается проверка - выставлено ли еще не обслуженное прерывание (т. е. обработчик прерывания пока еще не очистил прерывание).
2. Проверяются регистры SIC_IWR чтобы определить, что ядро нужно вывести из состояния ожидания (idle state) и/или разбудить его, выведя из режима сна, базируясь на этом запросе прерывания.
3. Регистры SIC_IMASK разрешают прерывания от периферийных устройств на уровне системы. Если Interrupt A разрешено, то обработка запроса переходит к шагу 4.
4. Регистры SIC_IARx определяют привязку прерываний периферии к набору прерываний общего назначения ядра (general-purpose core interrupts) IVG7 – IVG15. Привязка определяет приоритет обработки для Interrupt A (в зависимости от того к какому из IVG7 – IVG15 оно привязано).
5. Регистр ILAT контроллера CEC добавляет Interrupt A к логу прерываний, захваченных ядром, но пока еще не обработанных.
6. Регистр IMASK контроллера CEC разрешает события разных приоритетов ядра. Если событие IVGx, соответствующее Interrupt A, разрешено, то процесс переходит к шагу 7.
7. Из таблицы векторов прерываний (Event Vector Table, регистры EVTx) выбирается подходящий вектор для обработчика прерывания (interrupt service routine, ISR), в нашем примере это обработчик для Interrupt A.
8. Когда вектор события Interrupt A введен в конвейер ядра, устанавливается подходящий бит IPEND, который очищает соответствующий бит ILAT. Таким образом, IPEND отслеживает все ожидающие (отложенные) прерывания, а также те, которые в настоящий момент обслуживаются.
9. Когда выполнится ISR для Interrupt A, инструкция RTI очистит подходящий бит IPEND. Однако соответствующий бит SIC_ISR не очищается, пока ISR не очистит механизм, который сгенерировал Interrupt A, или пока ISR не очистит этот бит.
Нужно заметить, что события emulation, reset, NMI и exception, как и аппаратная ошибка (hardware error, IVHW) и запросы прерывания таймера ядра (core timer, IVTMR), вводят цепочку обработку прерываний на уровне ILAT, так что на них не влияют регистры прерывания уровня системы (SIC_IWR, SIC_ISR, SIC_IMASK, SIC_IARx).
Если несколько источников прерывания используют одно общее прерывание ядра, то ISR должен сам идентифицировать периферийное устройство, которое сгенерировало прерывание. Так что для ISR может понадобиться программно опросить периферийное устройство, чтобы определить, какое действие нужно предпринять для обработки прерывания.
[Системные прерывания от периферийных устройств]
Система процессора имеет несколько периферийных устройств, поэтому для их обслуживания может потребоваться поддержка нескольких прерываний. В таблице 4-7 перечислены:
• Источники прерывания от периферийных устройств (столбец Peripheral Interrupt Source).
• Идентификатор прерывания периферии (столбец Peripheral Interrupt ID) - числовые коды, используемые для заполнения системных регистров назначения прерываний (system interrupt assignment registers, SIC_IARx). Подробнее см. описание регистров SIC_IARx во врезке "Регистры SIC_IARx".
• Привязка прерываний общего назначения (General-purpose interrupt) ядра, присвоенное по умолчанию после сброса (столбец Reset Defaults). Здесь перечислены имена векторов EVT.
• Идентификатор прерывания ядра (core interrupt ID, столбец Core Interrupt ID), используемый в регистрах назначения системных прерываний (system interrupt assignment registers, SIC_IARx).
Таблица 4-7. Состояние источников прерывания периферийных устройств после сброса.
Структура обработки прерываний периферийных устройств гибко настраивается. По умолчанию после сброса несколько прерываний периферийных устройств совместно используют одно прерывание ядра общего назначения, как это показано в разделе "System Interrupt" руководства ([3] для BF538).
Обработчик прерывания, который должен поддерживать обработку нескольких источников прерываний от аппаратуры периферийных устройств, должен опросить регистры этой аппаратуры (привязанные к памяти регистры, memory mapped registers, MMR), чтобы определить, какое периферийное устройство сгенерировало прерывание.
Если привязка по умолчанию (см. врезку "Привязки приоритетов по умолчанию" или раздел "System Interrupt" руководства [3] для BF538), то в инициализацию прерывания входят только следующие шаги:
• В таблицу векторов ядра Event Vector Table (EVT) записывается адрес вектора обработчика прерывания. • Инициализируется регистр IMASK. • Демаскируется определенное прерывание периферийного устройства в регистре SIC_IMASK.
В процессорах семейства Blackfin может быть один или несколько регистров разрешения пробуждения системы по прерыванию (System Interrupt Wakeup-Enable registers, SIC_IWR). В процессоре ADSP-BF538 таких регистров два: SIC_IWR1 и SIC_IWR0.
Примечание: везде, где в тексте встречается ADSP-BF538 или BF538, имеется в виду 2 модели процессора: ADSP-BF538 и ADSP-BF538F.
Регистры SIC_IWR1 и SIC_IWR0 предоставляют привязку источников прерывания от периферийных устройств к контроллеру динамического управления питанием (Dynamic Power Management Controller, DPMC). Любое из периферийных устройств может быть сконфигурировано для пробуждения ядра - вывода его из состояния ожидания (idle state) или режима сна (Sleep mode) для обработки прерывания, что делается простым разрешением подходящего бита в регистрах SIC_IWRx. Обратитесь к разделу "System Interrupt" руководства по аппаратуре процессора (т. е. [3] для BF538). Если источник прерывания от аппаратуры разрешен в SIC_IWRx, и ядро приостановлено или помещено в режим сна, то прерывание укажет DPMC инициировать последовательность пробуждения, чтобы можно было обработать прерывание. Имейте в виду, что этот режим работы может добавить дополнительную задержку в обработку прерывания, в зависимости от управляемого состояния питания. Для дополнительной информации по режимам питания и состоянию приостановки ядра см. раздел "Dynamic Power Management" в руководстве по аппаратуре процессора ([3] для BF538).
По умолчанию, как это показано в разделе "System Interrupt" ([3] для BF538), все прерывания будут генерировать запрос пробуждения для ядра. Однако для некоторых приложений может понадобиться запретить эту функцию для некоторых периферийных устройств.
Регистр SIC_IWR никак не влияет на поведение процессора, если ядро не приостановлено или не помещено в режим сна. Биты в этом регистре соответствуют аналогичным битам в регистрах System Interrupt Mask (SIC_IMASK) и Interrupt Status (SIC_ISR).
После сброса все действительные биты в регистрах SIC_IWRx будут установлены в лог. 1, что разрешит функцию пробуждения для всех разрешенных прерываний. Перед разрешением прерываний сконфигурируйте этот регистр в в процедуре инициализации, которая выполняется в коде после сброса (до входа в бесконечный цикл функции main). Регистр SIC_IWRx может быть прочитан или записан в любое время. Чтобы защититься случайных ошибок или потери активности прерывания, этот регистр должен быть записан только тогда, когда запрещены все прерывания от периферийных устройств.
Имейте в виду, что функция пробуждения не зависит от функции маскирования прерывания. Т. е. если источник прерывания разрешен в SIC_IWR, но запрещен в SIC_IMASK (замаскирован), то ядро все равно проснется от этого источника прерывания и выйдет из ожидания или сна, однако прерывание не будет сгенерировано (код ISR не запустится).
Настройка по умолчанию для регистра SIC_IWR0 процессора ADSP-BF538:
Настройка по умолчанию для регистра SIC_IWR1 процессора ADSP-BF538:
Примечание: для всех бит 0 означает запрет функции пробуждения, 1 разрешение этой функции.
Системный контроллер прерывания (System Interrupt Controller, SIC) BF538 имеет 2 регистра состояния, предназначенных только для чтения: System Interrupt Status registers (SIC_ISR1 и SIC_ISR0). Каждый бит в этом регистре соответствует одному из источников прерывания от аппаратуры. Бит устанавливается, когда SIC детектирует выставленное прерывание, и сбрасывается, когда SIC детектировал, что было снято на входе прерывание от периферии. Обратите внимание, что для некоторых периферийных устройств, таких как порты ввода/вывода общего назначения (general-purpose I/O, GPIO), асинхронные входы прерывания могут пройти много циклов задержки от момента, когда ISR инициировал очистку прерывания (обычно записью в системный MMR) до времени, когда SIC определит, что прерывание было снято.
В зависимости от того, как источники прерывания привязаны ко входам групп прерываний IVGx, обработчик прерывания (ISR) может взаимодействовать с несколькими битами состояния прерывания, чтобы определить источник - откуда пришло прерывание. Одной из первых инструкций в коде ISR должно быть чтение SIC_ISRx, чтобы определить один из общих источников прерываний для этой группы. ISR должен полностью обработать все ожидающие общие прерывания до выполнения инструкции RTI (выход из ISR), которая разрешит последующие генерации прерываний на этом входе прерываний IVGx.
Важно: когда ISR завершается, инструкция RTI очистит соответствующий бит в регистре IPEND. Однако соответствующий бит в регистре SIC_ISR не будет очищен, пока ISR не очистит механизм, который сгенерировал прерывание.
Во многих системах имеется не так много аппаратных прерываний от устройств, которые надо обрабатывать, так что есть возможность назначить на каждое из таких прерываний уникальный уровень приоритета (т. е. на уникальный вход/группу прерываний IVGx). По крайней мере, нужно стараться проектировать системы именно так. В таких разработках очень редко надо будет читать SIC_ISR (если это вообще когда-нибудь понадобится), потому что каждый ISR будет соответствовать строго одному прерыванию от одного периферийного устройства.
На регистр SIC_ISR не влияет состояние регистра System Interrupt Mask (SIC_IMASK), и SIC_ISR может быть прочитан в любое время. Запись SIC_ISR никак не влияет на его содержимое.
Рис. 4-8. System Interrupt Status Register 0 (SIC_ISR0).
Рис. 4-9. System Interrupt Status Register 1 (SIC_ISR1).
В процессорах семейства Blackfin может быть один или несколько регистров маскирования прерывания (System Interrupt Mask register, SIC_IMASK). В процессоре ADSP-BF538 таких регистров два: SIC_IMASK1 и SIC_IMASK0. Эти регистры позволяют разрешать/запрещать каждый из источников прерывания на системном контроллере прерываний (System Interrupt Controller, SIC), независимо от того, было или нет разрешено соответствующее периферийное устройство.
Сброс принудительно сбрасывает все биты SIC_IMASKx в нули, чем запрещаются прерывания от всех периферийных устройств. Запись 1 в нужный бит разрешает соответствующее прерывание.
Хотя эти регистры могут быть прочитаны или записаны в любое время (в режиме Supervisor), они должны быть инициализированы в процедуре выполнения настроек после сброса, до того, как будут глобально разрешены прерывания.
Рис. 4-10. System Interrupt Mask Register 0 (SIC_IMASK0).
Рис. 4-11. System Interrupt Mask Register 1 (SIC_IMASK1).
Относительные приоритеты прерываний от периферийных устройств могут быть настроены путем привязки прерывания от периферии к соответствующему уровню прерываний ядра (т. е. к нужной группе прерываний IVGx). Привязка управляется регистрами назначения системных прерываний (System Interrupt Assignment Registers, SIC_IARx) - в них делается назначение прерывания периферийного устройства одной из групп прерываний общего назначения IVGx (напомню, что каждая группа IVGx имеет жестко установленный уровень приоритета). Если одной группе назначено больше одного источника прерывания периферии, то они, будучи разрешены, работают в объединением по ИЛИ в обработчике ISR, без какого-то аппаратного назначения приоритета (т. е. в пределах одной группы IVGx все источники прерываний равноправны). В этом случае программное обеспечение может приоритезировать обработку прерываний группы IVGx так, как это требуется в приложении.
Для прерываний общего назначения IVGx, когда на одну группу привязано несколько прерываний аппаратуры, нужно специально позаботиться о корректной обработке со стороны программы всех ожидающих прерываний, привязанных к одному входу IVGx. Программное обеспечение должно само в своем коде обрабатывать приоритет общих прерываний в пределах одной группы IVGx.
Регистры SIC_IARx могут быть прочитаны или записаны в любой момент в режиме Supervisor. Однако желательно их сконфигурировать в обработчике прерывания сброса (Reset interrupt service routine) до глобального разрешения прерываний. Чтобы защититься от ошибок или случайной потери активности прерывания, эти регистры должны быть записаны только тогда, когда все прерывания от периферийных устройств запрещены.
Рис. 4-12. System Interrupt Assignment Register 0 (SIC_IAR0).
Рис. 4-13. System Interrupt Assignment Register 0 (SIC_IAR1).
Рис. 4-14. System Interrupt Assignment Register 0 (SIC_IAR2).
Рис. 4-15. System Interrupt Assignment Register 0 (SIC_IAR3).
Рис. 4-16. System Interrupt Assignment Register 0 (SIC_IAR4).
Рис. 4-17. System Interrupt Assignment Register 0 (SIC_IAR5).
Рис. 4-18. System Interrupt Assignment Register 0 (SIC_IAR6).
Выбор IVG для прерывания
Биты SIC_IARx (вместо N подставляется значение из таблицы 4-8)
SIC_IAR0, значение после сброса 0x1000 0000
Real-Time Clock interrupt
SIC_IAR0, 0xN... ....
UART0 Error interrupt
SIC_IAR0, 0x.N.. ....
SPI0 Error interrupt
SIC_IAR0, 0x..N. ....
SPORT1 Error interrupt
SIC_IAR0, 0x...N ....
SPORT0 Error interrupt
SIC_IAR0, 0x.... N...
PPI Error interrupt
SIC_IAR0, 0x.... .N..
DMA Controller 0 Error (Generic) interrupt
SIC_IAR0, 0x.... ..N.
PLL Wakeup interrupt
SIC_IAR0, 0x.... ...N
SIC_IAR1, значение после сброса 0x3332 2221
DMA7 (UART TX) interrupt
SIC_IAR1, 0xN... ....
DMA6 (UART RX) interrupt
SIC_IAR1, 0x.N.. ....
DMA5 (SPI) interrupt
SIC_IAR1, 0x..N. ....
DMA4 (SPORT1 TX) interrupt
SIC_IAR1, 0x...N ....
DMA3 (SPORT1 RX) interrupt
SIC_IAR1, 0x.... N...
DMA2 (SPORT0 TX) interrupt
SIC_IAR1, 0x.... .N..
DMA1 (SPORT0 RX) interrupt
SIC_IAR1, 0x.... ..N.
DMA0 (PPI) interrupt
SIC_IAR1, 0x.... ...N
SIC_IAR2, значение после сброса 0x6665 5444
Software Watchdog Timer interrupt
SIC_IAR2, 0xN... ....
Memory DMA0 Stream 1 interrupt
SIC_IAR2, 0x.N.. ....
Memory DMA0 Stream 0 interrupt
SIC_IAR2, 0x..N. ....
GPIO interrupt B (порт F)
SIC_IAR2, 0x...N ....
GPIO interrupt A (порт F)
SIC_IAR2, 0x.... N...
Timer 2 interrupt
SIC_IAR2, 0x.... .N..
Timer 1 interrupt
SIC_IAR2, 0x.... ..N.
Timer 0 interrupt
SIC_IAR2, 0x.... ...N
SIC_IAR3, значение после сброса 0x0000 0000
UART2 Error interrupt
SIC_IAR3, 0xN... ....
UART1 Error interrupt
SIC_IAR3, 0x.N.. ....
SPI2 Error interrupt
SIC_IAR3, 0x..N. ....
SPI1 Error interrupt
SIC_IAR3, 0x...N ....
--- (не используется) ---
SIC_IAR3, 0x.... 0...
SPORT3 Error interrupt
SIC_IAR3, 0x.... .N..
SPORT2 Error interrupt
SIC_IAR3, 0x.... ..N.
DMA Controller 1 Error (Generic) interrupt
SIC_IAR3, 0x.... ...N
SIC_IAR4, значение после сброса 0x3222 2220
DMA14 (SPI1) interrupt
SIC_IAR4, 0xN... ....
DMA13 interrupt
SIC_IAR4, 0x.N.. ....
DMA12 interrupt
SIC_IAR4, 0x..N. ....
DMA11 (SPORT3 TX) interrupt
SIC_IAR4, 0x...N ....
DMA10 (SPORT3 RX) interrupt
SIC_IAR4, 0x.... N...
DMA9 (SPORT2 TX) interrupt
SIC_IAR4, 0x.... .N..
DMA8 (SPORT2 RX) interrupt
SIC_IAR4, 0x.... ..N.
CAN Error interrupt
SIC_IAR4, 0x.... ...N
SIC_IAR5, значение после сброса 0x4443 3333
CAN Receive interrupt
SIC_IAR5, 0xN... ....
TWI1 interrupt
SIC_IAR5, 0x.N.. ....
TWI0 interrupt
SIC_IAR5, 0x..N. ....
DMA19 (UART2 TX) interrupt
SIC_IAR5, 0x...N ....
DMA18 (UART2 RX) interrupt
SIC_IAR5, 0x.... N...
DMA17 (UART1 TX) interrupt
SIC_IAR5, 0x.... .N..
DMA16 (UART1 RX) interrupt
SIC_IAR5, 0x.... ..N.
DMA15 (SPI2) interrupt
SIC_IAR5, 0x.... ...N
SIC_IAR6, значение после сброса 0x0044 4664
--- (не используется) ---
SIC_IAR6, 0x0... ....
--- (не используется) ---
SIC_IAR6, 0x.0.. ....
--- (не используется) ---
SIC_IAR6, 0x..4. ....
--- (не используется) ---
SIC_IAR6, 0x...4 ....
--- (не используется) ---
SIC_IAR6, 0x.... 4...
Memory DMA1 Stream 1 interrupt
SIC_IAR6, 0x.... .N..
Memory DMA1 Stream 0 interrupt
SIC_IAR6, 0x.... ..N.
CAN Transmit interrupt
SIC_IAR6, 0x.... ...N
В таблице 4-8 перечислены значения для выбора группы вектора прерывания (Interrupt Vector Group, IVGx), которые записываются в тетрады регистров SIC_IARx.
Таблица 4-8. Номера IVGx для выбора.
Прерывание общего назначения
Значения для записи в SIC_IARx
IVG7
0
IVG8
1
IVG9
2
IVG10
3
IVG11
4
IVG12
5
IVG13
6
IVG14
7
IVG15
8
Устанавливать значение тетрад регистров SIC_IARx удобно с помощью макроса PX_IVG (Peripheral Interrupt ID, IVGx). Здесь Peripheral Interrupt ID это идентификатор периферийного устройства (можно посмотреть в таблице 4-7), а IVGx это значение из таблицы 4-8. Макрос PX_IVG определен в заголовке VisualDSP 5.0\Blackfin\include\defBF532.h. Пример использования:
*pSIC_IAR1 |= PX_IVG(11, 8);// Устанавливает периферийное устройство #11 (SPORT1 RX) на IVG8
[Регистры Core Event Controller (CEC)]
Контроллер событий использует 3 регистра MMR ядра для координирования отложенных запросов событий (поддержка приоритетов и вложенности прерываний). В каждом из этих MMR младшие 16 бит соответствуют 16 уровням событий (т. е. приоритетам). Например, бит 0 соответствует самому приоритетному уровню событий, режиму эмуляции (Emulator mode). Вот эти регистры:
Регистр маски прерываний ядра (Core Interrupt Mask register, IMASK, не путать с регистрами SIC_IMASKx) показывает, какие разрешено брать уровни прерываний. Регистр IMASK можно читать и записывать (но только в режиме супервизора). Имеют значения биты [15:5]; остальные биты [4:0] жестко закодированы в 1, и события от этих уровней всегда разрешены. Если IMASK[N] == 1 и ILAT[N] == 1, то будет взято прерывание N, если пока не было распознано прерывание с более высоким приоритетом. Если IMASK[N] == 0 и ILAT[N] стал установленным прерыванием N, то прерывание не будет взято, и ILAT[N] останется установленным.
Рис. 4-5. Core Interrupt Mask Register.
Примечание: для всех бит 0 означает, что прерывание запрещено (маскировано), 1 разрешено. Помеченные серым цветом биты не используются.
Каждый бит регистра захвата прерывания ядра (Core Interrupt Latch register, ILAT) показывает, что соответствующее прерывание было захвачено, однако пока еще не принято процессором в обработку (см. рис. 4-6). Бит будет сброшен до выполнения первой инструкции в соответствующем ISR. В точке, когда прерывание принято процессором, бит ILAT[N] будет очищен, и одновременно будет установлен бит IPEND[N]. Регистр ILAT может быть прочитан в режиме супервизора. Запись в ILAT используется только для очистки бит (в режиме супервизора). Чтобы очистить бит N в ILAT, сначала убедитесь, что IMASK[N] == 0, и затем запишите ILAT[N] = 1. Это запись функционально используется тогда, когда нужно очистить (отменить) захваченные запросы на прерывание вместо того, чтобы прерывание было обработано.
Инструкция RAISE может использоваться для установки любого бита от ILAT[15] до ILAT[5], и также биты ILAT[2] или ILAT[1].
Только аппаратный сигнал JTAG TRST может очистить ILAT[0].
Для прерываний, которые уже обрабатываются, бит ILAT соответствующей группы IVG не установится, если прерывание заново сработает в системе на уровне источника. Однако соответствующий бит в регистре SIC_ISR останется установленным. Поэтому даже если бит ILAT для отдельного IVG не установлен, в этом процессе прерывания не будут потеряны; контроллер SIC подтвердил бы эту информацию внутренне для контроллера CEC.
Рис. 4-6. Core Interrupt Latch Register.
Примечание: значение после сброса для бита 0 зависит от эмулятора. Для всех бит 0 означает, что прерывание не захвачено, 1 захвачено. Помеченные серым цветом биты не используются.
Регистр ожидающих прерываний ядра (Core Interrupt Pending register, IPEND) отслеживает все вложенные в настоящий момент прерывания (см. рис. 4-7). Каждый бит в IPEND показывает, что соответствующее прерывание сейчас активно или вложено на некотором уровне. Регистр IPEND можно прочитать в режиме супервизора, но нельзя записать. Бит IPEND[4] используется контроллером событий для временного запрета прерываний на входе и выходе ISR.
Когда событие обрабатывается, устанавливается соответствующий бит в регистре IPEND. Самый младший бит в IPEND, который сейчас установлен, показывает то прерывание, которое в настоящий момент обрабатывается. Это будет прерывание с самым высоким приоритетом среди всех выполняемых в настоящий момент, и все остальные прерывания, если они тоже активны, в настоящий момент будут приостановлены (вытеснены). Таким образом, в любой момент времени IPEND содержит в себе состояние всех вложенных друг в друга прерываний.
Рис. 4-7. Core Interrupt Pending Register.
Примечание: для всех бит, за исключением бита 4, лог. 0 означает отсутствие поставленного в очередь прерывания, 1 означает, что прерывание поставлено в очередь или активно (обрабатывается ISR).
[Event Vector Table]
Таблица векторов событий (Event Vector Table, EVT) это аппаратная таблица из 16 записей, каждая 32 бита длиной. Каждая запись EVT содержит вход в процедуру обработки каждого возможного события ядра. Записи EVT доступны как MMR, и каждая запись может быть запрограммирована при сбросе соответствующим адресом вектора для ISR. Когда происходит событие, то происходит передача управления (вызовом подпрограммы обработчика прерывания) по начальному адресу, сохраненному в EVT для этого события.
Архитектура процессора позволяет запрограммировать уникальные адреса в каждый из векторов прерывания; таким образом, нет жесткой фиксации положения обработчиков векторов прерывания в памяти на базе какого-то адреса. Этот подход минимизирует задержку, потому что не нужна команда дальнего перехода (long jump) из таблицы векторов в реальный код ISR (т. е. в EVT уже как бы закэшированы).
В таблице 4-8 перечислены события по приоритету. Каждое событие имеет соответствующий бит в регистрах состояния ILAT, IMASK и IPEND.
Регистр переназначения таблицы векторов событий (event vector table override, EVT_OVERRIDE) определяет источник адресов для векторов групп (входов) прерываний IVG7-IVG15. Например, если установлен бит в EVT_OVERRIDE, который соответствует IVG7, то вектора прерывания IVG7 имеют тот же адрес, что и при сбросе ядра (адрес в месте EVT7 игнорируется, когда это переназначение разрешено). Запись EVT для события Reset (IVG1) это адрес, с которого ядре стартует как только сброс снимается.
Таблица 4-9. Биты регистра EVT_OVERRIDE.
№ бита
Имя
Описание
15
IVG1
0: использовать EVT1 для вектора прерывания RAISE 1. 1: использовать адрес вектора Reset для вектора прерывания RAISE 1 (по умолчанию).
14:8
-
Зарезервировано
7
IVG15
0: нет никаких действий. 1: разрешить переназначение.
6
IVG14
0: нет никаких действий. 1: разрешить переназначение.
5
IVG13
0: нет никаких действий. 1: разрешить переназначение.
4
IVG12
0: нет никаких действий. 1: разрешить переназначение.
3
IVG11
0: нет никаких действий. 1: разрешить переназначение.
2
IVG10
0: нет никаких действий. 1: разрешить переназначение.
1
IVG9
0: нет никаких действий. 1: разрешить переназначение.
0
IVG8
0: нет никаких действий. 1: разрешить переназначение.
[Регистры и инструкции возврата]
Использование переназначения EVT позволяет другим событиям использовать адрес вектор сброса Reset как свой собственный адрес вектора, вместо своего назначенного по умолчанию адреса. Этот подход устраняет потребность двойной косвенной адресации, чтобы выполнить переход на внешне предоставленный адрес при сбросе.
Примерно так, как регистр RETS управляет инструкциями вызова CALL и возврата RTS, так и прерывания и исключения используют аппаратный стек регистров с одной записью. Если обрабатывается прерывание, секвенсер программы сохраняет адрес возврата в регистр RETI до перескока на вектор события. Типичная подпрограмма ISR завершается инструкцией RTI, которая командует секвенсеру перезагрузить значение программного счетчика (Program Counter, PC) значением из регистра RETI. Следующий пример показывает простую подпрограмму ISR.
isr:
[--SP] = (R7:0, P5:0); /* протолкнуть (push) в стек регистры ядра */
[--SP] = ASTAT; /* протолкнуть (push) в стек статус арифметики *//* Здесь нужно разместить код алгоритма ISR */
...
ASTAT = [SP++]; /* выбрать (pop) из стека статус арифметики */
(R7:0, P5:0) = [SP++]; /* выбрать (pop) из стека регистры ядра */
RTI; /* возврат из прерывания */
isr.end:
Нет необходимости заботиться о содержимом регистра RETI, когда запрещена вложенность прерываний. Однако если вложенность должна быть разрешена, и соответствующий обработчик прерывания должен быть прерван (вытеснен) прерыванием с более высоким приоритетом, то регистр RETI должен быть сохранен, скорее всего в стек (хотя не обязательно именно в стек, можно и в другое место памяти).
Хитрость в том, что доступ к регистру RETI имеет неявный дополнительный эффект - чтение регистра RETI разрешает вложенность прерываний. Запись в RETI снова запрещает вложенность. Эта возможность позволяет обработчику ISR разбить самого себя на прерываемые и не прерываемые секции кода. Например:
isr:
[--SP] = (R7:0, P5:0); /* протолкнуть в стек регистры ядра */
[--SP] = ASTAT; /* протолкнуть в стек статус арифметики *//* В этом месте должен быть размещен критический, атомарно выполняемый код: */
...
[--SP] = RETI; /* разрешить вложенность прерываний *//* В этом месте нужно разместить основной код алгоритма ISR,
который может быть прерван более приоритетными ISR: */
...
RETI = [SP++]; /* снова запрет вложенности прерываний *//* Здесь можно разместить еще одну секцию критического,
атомарно выполняемого кода: */
ASTAT = [SP++]; /* выбрать из стека статус арифметики */
(R7:0, P5:0) = [SP++]; /* выбрать из стека регистры ядра */
RTI; /* возврат из прерывания */
isr.end:
Понятие "атомарность" означает "неделимый" - пошло от того, что атомы как бы не делятся (по крайней мере разделить очень трудно). В программировании многозадачных систем (или систем с прерываниями, что в данном контексте одно и то же) есть такое понятие, как атомарная операция. Это такая операция в программе, которая, будучи запущенной, не может быть прервана никаким другим выполняющимся кодом (например, обработчиком прерывания), даже на некоторое время.
Также есть такое понятие, как атомарный доступ к переменной. Например, обычно 32-разрядная процессорная система не может без обеспечения атомарности доступа к переменной размером больше 32 бита гарантировать успешное завершение операции. К примеру, нужно инкрементировать 64 битное число за несколько отдельных операций (сначала увеличить на 1 младшую половину переменной, учесть перенос, и при необходимости увеличить на 1 вторую половину переменной). Если не обеспечить атомарность этой операции, то попытка чтения этой переменной из более приоритетного потока (обработчика прерывания) может дать неверный результат. Обеспечение атомарности операции доступа к переменной устраняет эту проблему.
Для некоторых переменных не нужно обеспечивать атомарность доступа - это те переменные, доступ к которым процессор может осуществить за одну инструкцию ассемблера. Например, инкремент байта на 8-битном микроконтроллере изначально атомарная операция.
Если не требуется иметь в ISR не прерываемый код, то хорошей практикой программирования будет разрешить вложенность немедленно. Это предотвратит нежелательную задержку для запуска высокоприоритетных прерываний. Пример:
isr:
[--SP] = RETI; /* разрешить вложенность прерываний */
[--SP] = (R7:0, P5:0); /* вдвинуть в стек (push) регистры ядра */
[--SP] = ASTAT; /* вдвинуть в стек (push) флаги арифметических операций *//* В этом месте нужно разместить код обработчика прерывания: */
...
ASTAT = [SP++]; /* восстановить из стека (pop) флаги арифметических операций */
(R7:0, P5:0) = [SP++]; /* восстановить из стека (pop) регистры ядра */
RETI = [SP++]; /* запрет вложенности прерываний */
RTI; /* возврат из прерывания */
isr.end:
Подробное описание техники см. в разделе "Вложенность прерываний". События эмуляции, NMI и исключения используют технику наподобие "нормальных" прерываний (т. е. без вложенности). Однако они имеют свой собственный регистр возврата и соответствующую ему инструкцию возврата. Таблица 4-10 дает обзор этих инструкций и регистров.
Таблица 4-10. Регистры и инструкции возврата.
Имя
Класс событий
Регистр адреса возврата
Инструкция возврата
EMU
Эмуляция
RETE
RTE
RST
Сброс
RETI
RTI
NMI
Немаскируемое прерывание
RETN
RTN
EVX
Exception
RETX
RTX
Зарезервировано
-
-
IVHW
Hardware Error
RETI
RTI
IVTMR
Таймер ядра
IVG7
Прерывание 7
IVG8
Прерывание 8
IVG9
Прерывание 9
IVG10
Прерывание 10
IVG11
Прерывание 11
IVG12
Прерывание 12
IVG13
Прерывание 13
IVG14
Прерывание 14
IVG15
Прерывание 15
Выполнение инструкций RTX, RTN или RTE в событии с меньшим приоритетом. Инструкции RTX, RTN и RTE разработаны для возврата из исключения (eXception), NMI и события эмуляции (Emulator) соответственно. Не используйте их для возврата из события с приоритетом ниже. Для возврата из прерывания используйте инструкцию RTI. Ошибочное использование инструкций возврата может привести к непредсказуемым результатам.
В случае RTX будет аппаратно очищен бит IPEND[3]. В случае RTI в регистре IPEND будет аппаратно очищен единичный бит, соответствующий прерыванию с самым высоким приоритетом.
[Emulation Interrupt (прерывание отладки)]
Событие эмуляции переводит процессор в режим эмуляции (Emulation mode), где инструкции читаются из интерфейса JTAG. Это самое высокое по приоритету прерывание для ядра. Детальное описание процесса эмуляции см. в разделе Blackfin Processor Debug руководства по аппаратуре Вашего процессора ([3] для BF538).
[Reset Interrupt (прерывание сброса)]
Прерывание сброса (RST) может быть инициировано через вывод ~RESET или при событии истечения таймаута сторожевого таймера (watchdog timer). Это место отличается от прерываний тем, что его содержимое только для чтения. Запись по этому адресу меняет регистр, но не меняет вектора процессора при сбросе. Процессор всегда при сбросе переходит на вектор сброса.
Состояние сброса (Reset state) инициализирует логику процессора, переводя её в состояние по умолчанию (исходное состояние). Во время Reset state программа приложения и операционная система не выполняются. Такты во время Reset state останавливаются.
Процессор остается в Reset state, пока внешняя логика удерживает в активном уровне внешний сигнал ~RESET. Как только этот сигнал перестанет быть активным, процессор завершает процедуру сброса и переключается в режим супервизора Supervisor, где выполняет код по вектору события сброса.
Программа в режиме супервизора (Supervisor mode) или режиме эмуляции (Emulation mode) может вызвать Reset state без вовлечения внешнего сигнала ~RESET. Это осуществляется выдачей Reset-версии инструкции RAISE.
Программы приложения в пользовательском режиме (User mode) не могут вызвать Reset state, за исключением системного вызова, предоставленного ядром операционной системы. В таблице 3-5 показано состояние процессора при сбросе.
Таблица 3-5. Состояние процессора при сбросе.
Элемент
Описание состояния сброса
Ядро
Рабочий режим
Режим супервизора в событии сброса, такты остановлены.
Режим округления (Rounding Mode)
Несмещенное округление (Unbiased rounding).
Счетчики цикла
Запрещены, обнулены.
DAG-регистры (I, L, B, M)
Случайные значения (должны быть очищены при инициализации).
Регистры данных и адреса
Случайные значения (должны быть очищены при инициализации).
Определяются лог. уровнями выводов BMODE в момент сброса.
Тактовая частота MSEL
Для установленных по умолчанию значений см. описание поля MSEL регистра PLL_CTL в аппаратном руководстве по процессору ([3] для BF538).
Режим пропуска PLL (PLL Bypass Mode)
Запрещен.
VCO/Core Clock Ratio
См. описание поля CSEL регистра PLL_DIV в аппаратном руководстве по Вашему процессору ([3] для BF538).
VCO/System Clock Ratio
См. описание поля SSEL регистра PLL_DIV в аппаратном руководстве по Вашему процессору ([3] для BF538).
Тактирование периферийных устройств
Запрещено.
[Сброс системы и включение питания]
В таблице 3-6 описаны 5 типов сброса. Обратите внимание, что все сбросы за исключением программного сброса (System Software), сбрасывают ядро процессора.
Таблица 3-6. Виды сброса.
Reset
Источник
Результат
Hardware Reset
Подача сигнала на вывод ~RESET.
Сбрасывает как ядро, так и периферийные устройства, включая контроллер динамического управления питанием (Dynamic Power Management Controller, DPMC). Также сбрасывает бит No Boot в регистре SYSCR.
System Software Reset
Запись b#111 в биты [2:0] системного MMR SWRST по адресу 0xFFC00100 приведет к программному сбросу системы.
Сбрасываются только периферийные устройства, исключая блоки RTC и DPMC. DPMC сбрасывает только No Boot в бите Software Reset регистра SYSCR. Ядро не сбрасывается. Последовательность загрузки не инициируется.
Watchdog Timer Reset
Программирование сторожевого таймера может вызвать этот тип сброса, если программа не успела перезагрузить таймер (например повисла).
Сбрасывает как ядро, так и периферийные устройства, за исключением блока RTC и большинства узлов DPMC (Watchdog Timer reset не работает, если процессор находится в режиме сна). Регистр программного сброса (Software Reset register, SWRST) может быть прочитан, чтобы определить, что источником сброса был сторожевой таймер.
Core Double-Fault Reset
Когда это разрешено битом DOUBLE_FAULT в регистре SWRST, этот сброс будет вызван входом ядра в состояние двойной ошибки.
Сбрасывает как ядро, так и периферийные устройства, исключая блок RTC и большинство узлов DPMC. Регистр SWRST может быть прочитан, чтобы определить, что источником сброса был Core Double Fault.
Core-Only Software Reset
Этот сброс вызывается выполнением инструкции RAISE 1, или установкой бита программного сброса (Software Reset, SYSRST) в регистре управления отладкой (Debug Control register, DBGCTL) через программное обеспечение поддержки эмулятора с использованием порта JTAG. Регистр DBGCTL не виден на карте памяти процессора.
Сбрасывает только ядро. Периферийные устройства не распознают этот сброс.
Hardware Reset (аппаратный сброс). Сброс кристалла процессора является асинхронным событием сброса. Для выполнения аппаратного сброса входной вывод ~RESET должен быть переведен из активного состояния (лог. 0) в неактивное (лог. 1), подробнее см. даташит на процессор.
Аппаратно инициированный сброс выполняет широкий сброс системы, который включает как ядро, так и периферийные устройства. После того, как сигнал вывода ~RESET переведен в неактивное состояние из активного, процессор гарантирует, что все асинхронные периферийные устройства распознаны и для них выполнен сброс. После сброса процессор переходит к последовательности загрузки, как это сконфигурировано состоянием выводов BMODE.
Выводы корпуса BMODE это специально выделенные выводы для управления режимом загрузки, на которых больше нет никаких функций. Эти выводы должны быть постоянно подключены напрямую либо к VDD (+ питания, обычно +3.3V), либо к VSS (минус питания, земля, GND). Эти биты и соответствующие биты в SYSCR конфигурируют режим загрузки, который будет реализован после аппаратного сброса или программного сброса системы (System Software reset). Для дополнительной информации см. раздел "Reset Interrupt" и таблицу 4-12.
Значения, прочитанные с выводов BMODE, зеркально отображаются в регистр конфигурации сброса системы (System Reset Configuration register, SYSCR). Эти значения делаются доступными для программного доступа, и могут быть модифицированы программно после процедуры аппаратного сброса.
Различные конфигурационные параметры распространяются в различные места из регистра SYSCR. Подробнее см. раздел, посвященный сбросу и загрузке в руководстве по аппаратуре Вашего процессора ([3] для BF538).
Рис. 3-2. System Reset Configuration Register (SYSCR).
Серым цветом показаны не используемые биты, крестиками показаны биты, состояние которых зависит от внешних входов процессора BMODEx, определяющих режим загрузки.
No Boot on Software Reset. Этот бит вместе с битами BMODEx определяет, как будет загружаться процессор. 0: для определения режима загрузки используются входы BMODE1, BMODE2 процессора, 1: выполнение начинается от начала встроенной памяти L1, или начала памяти ASYNC bank 0, когда BMODE[1:0] = 00.
BMODE[1:0]. Эти биты показывают режим загрузки (Boot Mode), который был выбран внешними выводами корпуса процессора BMODE1 и BMODE0.
00: Выполнение из внешней 16-битной памяти, подключенной к ASYNC Bank0 (пропуск запуска кода Boot ROM). 01: Загрузка из 8/16 битной параллельной микросхемы FLASH/PROM. 10: Загрузка через SPI в режиме SPI Slave mode (данные поступают от хоста SPI). 11: Загрузка из памяти SPI, адресуемой 8/16/24 битами, с поддержкой микросхем памяти Atmel AT45DB041B, AT45DB081B и AT45DB161B DataFlash® (хостом SPI выступает загружаемый процессор Blackfin).
Подробнее см. статью [4].
Программные сбросы и сторожевой таймер. Программный сброс может быть инициирован тремя путями:
• Сторожевым таймером, если это сконфигурировано. • Установкой поля бит системного сброса (System Reset field) в регистре программного сброса (см. рис. 3-2). • Выполнением инструкции RAISE 1.
Сторожевой таймер сбрасывает одновременно ядро и периферийные устройства. Результатом системного сброса (System Reset) будет сброс периферии без сброса ядра и без инициирования последовательности загрузки.
Сброс системы должен быть выполнен при выполнении из памяти L1 (либо кэш, либо SRAM). Когда память инструкций L1 сконфигурирована как кэш, убедитесь, что последовательность системного сброса была прочитана в кэш.
После того, как был инициирован сброс либо от сторожевого таймера, либо от System reset, процессор гарантирует, что все периферийные устройства распознаны, и завершает их сброс.
Для сброса, который был сгенерирован сторожевым таймером, процессор перейдет в выполнение последовательности загрузки, как если бы процессор прошел полное включение с переходом в активный режим. Режим загрузки конфигурируется состоянием выводов управления BMODE и бита NOBOOT (не делать загрузку при программном сбросе).
Если бит NOBOOT в регистре SYSCR очищен, то последовательность загрузки определяется управляющими битами BMODE. Имейте в виду, что содержимое регистра SYSCR меняется от одной модели процессора к другой, поэтому конкретную реализацию см. в описании аппаратуры процессора ([3] для BF538).
Программный сброс может быть инициирован путем установки поля бит системного сброса (System Reset field) в регистре программного сброса (Software Reset register, SWRST). Бит 15 показывает, произошел ли программный сброс от момента, когда был последний раз прочитан регистр SWRST. Бит 14 и бит 13, соответственно, показывают был ли сгенерирован программный сброс от сторожевого таймера или от двойной ошибки ядра (Core Double Fault). Биты [15:13] предназначены только для чтения, и сразу очищаются, когда был прочитан регистр. Биты [3:0] предназначены для чтения и записи.
Когда выводы BMODE не установлены в состояние b#00, и установлен No Boot в бите программного сброса (Software Reset bit) в регистре SYSCR, процессор начинает выполнение с начала памяти L1, встроенной в кристалл. В этой конфигурации ядро начинает выбирать инструкции от начала встроенной в чип памяти L1.
Когда выводы BMODE установлены в b#00, ядро начнет выбирать инструкции по адресу 0x2000 0000 (начало ASYNC Bank 0).
Рис. 3-2. Регистр программного сброса (SWRST).
Программный сброс. Программный сброс (Software reset) инициируется выполнением инструкции RAISE 1 или установкой бита Software Reset (SYSRST) в регистре ядра для управления отладкой (Debug Control register, DBGCTL) через программное обеспечение поддержки отладки с задействованием порта JTAG (регистр DBGCTL не отображается на карту памяти процессора).
На некоторых процессора программный сброс влияет только на состояние ядра процессора. На других процессорах код загрузки немедленно сбрасывает систему, когда выполняется из-за программного сброса. Имейте в виду, что состояние ресурсов системы может быть неопределенным, либо даже быть в недопустимом состоянии, в зависимости от активности системы во время периода сброса.
Сброс ядра и системы. Чтобы выполнить сброс системы и ядра, используйте последовательность кода, показанного в листинге 3-4. Как описано в комментариях к коду, для завершения мягкого сброса системы требуется 5 системных тактовых циклов, так что нужен цикл для задержки. Этот код должен размещаться в памяти L1, чтобы мягкий программный сброс мог работать правильно.
Листинг 3-4. Сброс ядра и системы.
/* Выдача мягкого сброса системы */
P0.L = LO(SWRST);
P0.H = HI(SWRST);
R0.L = 0x0007;
W[P0] = R0;
SSYNC;/* Ожидание момента завершения системного сброса (понадобится 5 тактов SCLK). */
/* Подразумевается самый худший случай, когда соотношение CCLK:SCLK
составляет (15:1), используется 5*15 = 75 в качестве начального значения
для счетчика цикла */
P1 = 75;
LSETUP(start, end) LCO = P1;
start:
end:
NOP;/* Очистка системы мягким сбросом */
R0.L = 0x0000;
W[P0] = R0;
SSYNC;
RAISE 1;
Имейте в виду, что точное поведение сброса и инструкции могут меняться от одной модели процессора к другой. Последовательность в листинге 3-4 рекомендуется только для устройств, у которых не реализована API-функция bfrom_SysControl() API в коде ROM.
У ядра есть выход, который показывает двойную ошибку. Это не восстанавливаемое состояние. Система может быть запрограммирована для отправки запроса на сброс, если детектировано событие двойной ошибки. Это детектирование разрешено битом DOUBLE_FAULT в регистре SWRST. Впоследствии запрос на сброс вызывает сброс системы для ядра и периферийных устройств.
Вектор сброса определяется системой процессора. Он указывает на начало кода встроенное в кристалл boot ROM, или на начало внешней асинхронной памяти - в зависимости от состояния битов выбора режима загрузки BMODE.
[NMI (немаскируемое прерывание)]
Запись NMI зарезервирована для немаскируемого прерывания, которое может быть сгенерировано сторожевым таймером или входным сигналом NMI для процессора. Пример события, на которое требуется немедленное внимание процессора, и для чего подходит NMI, это предупреждение об отключении питания.
Внимание: если произойдет исключение в обработчике события, который уже обслуживает исключение, NMI, сброс, или событие эмуляции, то это вызовет срабатывание условия двойной ошибки, и адрес инструкции, вызвавшей исключение, будет записан в RETX.
Вывод NMI чувствителен к лог. уровню, и должен всегда быть притянут к своему неактивному состоянию, если не используется. Для некоторых моделей вход NMI активен для лог. 1, и на некоторых для лог. 0, за подробностями обратитесь к даташиту на Ваш процессор (для BF538 активный уровень для NMI это ...).
[Exceptions (исключения)]
Исключения обсуждаются в разделе "Аппаратные ошибки и обработка исключений".
Аппаратные ошибки также обсуждаются в разделе "Аппаратные ошибки и обработка исключений".
[Core Timer Interrupt]
Прерывание таймера ядра (Core Timer Interrupt, IVTMR) срабатывает, когда значение таймера ядра достигает 0. Дополнительную информацию по таймеру ядра см. в описании аппаратуры процессора ([3] для BF538).
[General-purpose Core Interrupts (IVG7-IVG15)]
Системный контроллер прерываний (System Interrupt Controller, SIC) может перенаправлять прерывания на события ядра (или группы приоритетов) IVG7-IVG15, которые также называются как прерывания общего назначения. Прерывания общего назначения используются для любого события в системе, которое требует внимания со стороны вычислительного ядра. Например, контроллер DMA может использовать прерывание для сигнализации об окончании передачи данных, или устройство последовательного обмена может использовать прерывание для сигнализации об ошибках передачи.
Программа может также вызывать срабатывание прерываний общего назначения путем использования инструкции RAISE. Эта инструкция может принудительно генерировать события для прерываний IVG15-IVG7, IVTMR, IVHW, NMI и RST, но не для генерации исключений и генерации входа в режим эмуляции (EVX и EMU соответственно).
Хорошей практикой является резервировать 2 группы прерываний с самым низким приоритетом (IVG15 и IVG14) для обработки программных прерываний.
Для системных прерываний, специфичных для конкретной модели процессора, см. описание аппаратуры по этому процессору ([3] для BF538).
[Как глобально разрешить/запретить прерывания]
Прерывания общего назначения можно глобально запретить (т. е. запретить сразу все прерывания) инструкцией CLI Dreg, и заново разрешить инструкцией STI Dreg (здесь Dreg это регистр ядра процессора). Обе эти инструкции доступны только в режиме супервизора. События Reset, NMI, emulation и exception не могут быть глобально запрещены. Глобальный запрет прерываний очищает биты IMASK[15:5] после сохранения текущего состояния IMASK.
CLI R5; // сохранение IMASK в R5, и маскирование всех прерываний
/* Тут можно поместить критические инструкции: */
...
STI R5; // восстановление содержимого IMASK из R5
Если будет попытка выполнить инструкцию CLI или STI в пользовательском режиме ядра (User mode, не Supervisor), то произойдет исключение ошибки: недопустимое использование защищенного ресурса (Illegal Use of Protected Resource exception). Инструкции CLI и STI не могут быть выполнены параллельно с другими инструкциями.
Инструкция CLI часто используется непосредственно перед инструкцией IDLE. Инструкция STI часто размещается после инструкции IDLE, потому что она будет выполнена первой после выхода ядра из состояния приостановки (при пробуждении ядра процессора).
Когда несколько инструкций нужно выполнить атомарно, или когда требуется точно выдержать время выполнения куска кода прерывания, то используют глобальный запрет прерываний (инструкцией CLI) перед начальным куском критичного кода. Но нужно при этом не забыть снова разрешить прерывания в конце критичного кода (инструкцией STI).
[Обслуживание прерываний]
Контроллер событий ядра (Core Event Controller, CEC) имеет один элемент организации очереди на событие - бит в регистре ILAT. Соответствующий бит регистра ILAT устанавливается, когда детектирован фронт сигнала прерывания (что занимает по времени 2 такта ядра), и очищается, когда устанавливается соответствующий бит регистра IPEND. Бит IPEND показывает, что вектор события введен в конвейер ядра. В этот момент времени CEC распознает и ставит в очередь фронт следующего события на соответствующем входе прерывания. Минимальная задержка от момента фронта прерывания общего назначения до выставления на выходе бита в IPEND занимает 3 такта ядра. Однако задержка может быть намного больше, в зависимости от уровня активности ядра и состояния.
Чтобы определить, когда обработать прерывание, контроллер операцией логического AND (т. е. лог. "И") все три элемента в ILAT, IMASK, и текущий уровень приоритета кода, выполняемого процессором.
Обработка прерывания с самым высоким приоритетом вовлекает следующие действия:
1. Вектор прерывания в Event Vector Table (EVT) становится следующим адресом для выборки.
В момент прерывания отбрасывается (обрывается) большинство инструкций, находящихся в настоящий момент в конвейере. При обработке исключения все инструкции после той инструкции, которая вызвала исключение, будут отброшены. На исключении по ошибке будут отброшены инструкция, вызвавшая исключение и все инструкции за ней.
2. Адрес возврата сохраняется в подходящий регистр возврата.
Регистр возврата для прерываний это RETI, для исключений RETX, для NMI это RETN, и для эмуляции/отладки это RETE. Адресом возврата будет адрес следующей инструкции за последней выполненной инструкцией в нормальном потоке выполнения программы.
3. Режим процессора устанавливается в уровень взятого события.
Если событие это NMI, исключение или прерывание, то режим процессора будет Supervisor. Если событие было исключением эмуляции, то режим процессора будет Emulation.
4. Перед тем, как начнется выполнение первой инструкции обработчика, соответствующий бит в регистре ILAT очищается и соответствующий бит в регистре IPEND устанавливается.
Бит IPEND[4] также устанавливается для запрета всех прерываний, чтобы запретить все прерывания, пока сохраняется адрес возврата в RETI.
[Обслуживание системных прерываний]
Прерывания, которыми сигнализируют о событиях периферийные устройства, могут быть как сгруппированы на один уровень приоритета (на одну группу прерываний IVGx приходятся прерывания от нескольких устройств), так и обслуживаться отдельно в выделенной группе (к группе IVGx привязано только одно прерывание). Это зависит от настройки - прерывания могут группироваться в контроллере системных прерываний (System Interrupt Controller, SIC). В отличие от прерываний ядра, системные прерывания чувствительны к уровню. Периферийные устройства не снимают запрос на прерывание, пока это не будет сделано вручную в коде программы.
Если несколько прерываний от периферийных устройств назначены на один и тот же канал (группу прерываний) IVGx, то обработчик прерывания этого IVG обычно требует взаимодействия с регистрами SIC_ISR, чтобы определить, от какого периферийного модуля поступило прерывание. Некоторые модули группируют прерывания далее еще и внутри себя, и тогда эти модули обычно предоставляют регистр состояния, чтобы его также опросил обработчик прерывания с целью разобраться в причине возникновения события.
Хорошей практикой программирования является как можно быстрее подтвердить для периферийного устройства запрос на обслуживание прерывания. Подтверждение позволит периферийному устройству отреагировать на следующие события максимально быстро. ISR должен гарантировать, что запросы были сняты до того, как выполнится инструкция RTI. Иначе ISR будет немедленно вызван заново после выполнения инструкции RTI.
Часто запросы прерываний очищаются операциями write-one-to-clear (W1C), т. е. "записать единицу для очистки". Такая команда записи обычно не приостанавливает ядро, а автоматически захватывается и синхронизируется с доменом системной тактовой частоты (SCLK) до того, как попасть на шину PAB. В зависимости от соотношения частот CCLK и SCLK этот процесс может занять несколько циклов CCLK, прежде чем операция W1C достигнет периферийного устройства. Если операция W1C выполнится в конце ISR, то рекомендуется либо инструкцию SSYNC, либо сделать дополнительный доступ к шине PAB перед инструкцией RTI, чтобы гарантировать, что периферийное устройство снимет запрос до выполнения RTI. Поскольку секвенсер программы и контроллер CEC работают на частоте CCLK, то снятие запроса все еще должно быть синхронизировано с доменом CCLK. Эта синхронизация может занять другой такт SCLK, который не защищен инструкцией SSYNC. Обычно заключительное восстановление регистра и выборка из стека защищает от этой проблемы, и она никогда не случается, однако в общем случае программа все равно должна быть протестирована на предмет корректной работы в случае выбора большого соотношения между частотами CCLK и SCLK. Дополнительное чтение PAB до инструкции RTI самый лучший способ гарантировать действительную очистку события в SIC до выхода из ISR.
Эти инструкции относятся к так называемым инструкциям синхронизации. Когда необходимо жестко соблюдать порядок выполнения загрузок из памяти (load) и сохранений в память (store), что может потребоваться для последовательных записей в устройство ввода/вывода для его настройки и управления, используют инструкции синхронизации ядра или системы. Это CSYNC или SSYNC соответственно.
Инструкция CSYNC гарантирует, что все ожидающие своего выполнения операции ядра завершены и буфер хранения (между ядром процессора и участками памяти L1) были завершены (flushed) до начала выполнения следующий инструкции. Ожидающие операции ядра могут включать в себя прерывания, спекулятивные состояния (такие как предсказания ветвлений), или исключения.
Рассмотрим следующий пример последовательности кода:
IF CC JUMP away_from_here;
CSYNC;
R0 = [P0];
away_from_here:
В этом примере кода инструкция CSYNC гарантирует следующее:
• Ветвление по условию (IF CC JUMP away_from_here) распознано, принудительно поставлено в конвейер выполнения, пока не распознано условие, и любые записи в буфере хранения процессора сброшены (flushed, т. е. засинхронизированы со своим местом назначения). • Все поставленные в очередь прерывания или исключения были обработаны до завершения CSYNC. • Не было рискованной загрузки из памяти.
Загрузки данных и выборки инструкции по условию (инструкции CALL) в затенении перехода по условию обычно не перестанут работать, если не защищены инструкцией CSYNC, как показано выше. Однако, если была попытка загрузки или выборки из недопустимого или не инициализированного региона памяти, контроллер памяти может генерировать аппаратную ошибку из-за нежелательного доступа, даже если операция будет немедленно оборвана. Отдельное внимание должно быть уделено ситуации, если условный переход защищает от указателя NULL. Помните, что адрес 0x00000000 размещается в области SDRAM.
Инструкция SSYNC гарантирует, что все побочные эффекты от предыдущих операций распространяются наружу через интерфейс между областями памяти L1 и остальной частью чипа (т. е. произошла синхронизация по перемещению данных). В дополнение к выполнению функций синхронизации CSYNC, инструкция SSYNC сбрасывает (flush) любые записи в буферы между памятью L1 и доменом системы, и генерирует запрос синхронизации для системы, который требует подтверждения перед завершением SSYNC.
[Очистка запросов на прерывание]
Когда процессор обрабатывает событие ядра, то он автоматически очищает запрошенный бит в регистре ILAT, и в коде ISR не требуется никаких дополнительных действий. Важно понимать, что контроллер SIC не предоставляет какой-либо механизм обратного подтверждения прерывания от контроллера CEC для периферийного устройства. Хотя биты ILAT точно так же автоматически очищаются, когда обслуживается прерывание, все равно сигнализация от периферии не очищает этот чувствительный к уровню запрос, пока это явно не будет сделано в коде программного обеспечения. Если запрос не будет очищен программно, то периферийное устройство удерживает запрос на прерывание, и соответствующий бит ILAT будет немедленно установлен заново. Это приведет к тому, что будет снова вызван тот же вектор прерывания сразу после того, как будет выполнена инструкция RTI.
Таким образом, каждая подпрограмма, которая обслуживает прерывания от периферийного устройства (т. е. код ISR) обязательно должна очистить сигнализирующий запрос на прерывание от соответствующего периферийного устройства. Отдельные периферийные устройства предоставляют заданный механизм для очистки запросов прерывания. К примеру, прерывания приема очищаются, когда принятые данные вычитываются из соответствующих буферов. Запросы на передачу обычно очищаются, когда программа (или DMA) записывает новые данные в буферы передачи. Эти неявные механизмы подтверждения позволяют избежать необходимости трат дополнительных программных циклов в потоковых интерфейсах. Другие периферийные устройства, такие как таймеры, порты GPIO, и запросы на обработку ошибки требуют явных инструкций подтверждения, которые обычно выполняются эффективными операциями W1C (write-1-to-clear).
Листинг 4-4 показывает хороший пример того, как запрос прерывания от GPIO должен быть обработан процессором ADSP-BF537 Blackfin.
Листинг 4-4. Обработка запроса на прерывание от GPIO.
#include < defBF537.h >
.section program;
_portg_a_isr:
/* сохранение используемых регистров */
[--sp] = (r7:7, p5:5);
/* очистка запроса на прерывания от вывода GPIO PG2, */
/* не имеет значения какой канал используется, A или B */
p5.l = lo(PORTGIO_CLEAR);
p5.h = hi(PORTGIO_CLEAR);
r7 = PG2;
w[p5] = r7;
/* здесь поместите код пользователя */
...
/* синхронизация системы, восстановление регистров и выход */
ssync;
(r7:7, p5:5) = [sp++];
rti;
_portg_a_isr.end:
В этом примере показана инструкция типа W1C, которая может потребовать несколько циклов SCLK для завершения, в зависимости от загруженности системы и истории выполнения команд. Программный секвенсер не ждет, пока инструкция завершится, и немедленно продолжает выполнение программы. Инструкция SSYNC гарантирует, что команда W1C действительно завершится и очистит запрос в периферийном устройстве GPIO до того, как выполнится инструкция RTI. Однако инструкция SSYNC не гарантирует, что освобождение запроса прерывания также было распознано контроллером CEC, что может потребовать некоторого большего количества циклов CCLK - в зависимости от соотношения CCLK к SCLK. В обработчиках, состоящих всего из нескольких инструкций рекомендуется использовать 2 инструкции SSYNC между командой очистки и инструкцией RTI. Однако одной инструкции SSYNC обычно достаточно, если команда очистки выполнена ближе к началу кода ISR, или если за инструкцией SSYNC следует другой набор инструкций до того, как произойдет возврат из ISR. Обычно для этой цели используется множественная команда восстановления из стека (pop-multiple), как это показано в листинге 4-4. Альтернативно можно применить чтение из любого системного MMR до выполнения RTI - это будет гарантией, что запись завершена и условие прерывания очищено.
Чувствительная к уровню природа прерываний от периферии позволяет привязать несколько прерываний на один канал IVG и, таким образом, сделать для них одинаковый приоритет. Все это программируется через регистры SIC_IARx. Если сделана привязка нескольких прерываний на одну группу/канал IVG, то общий ISR для этих прерываний обычно должен опрашивать регистр SIC_ISR, чтобы определить какой источник сигнализировал о прерывании. Если вдруг произошло так, что несколько прерываний одновременно запросили прерывание, то тогда в зоне ответственности ISR выбрать способ (и приоритет) их обработки - либо за один вызов ISR, либо за несколько вызовов (обычно 2 вызова), обрабатывая один запрос прерывания на один на вызов. Если был обработан только один запрос, и он был очищен до выполнения инструкции RTI, то тот же ISR будет немедленно вызван снова, чтобы обработать второй запрос от другого периферийного устройства, который все еще находится в ожидании обработки. Первый способ обработки (за один проход ISR) потребует меньше циклов для обслуживания обоих запросов, а второй запрос позволяет повысить приоритетность обработки запросов для выбранного прерывания - в случае использования обработки прерываний без вложенности.
[Программные прерывания]
Программное обеспечение не может напрямую установить биты регистра ILAT, так как запись в ILAT приведет к выполнению операции write-1-to-clear (W1C). Вместо этого используйте инструкцию RAISE для программной установки отдельных битов ILAT. Это безопасно установит нужные биты ILAT без влияния на остальную часть регистра.
Инструкций RAISE не должна использоваться для запуска события эмуляции или исключения, это должно обрабатываться специальными инструкциями EMUEXCPT и EXCPT.
EMUEXCPT (принудительная эмуляция). Вызывает исключение эмуляции, после чего процессор входит в режим эмуляции.
Когда разрешена эмуляция, процессор немедленно получает исключение и входит в режим эмуляции. Когда эмуляция запрещена, инструкция EMUEXCPT ведет себя точно так же, как и инструкция NOP.
Примечание: для процессоров ADSP-BF535 имеется отличие - если эмуляция запрещена, то EMUEXCP генерирует исключение недопустимой инструкции.
Исключение эмуляции имеет самый высокий приоритет среди всех событий процессора.
EXCPT (принудительное исключение). Вызовет исключение с кодом uimm4. Когда выдана инструкция EXCPT, секвенсер передает управление на обработчик исключения, предоставленный пользователем.
Код уровня приложения использует инструкцию EXCPT для работы системных вызовов. Инструкция не устанавливает бит EVSW (бит 3) регистра ILAT.
Часто инструкция RAISE выполняется в обработчике прерывания для снижения приоритета прерывания. Это позволяет менее срочным для выполнения кускам кода ISR быть прерванными даже более низкими по приоритету прерываниями.
isr7: /* Обработчик прерывания для IVG7 */
...
/* здесь выполняются инструкции с высоким приоритетом: */
...
/* рукопожатие с сигнализирующим периферийным устройством: */
RAISE 14;
RTI;
isr7.end:
isr14: /* Обработчик программного прерывания для IVG14 */
...
/* дальнейшая обработка события, инициированная в IVG7 */
RTI;
isr14.end:
Этот пример может читать данные из любого приемного интерфейса, выложить их в очередь, и позволить ISR с меньшим приоритетом выполниться сразу после возврата из isr7. Поскольку IVG15 используется для нормального выполнения программы в системах без многозадачности, IVG14 часто используется для выделения под программные прерывания.
Пример кода обработки исключения использует тот же самый принцип обработки исключения на нормальном уровне приоритета (см. раздел "Аппаратные ошибки и обработка исключений", листинг 4-7).
[Вложенность прерываний]
Прерывания могут обрабатываться либо с разрешением вложенности друг в друга, либо с запретом вложенности. Это уже обсуждалось в разделе "Регистры и инструкции возврата".
Не вложенные прерывания. Если не требуется вложенность прерываний, то все прерывания будут запрещены, пока выполняется какой-то ISR. Однако, обратите внимание: emulation, NMI и исключения все еще будут восприниматься системой.
Когда системе не нужно поддерживать вложенность прерываний, то не нужно сохранять в стек адрес возврата, который и так сохраняется в RETI. Только порция данных, хранящая состояние машины, должна быть сохранена в стеке супервизора (обычно эти действия осуществляются в начале кода ISR). Для возврата из не позволяющего вложенность ISR должна быть выполнена только инструкция RTI, потому что адрес возврата уже хранится в регистре RETI.
На рисунке 4-8 показан пример обработки прерывания, где прерывания глобально запрещены для всего ISR.
Рис. 4-8. Обработка не вложенного прерывания.
CYCLE 1: прерывание захвачено. Все возможные источники прерывания определены. CYCLE 2: прерывание приоритезировано. CYCLE 3: все инструкции выше A2 убиты. A2 будет убита, если это инструкция RTI или CLI. Начнется выборка адреса старта ISR. CYCLE 4: I0 (инструкция в начале ISR) входит в конвейер. CYCLE M: Когда инструкция RTI достигнет стадии DF1, инструкция A3 будет выбрана в подготовке возврата из прерывания. CYCLE M+4: RTI достигла стадии WB, заново разрешаются прерывания.
Вложенные прерывания. Если нужно обеспечить поддержку вложенности прерываний в каком-то ISR, то в нем адрес возврата в точку прерывания должен быть дополнительно явно сохранен в стеке, и впоследствии восстановлен из стека при выходе. Вложенность разрешается инструкцией проталкивания (push) в стек супервизора адреса возврата, находящегося в настоящий момент в RETI ([--SP] = RETI), что обычно делается как можно раньше, в начале ISR (у которого приоритет меньше, и который позволяет вложенность в себя). Это действие очистит бит глобального запрета прерываний IPEND[4], и разрешит прерывания. Далее, как обычно, все регистры, используемые в ISR, также проталкиваются в стек супервизора. Состояние процессора сохраняется в стек супервизора, не в стек режима пользователя. Следовательно, инструкции проталкивания в стек RETI ([--SP] = RETI) и выборки из стека RETI (RETI = [SP++]) будут работать со стеком супервизора.
Рисунок 4-9 показывает, что проталкиванием RETI в стек прерывания могут быть разрешены во время выполнения ISR, в результате прерывания будут запрещены только в очень малый отрезок времени.
Рис. 4-9. Обработка вложенного прерывания.
CYCLE 1: прерывание захвачено. Все возможные источники прерывания определены. CYCLE 2: прерывание приоритезировано. CYCLE 3: все инструкции выше A2 убиты. A2 будет убита, если это инструкция RTI или CLI. Начнется выборка адреса старта ISR. CYCLE 4: I0 (инструкция в начале ISR) входит в конвейер. Предполагается, что это инструкция проталкивания (push) в стек RETI (с целью разрешить вложенность прерываний). CYCLE 10: когда push достигнет стадии DF2, прерывания снова разрешаются. CYCLE M+1: когда инструкция выборки из стека (pop) RETI достигнет стадии DF2, прерывания запрещены. CYCLE M+5: когда RTI достигнет стадии WB, прерывания заново разрешены.
Листинг 4-5. Пример предварительного кода для ISR, позволяющего вложенность.
/* Код пролога для ISR, позволяющего вложенность прерываний. Здесь в стек
супервизора проталкивается значение адреса возврата в RETI, что гарантирует
разрешение прерываний (у которых более высокий приоритет, что у текущего).
До этого момента все прерывания приостановлены. */
ISR:
[--SP] = RETI; /* это действие разрешает прерывания и сохраняет адрес возврата в стек */
[--SP] = ASTAT;
[--SP] = FP;
[-- SP] = (R7:0, P5:0);
/* Здесь должно быть размещено тело обработчика прерывания. Обратите внимание, что
ресурсы процессора (аккумуляторы, DAG-и, счетчики циклов и границы) не сохранены.
Т. е. предполагается, что ISR не использует ресурсы процессора. */
...
Листинг 4-6. Пример завершающего кода для ISR, позволяющего вложенность.
/* Код эпилога для ISR, позволяющего вложенность. Здесь восстанавливаются
регистры ASTAT, данных и указателя. Выборка (pop) RETI из стека супервизора
гарантирует, что прерывания приостановлены между загрузкой адреса возврата
и выполнением RTI. */
(R7:0, P5:0) = [SP++] ;
FP = [SP++] ;
ASTAT = [SP++] ;
RETI = [SP++];
/* Выполнение RTI, которая делает переход на адрес возврата, снова разрешает
прерывания, и переключается в режим пользователя (User mode), если это было
последнее из ряда вложенных друг в друга ISR. */
RTI;
Инструкция RTI приводит к возврату из прерывания. Адрес возврата извлекается из стека в регистр RETI, это действие приводит к приостановке прерываний от момента, когда RETI восстановился до момента, когда инструкция RTI завершила выполнение. Приостановка прерываний предотвращает ситуацию, что следующее прерывание повредит регистр RETI.
Далее инструкция RTI очистит бит с самым высоким приоритетом, который установлен в настоящий момент в IPEND. Затем процессор перескакивает по адресу, на который указывает значение регистра RETI, и заново разрешает прерывания очисткой IPEND[4].
Запоминание вложенных запросов прерываний. Контроллер прерываний системы (System Interrupt Controller, SIC) детектирует и перенаправляет чувствительные к уровню запросы на прерывание от периферийных устройств. Контроллер событий ядра (Core Event Controller, CEC) предоставляет чувствительное к срезу детектирование для прерываний общего назначения (группы прерываний IVG7-IVG15, жестко привязанные к приоритетам). Следовательно, SIC генерирует синхронный импульс прерывания для CEC, и затем ждет подтверждения прерывания от CEC. Когда прерывание было подтверждено ядром (через выставление подходящего выхода IPEND), SIC генерирует другой синхронный импульс прерывания для CEC, если прерывание периферии все еще выставлено. С таким методом обработки не теряются запросы на обработку прерывания, когда они возникли во время обработки другого прерывания.
Несколько источников прерываний может быть привязано к одному прерыванию общего назначения ядра (группе прерываний IVGx). По этой причине несколько импульсов запросов прерываний могут поступить от SIC одновременно, перед обработкой прерывания или во время обработки для события прерывания, которое уже было детектировано для этого входа прерывания. Для совместно обрабатываемых прерываний на одной группе IVGx есть описанный ранее механизм подтверждения прерывания IPEND, который заново разрешает все совместно обрабатываемые прерывания. Если любое из общих в обработке источников прерываний все еще выставляют свой запрос, то контроллером SIC будет снова сгенерирован как минимум 1 импульс. Регистры состояния прерывания (Interrupt Status registers, ISR) показывают текущее состояние совместно обрабатываемых источников прерывания.
Само-вложенность прерываний ядра. Прерывания, которые вложены "сами в себя" могут быть прерваны событиями с тем же уровнем приоритета. Когда установлен бит SNEN в регистре SYSCFG, то поддерживается самовложенность прерываний ядра. Самовложенность поддерживается для любого уровня прерывания, сгенерированного как инструкцией RAISE, так и для прерываний уровня ядра.
В качестве примера предположим, что бит SNEN установлен, и процессор обрабатывает прерывание, сгенерированное инструкцией RAISE 14. Как только регистр RETI был сохранен в стек внутри ISR, вторая инструкция RAISE 14 позволит процессору обслужить второе прерывание.
Когда разрешена самовложенность, процессор устанавливает последний бит регистра RETI, когда проталкивает его в стек. Когда RETI впоследствии выбирается из стека, то этот последний бит проверяется. Если он установлен, то процессор не делает очистку регистра IPEND. Таким образом, соответствующий бит в IPEND не очищается по выполнении инструкции RTI, и в этом процессе прерывания не теряются. Обратите внимание, что на плечи пользователя ложится ответственность по корректному проталкиванию/выборке (push/pop) регистра RETI в стек/из стека.
Самовложенность не поддерживается для прерываний периферии системного уровня, таких как SPORT или SPI.
Регистр конфигурации системы (System Configuration register, SYSCFG) управляет конфигурацией процессора. К этому регистру можно получить доступ только из режима супервизора.
Рис. 4-3. System Configuration Register.
Выделение пространства под системный стек. Модель программного стека для обработки исключений подразумевает, что стек супервизора никогда не должен генерировать исключение, когда обработчик исключения сохраняет свое состояние. Однако, если стек супервизора вырастет за запись CPLB или блок SRAM, то фактически может сгенерироваться исключение.
Чтобы гарантировать, что стек супервизора никогда не сгенерирует исключение - не произойдет переполнения последней записи CPLB или блока SRAM при выполнении обработки исключения - рассчитайте максимальное пространство, которое займут все ISR и обработчик исключения, когда они станут активны, и выделите под стек достаточно места в SRAM.
[Задержки в обработке прерываний]
В некоторых процессорных архитектурах, если инструкции выполняются из внешней памяти, и прерывание произойдет в тот момент, когда выборка инструкции текущей операции не завершилась, то прерывание остается отложенным до того момента, пока текущая операция по обработке инструкции не завершится. Предположим, что процессор работает на частоте 300 МГц, и время выполнения кода из внешней памяти занимает по доступу 100 нс. В зависимости от того, когда произойдет прерывание по отношению к операции выборки инструкции, ISR может быть задержано до примерно 30 тактов. Когда учитываются операции работы с кэшем, ISR может быть задержано на еще большее время - сотни циклов ядра.
Чтобы обеспечить для высокоприоритетных прерываний как можно меньшую задержку в запуске ISR, процессор позволяет выполнить любую операцию с высокой латентностью на уровне системы, пока ISR выполняется из памяти L1. См. рисунок 4-10.
Рис. 4-10. Минимизация латентности в обработке ISR.
Если загрузка инструкции не попала в кэш инструкций L1, и генерируется высоколатентная операция заполнения строки кэша, то когда возникнет прерывание, оно будет задержано до того момента, пока не завершится заполнение. Вместо этого процессор выполнит ISR в его новом контексте, и операция заполнения кэша завершится в фоне.
Обратите внимание, что ISR должна находиться в кэше L1 или памяти SRAM, и не должна генерировать промахи кэша, доступ к памяти L2 или доступ к периферии, поскольку процессор уже занят выполнением операции заполнения строки оригинального кэша. Если в ISR будет выполнена операция по загрузке или сохранению одного из этих типов доступа, то ISR будет задержана пока не завершится оригинальный внешний доступ, до инициирования новой операции загрузки или сохранения.
Если ISR завершит свое выполнение до завершения операции загрузки, то процессор приостановится, ожидая завершения заполнения.
То же самое поведение наблюдается для остановок при вовлечении чтений медленной памяти или периферийных устройств.
Запись в медленную память обычно не показывает такого поведения, поскольку считается, что запись укладывается в 1 цикл, так как данные немедленно передаются в буфер записи для последующей обработки.
Подробнее информацию по структуре памяти и кэша см. раздел 6 "Memory" документации [1].
Регистр состояния секвенсера (Sequencer Status register, SEQSTAT) содержит информацию по текущему состоянию секвенсера, как и диагностическую информацию о последнем произошедшем событии. SEQSTAT является регистром только для чтения, и его можно прочитать только в режиме супервизора.
Рис. 4-12. Sequencer Status Register (ADSP-BF5xx).
Hardware Error Interrupt. Прерывание аппаратной ошибки (Hardware Error Interrupt) показывает наличие ошибки в аппаратуре или неправильное функционирование системы. Аппаратные ошибки происходят, когда внешняя логика ядра, такая как контроллер шины памяти, не может завершить передачу данных (чтение или запись), и выставляет входной сигнал ошибки для ядра. Такие аппаратные ошибки вызывают Hardware Error Interrupt (прерывание IVHW в таблице векторов событий EVT, с задействованием регистров ILAT, IMASK и IPEND). Обработчик Hardware Error Interrupt может затем прочитать данные о причине ошибки из 5-разрядного поля HWERRCAUSE, имеющегося в регистре состояния секвенсера (Sequencer Status register, SEQSTAT), и в зависимости от вида ошибки предпринять соответствующие действия.
Hardware Error Interrupt генерируется в следующих случаях:
• Ошибки четности шины (Bus parity errors). • Внутренние ошибки ядра, такие как переполнение в мониторе быстродействия (Performance Monitor overflow). • Ошибки периферийных устройств. • Ошибки таймаута шины.
В таблице 4-11 перечислены поддерживаемые аппаратные события ошибки с их соответствующим кодами поля HWERRCAUSE. Код самой последней ошибки появится в поле HWERRCAUSE. Если сразу произошло одновременно несколько ошибок, то только последняя из них может быть распознана и обслужена. Ядро не поддерживает приоритезацию, конвейеризацию или постановку в очередь нескольких кодов ошибок. Hardware Error Interrupt остается активным до тех пор, пока пока остается активным любое из условий ошибки.
Обратите внимание, что состояние аппаратной ошибки нельзя очистить программно. В случае аппаратной ошибки RETI не сохраняет адрес инструкции, которая вызвала аппаратную ошибку. Возможно, что аппаратная ошибка была вызвана инструкцией, выполненной за некоторое количество тактов ядра до момента, когда эта ошибка была зарегистрирована. В таких сценариях рекомендуется использовать буфер трассировки, чтобы вычислить инструкцию, которая могла вызвать аппаратную ошибку.
Аппаратная ошибка может быть сгенерирована либо доступом ядра, либо DMA.
В двухядерных платформах (что не относится к ADSP-BF538) аппаратная ошибка будет зарегистрирована только в том ядре, которое вызвало ошибку. Если в двухядерной платформе ошибку сгенерировал DMA, то ошибка распространится на оба ядра.
Таблица 4-11. Аппаратные условия, которые приводят к прерываниям аппаратной ошибки.
Аппаратное условие
HWERRCAUSE (bin)
HWERRCAUSE (hex)
Примечания/примеры
DMA Bus Comparator Source
0b00001
0x01
(Только для BF535) выход Compare Hit перенаправляется напрямую на вход прерывания аппаратной ошибки (Hardware Error interrupt input). Прерывание Compare Hit можно замаскировать (запретить) записью в регистр управления компаратором шины DMA (DMA Bus Control Comparator, DB_CCOMP).
System MMR Error
0b00010
0x02
(Не применимо к BF535) ошибка может произойти, если происходит доступ к недопустимому системному MMR, если к 32-разрядному регистру происходит обращение из 16-разрядной инструкции, или если к 16-разрядному регистру осуществляется доступ из 32-разрядной инструкции.
External Memory Addressing Error
0b00011
0x03
(Не применимо к BF535) была сделана попытка резервирования не инициализированной памяти.
Performance Monitor Overflow
0b10010
0x12
Переполнения монитора быстродействия. Подробнее см. раздел "Performance Monitor Unit" руководства [1].
Error from D-cache A fill buffer
0b10110
0x16
(Только для BF535) была сделана попытка доступа к зарезервированной или не инициализированной памяти.
Error from D-cache B fill buffer
0b10111
0x17
(Только для BF535) была сделана попытка доступа к зарезервированной или не инициализированной памяти.
RAISE 5 instruction
0b11000
0x18
Программа выдала инструкцию RAISE 5 для вызова Hardware Error Interrupt (IVHW).
Зарезервировано
все другие битовые комбинации
все другие значения
Исключения (Exceptions). Исключения синхронны по отношению к потоку выполнения инструкций. Другими словами, отдельная инструкция может вызвать исключение, когда попытается выполниться. Никакие инструкции после "незаконной" инструкции не будут выполнены до того, как запустится обработчик исключения.
Многие исключения связаны с памятью. Например, исключение будет выдано в случае не выровненного доступа к памяти, или когда произошел промах мимо буфера защиты кэширования (cacheability protection lookaside buffer, CPLB), или когда происходит нарушение защиты доступа. Исключения также выдаются, когда выполняется недопустимая инструкция или недопустимая комбинация регистров для инструкции.
Исключение может быть зафиксировано либо до, либо уже после выполнения инструкции, в зависимости от того, было ли это исключение типа службы или ошибочное исключение типа (service type or an error type exception).
Инструкция, вызвавшая событие исключения службы типа (service type event) будет выполнена, и адрес, записанный в регистре RETX, будет указывать на инструкцию после той, которая вызвала исключение. Пример исключения службы типа - один шаг в отладчике.
Инструкция, вызвавшая события ошибки типа (error type event) не может быть выполнена, так что адрес, записанный в регистр RETX, будет адресом незаконной инструкции. Пример error type event - промах CPLB.
Обычно регистр RETX содержит корректный адрес для возврата. Чтобы пропустить незаконную инструкцию, позаботьтесь о случае, когда следующий адрес не простой следующий линейный адрес. Это может произойти, когда исключение вызывала инструкция в конце цикла. В этом случае правильным следующим адресом будет начало цикла.
Поле EXCAUSE[5:0] в регистре состояния секвенсера (Sequencer Status register, SEQSTAT) записывается всякий раз, когда было взято исключение, и оно указывает обработчику исключения, какой произошел тип исключения. Обратитесь к таблице 4-13 для получения списка событий, которые могли вызвать исключения.
Важно: если исключение произошло в обработчике события, который уже обрабатывает исключение, NMI, сброс, или событие эмуляции, то это вызовет срабатывание условия двойной ошибки (double fault condition), и адрес инструкции, вызвавшей исключение, будет записан в RETX (для процессора BF535 имеется другое поведение, см. таблицу 4-13 и примечание 2 к ней).
Таблица 4-13. События, которые вызывают исключения.
Исключение
EXCAUSE
Тип(1)
Примечания/примеры
Инструкция EXCPT, принудительно запускающая исключение, с 4-битным полем m.
поле m
S
Инструкция предоставляет 4-битный код для поля EXCAUSE.
Один шаг.
0x10
S
Когда процессор находится в пошаговом режиме, каждая инструкция кода генерирует исключение. Обычно это используется для отладки.
Исключение, к которому приведет заполнение буфера трассировки.
0x11
S
Процессор получает это исключение, когда переполняется буфер трассировки (только когда эта функция разрешена регистром Trace Unit Control).
См. секцию руководства [1], посвященную правилам множественных ошибок (multi-issue rules).
Data access CPLB protection violation
0x23
E
Сделана попытка прочитать или записать ресурс, доступный только для режима супервизора, или был недопустимый доступ к памяти. Ресурсами супервизора являются регистры и инструкции, которые зарезервированы для использования супервизором: регистры супервизора, все MMR и инструкции, относящиеся только к супервизору (одновременный, двойной доступ к двум MMR с использованием DAG-ов генерирует такой тип исключения). Дополнительно эта запись используется для сигнализации о нарушении защиты, вызванном неразрешенным доступом к памяти, и это определено блоком Memory Management Unit (MMU) защищенного кэшируемого буфера (cacheability protection lookaside buffer, CPLB).
Data access misaligned address violation
0x24
E
Сделана попытка не выровненного по адресу доступа к памяти данных или данным кэша.
Unrecoverable event
0x25
E
Невосстановимое событие. Например, исключение было сгенерировано при обработке предыдущего исключения.
Data access CPLB miss
0x26
E
Используется блоком MMU для сигнализации о промахе CPLB при доступе к данным.
Data access multiple CPLB hits
0x27
E
Для выборки адреса данных есть больше одной совпадающей записи CPLB.
Watchpoint match
0x28
E
Исключение, вызванное совпадением точки останова отладки. При этом установлен один из битов EMUSW в регистре управления установки контрольной точки (Watchpoint Instruction Address Control register, WPIACTL).
Instruction fetch misaligned address violation
0x2A
E
Сделана попытка не выровненной выборки кэша инструкции (обратите внимание, что это исключение никогда не будет сгенерировано относительными ветвлениями от PC, оно будет действовать только для косвенного ветвления). Для процессора ADSP-BF535 есть специальное поведение, см. примечание (2).
Instruction fetch CPLB protection violation
0x2B
E
Недопустимая выборка инструкции доступа (memory protection violation, нарушение защиты памяти).
Instruction fetch CPLB miss
0x2C
E
Промах CPLB на выборке инструкции.
Instruction fetch multiple CPLB hits
0x2D
E
Адресу выборки инструкции соответствует больше одной совпадающей записи CPLB.
Illegal use of supervisor resource
0x2E
E
Сделана попытка использования регистра супервизора или его инструкции из режима пользователя (User mode). Ресурсы и регистры супервизора зарезервированы только для использования в режиме супервизора. Это регистры супервизора, все MMR, инструкции, предназначенные только для супервизора.
Примечания:
(1): Буква в этом столбце обозначает тип исключения. Для служб (S) адресом возврата будет адрес инструкции, которая следует за исключением. Для ошибок (E) адресом возврата будет адрес инструкции, которая вызвала исключение.
(2): Во время исключения выборки инструкции при невыровенном доступе для процессоров ADSP-BF535 есть отличие: адрес возврата, предоставленный в RETX, является адресом назначения, который не выровнен, а не адресом незаконной инструкции. Например, если сделана попытка косвенного ветвления на не выровненный адрес, находящийся в P0, то адрес возврата в RETX равен P0, а не адресу инструкции ветвления.
Если инструкция привела к нескольким исключениям, то первым в SEQSTAT будет зарегистрировано исключение с самым высоким приоритетом. Приоритеты исключений перечислены в таблице 4-14. Если исключение с самым высоким приоритетом обработано, то будет зарегистрировано и может быть обработано следующее по приоритету исключение, и так далее. Например предположим, что следующая инструкция генерирует исключение промаха CPLB инструкции (0x2C), и исключение промаха данных CPLB (0x26). При выполнении этой инструкции сначала будет сгенерировано событие исключения инструкции CPLB. После обработки этого исключения пользователем ядре выполнит инструкцию снова, и в этот раз будет сгенерировано исключение данных CPLB.
[P0] = R0; /* генерирует инструкцию CPLB miss и данные CPLB пропадут */
Таблица 4-14. Исключения по убыванию приоритета (чем больше номер приоритета, тем ниже приоритет).
Приоритет
Исключение
EXCAUSE
1
Unrecoverable Event (не восстанавливаемое событие)
0x25
2
I-Fetch Multiple CPLB Hits (множественные попадания в кэш)
0x2D
3
I-Fetch Misaligned Access (не выровненный доступ)
0x2A
4
I-Fetch Protection Violation (нарушение защиты)
0x2B
5
I-Fetch CPLB Miss (промах защиты кэша)
0x2C
6
I-Fetch Access Exception (ошибка доступа)
0x29
7
Watchpoint Match
0x28
8
Undefined Instruction (неопределенная команда)
0x21
9
Illegal Combination (недопустимая комбинация)
0x22
10
Illegal Use of Protected Resource (недопустимое использование защищенного ресурса)
0x2E
11
DAG0 Multiple CPLB Hits
0x27
12
DAG0 Misaligned Access
0x24
13
DAG0 Protection Violation
0x23
14
DAG0 CPLB Miss
0x26
15
DAG1 Multiple CPLB Hits
0x27
16
DAG1 Misaligned Access
0x24
17
DAG1 Protection Violation
0x23
18
DAG1 CPLB Miss
0x26
19
EXCPT Instruction
поле m
20
Один шаг
0x10
21
Буфер трассировки
0x11
Примечание: объяснение значения исключений см. также в таблице 4-13.
Исключения, возникающие при выполнении обработчика исключения. Когда выполняется обработчик исключения (exception handler), избегайте инструкций, которые генерируют другое исключение. Если произошло исключение при выполнении кода в обработчике исключения, обработчике NMI, по вектору сброса, или в режиме эмуляции, то:
• Инструкция, вызвавшая исключение, не выполняется. Предотвращаются все обратные записи инструкции. • Не будет взято сгенерированное исключение. • Поле EXCAUSE в SEQSTAT обновляется кодом неисправимого события (unrecoverable event code). • Адрес незаконной инструкции сохраняется в RETX. Имейте в виду, что если, к примеру, процессор выполнял бы обработчик NMI, то регистр RETN не был бы обновлен; адрес вызвавшей исключение инструкции всегда сохраняется в RETX.
Чтобы определить, произошло ли исключение во время выполнения обработчика исключения, проверьте в конце обработчика исключения поле SEQSTAT на предмет наличия в нем кода "невосстановимого события" (unrecoverable event, EXCAUSE = 0x25). Если произошло невосстанавливаемое событие, то регистр RETX содержит адрес самой последней инструкции, которая вызвала исключение. Этот механизм не предназначен для восстановления из такой ситуации, только для её детектирования.
Исключения и конвейер. Прерывания и исключения рассматривают инструкции в конвейере по-разному.
• Когда происходит прерывание, то обрываются все инструкции в конвейере. • Когда происходит исключение, то обрываются все инструкции в конвейере, которые находятся после инструкции, вызвавшей исключение. Для исключений ошибок также обрывается и инструкция, вызвавшая исключение.
Из-за того, что исключения, NMI и события эмуляции имеют выделенный регистр возврата, защита адреса возврата не обязательна. Следовательно, инструкции PUSH и POP для исключений, NMI, событий эмуляции не влияют на систему прерывания.
Однако имейте в виду, что инструкции возврата для исключений (RTX, RTN и RTE) делают очистку самого младшего бита (Least Significant Bit, LSB), который в настоящий момент установлен в IPEND.
Отложенная обработка исключения (Deferring Exception Processing). Обработчики исключения обычно являются длинными подпрограммами, потому что они должны отличать исключения друг от друга и для каждого типа исключения предпринимать соответствующее действие. В результате из-за длины подпрограмм может быть так, что система будет находится в подвешенном состоянии (пока не обработается исключение) слишком долго, не давая выполнятся другим прерываниям.
Чтобы избежать ситуации приостановки прерываний, пишите обработчик исключения как обычно, чтобы он мог идентифицировать все случаи исключения, однако отложите обработку на прерывание с низким приоритетом. Чтобы запустить обработчик прерывания с низким приоритетом, используйте инструкцию принудительного запуска прерывания / сброса (Force Interrupt / Reset instruction, RAISE).
Когда обработка исключения откладывается на прерывание с низким уровнем приоритета IVGx, система должна гарантировать, что в IVGx был произведен вход до того, как произошел возврат в код уровня приложения, который привел к исключению. Если произошло отложенное прерывание с приоритетом выше, чем IVGx, то допустимо войти в прерывание с более высоким приоритетом до входа в IVGx.
Пример кода обработчика исключения. В следующем примере кода применяется обработчик исключения с отложенной обработкой.
Листинг 4-7. Подпрограмма обработчика исключения с отложенной обработкой.
/* Определение исключения производится оценкой поля EXCAUSE в регистре SEQSTAT
(сначала в стек супервизора сохраняется содержимое регистров R0, P0, P1
и ASTAT */
[--SP] = R0;
[--SP] = P0;
[--SP] = P1;
[--SP] = ASTAT;
R0 = SEQSTAT;
/* Маскирование содержимого SEQSTAT, в R0 останется только поле EXCAUSE. */
R0 <<= 26;
R0 >>= 26;
/* Используется таблица переходов EVTABLE, jump к событию, на которое
указывает R0 */
P0 = R0;
P1 = _EVTABLE;
P0 = P1 + ( P0 << 1 );
R0 = W [ P0 ] (Z);
P1 = R0;
JUMP (PC + P1);
/* Дальше идет точка входа для события. В этом месте обработка типа исключения
откладывается на самое низкоуровневое прерывание IVG15. Обычно в этом месте
происходит передача параметра. */
_EVENT1:
RAISE 15;
JUMP.S _EXIT;
/* Точка входа для IVG14 */
_EVENT2:
RAISE 14;
JUMP.S _EXIT;
/* Тут могут быть обработки для других событий */
/* По окончании обработчика восстанавливаются R0, P0, P1 и ASTAT,
и происходит возврат. */
_EXIT:
ASTAT = [SP++];
P1 = [SP++];
P0 = [SP++];
R0 = [SP++];
RTX;
_EVTABLE:
.byte2 addr_event1;
.byte2 addr_event2;
...
.byte2 addr_eventN;
/* Таблица переходов EVTABLE содержит 16-битные смещения адреса для каждого
события. С использованием смещений позиция этого кода получается независимой
от места в памяти, и размер таблицы уменьшается.
+--------------+
| addr_event1 | _EVTABLE
+--------------+
| addr_event2 | _EVTABLE + 2
+--------------+
| . . . |
+--------------+
| addr_eventN | _EVTABLE + 2N
+--------------+
*/
Пример кода для подпрограммы, декодирующей исключения. Следующий код показывает шаблон подпрограммы низкоуровневого прерывания (ISR), выполняющей отложенную обработку (сюда происходит переход из обработчика исключения, описанного выше).
Листинг 4-8. ISR, обрабатывающий исключения (привязан к группе прерываний IVG15).
/* В этом месте разместите тело обработчика исключения: */
...
RETI = [SP++]; /* Выборка (pop) адреса возврата из стека. */
RTI; /* Возврат из прерывания. */