Контроллер прерываний: различия между версиями

Материал из MIK32 микроконтроллер
Нет описания правки
Нет описания правки
 
Строка 15: Строка 15:
Пример обработки прерывания:
Пример обработки прерывания:


https://disk.yandex.ru/d/tpft5MKx1UggXA
<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>


<syntaxhighlight lang="python" line>


def quick_sort(arr):
void trap_handler() {
less = []
  if (EPIC->STATUS & (1 << EPIC_TIMER32_0_INDEX)) { //Проверка источника прерывания
pivot_list = []
    GPIO_1->OUTPUT ^= 1 << 13; //Установка значения выходного регистра
more = []
    // TIMER32_0->Enable = TIMER32_RESET_VALUE_M | TIMER32_ENABLE_M;
if len(arr) <= 1:
    TIMER32_0->IntClear = TIMER32_INT_OVERFLOW_M; //Сброс флага прерывания таймера
return arr
    EPIC->CLEAR = 1 << EPIC_TIMER32_0_INDEX; //Сброс флага прерывания линии таймера
else:
  }
pass
}


</syntaxhighlight>
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++); //При выполнении из ОЗУ работает быстрее таймера
	// }
}