Контроллер прерываний: различия между версиями
Материал из MIK32 микроконтроллер
Sh-sergey (обсуждение | вклад) (init) |
Sh-sergey (обсуждение | вклад) Нет описания правки |
||
(не показана 1 промежуточная версия этого же участника) | |||
Строка 15: | Строка 15: | ||
Пример обработки прерывания: | Пример обработки прерывания: | ||
<syntaxhighlight lang="c++"> | |||
#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++); //При выполнении из ОЗУ работает быстрее таймера | |||
// } | |||
} | |||
</syntaxhighlight> |
Текущая версия от 12:17, 5 апреля 2022
Данная статья рассматривает настройку контроллера прерываний. Ниже даны основные моменты, на которые следует обратить внимание, далее дан пример с обработкой прерывания от 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++); //При выполнении из ОЗУ работает быстрее таймера
// }
}