Контроллер прерываний
Материал из MIK32 микроконтроллер
Данная статья рассматривает настройку контроллера прерываний. Ниже даны основные моменты, на которые следует обратить внимание, далее дан пример с обработкой прерывания от 32-х разрядного таймера.
Важный момент
Контроллер прерываний не является векторным, при возникновении прерывания из любого источника он всегда вызовет один обработчик.
Обратите внимание
Для работы контроллера прерываний требуется следующее:
- Включить тактирование EPIC на шине APB_M (в блоке Power Manager);
- Разрешить прерывания по необходимым линиям в блоке EPIC (контроллер прерываний);
- Разрешить аппаратные прерывания (установить соответствующие регистры состояния в ядре).
В периферийных блоках также требуется разрешить прерывания по определенным событиям.
Пример обработки прерывания:
#include <mcu32_memory_map.h> #include <pad_config.h> #include <gpio.h> #include <power_manager.h> #include <timer32.h> #include <epic.h> #include <csr.h> #include <scr1_csr_encoding.h> void trap_handler() { if (EPIC->STATUS & (1 << EPIC_TIMER32_0_INDEX)) { //Проверка источника прерывания GPIO_1->OUTPUT ^= 1 << 13; //Установка значения выходного регистра // TIMER32_0->Enable = TIMER32_RESET_VALUE_M | TIMER32_ENABLE_M; TIMER32_0->IntClear = TIMER32_INT_OVERFLOW_M; //Сброс флага прерывания таймера EPIC->CLEAR = 1 << EPIC_TIMER32_0_INDEX; //Сброс флага прерывания линии таймера } } void EnableInterrupts() { set_csr(mstatus, MSTATUS_MIE); set_csr(mie, MIE_MEIE); } void DisableInterrupts() { clear_csr(mie, MIE_MEIE); } int main() { DisableInterrupts(); //Включаем тактирование необходимых блоков PM->CLK_APB_P_SET = PM_CLOCK_GPIO_1_M; PM->CLK_APB_M_SET = PM_CLOCK_PAD_CONFIG_M | PM_CLOCK_WU_M | PM_CLOCK_PM_M | PM_CLOCK_TIMER32_0_M | PM_CLOCK_EPIC_M; for (volatile int i = 0; i < 10; i++); //Настройка вывода (светодиода) PAD_CONFIG->PORT_1_CFG = 1 << (13 << 1); //Установка режима 01 (GPIO) вывода 13 GPIO_1->DIRECTION_OUT = 1 << 13; GPIO_1->OUTPUT = 0; //Установка значения выходного регистра //Остановка таймера и сброс настроек до стандартных TIMER32_0->Enable = TIMER32_RESET_VALUE_M; TIMER32_0->IntMask = 0; TIMER32_0->IntClear = 0x3FF; TIMER32_0->Control = 0; //Настройка максимального значения счетчика //и включение прерывания на переполнение TIMER32_0->Top = 32000000u; TIMER32_0->IntMask = TIMER32_INT_OVERFLOW_M; //Сброс настроек контроллера прерываний //и включение линии прерываний таймера EPIC->MASK_CLEAR = 0xFFFF; EPIC->CLEAR = 0xFFFF; //Сброс флагов прерываний EPIC->MASK_SET = 1 << EPIC_TIMER32_0_INDEX; //Разрешение прерываний и запуск таймера EnableInterrupts(); TIMER32_0->Enable = TIMER32_ENABLE_M; for (;;); // while (1) { // GPIO_1->OUTPUT = (1 << 13) & ~GPIO_1->OUTPUT; //Цикл зависит от скорости выполнения программы // for (volatile int i = 0; i < 500000; i++); //При выполнении из ОЗУ работает быстрее таймера // } }