PIC32 – прерывания

Visits: 2262


Регистры прерываний

INTCON – регистр управления

bit 16 SS0: Single Vector Shadow Register Set bit
1 = Single vector is presented with a shadow register set
0 = Single vector is not presented with a shadow register set

bit 12 MVEC: Бит конфигурации Мультиверторного режима

1 = Контроллер прерывания сконфигурирован для Мультивекторного режима
0 = контроллер прерывания сконфигурирован для Одновекторного режима

bit 10-8 TPC<2:0>: Биты управления прерыванием от таймера приближения
111 = Interrupts of group priority 7 or lower start the Interrupt Proximity timer
110 = Interrupts of group priority 6 or lower start the Interrupt Proximity timer
101 = Interrupts of group priority 5 or lower start the Interrupt Proximity timer
100 = Interrupts of group priority 4 or lower start the Interrupt Proximity timer
011 = Interrupts of group priority 3 or lower start the Interrupt Proximity timer
010 = Interrupts of group priority 2 or lower start the Interrupt Proximity timer
001 = Interrupts of group priority 1 start the Interrupt Proximity timer
000 = Прерывания от таймера приближения отключено.

bit 4 INT4EP:,bit 3 INT3EP:,bit 2 INT2EP:,bit 1 INT1EP:,bit 0 INT0EP: – биты управления полярность сигналов прерывания на внешних входах.

1 = по нарастанию
0 = по срезу

INTSTAT – регистр состояния прерывай

bit 10-8 RIPL<2:0>: приоритет прерывания предоставленный CPU

bit 5-0 VEC<5:0>: вектор прерывания предоставленный CPU

TPTMR – регистр установки времени таймера приближения

bit 31-0 TPTMR<31:0>: Биты времени перезагрузки таймера приближения. Величина времени перезагрузки Используется величина таймера приближения как значение перезагрузки, когда таймер приближения срабатывает по событию прерывания.

IFSx – регистры статуса флаги прерываний

IECx – регистры управления разрешения прерываний

IPCx – регистры управления приоритетом прерываний

bit 28-26 IP0x<2:0>: биты приоритет прерываний, до 7 уровней прерываний. В диапазоне от 1 (самый низкий) до 7 (самый высокий) 0 – прерывание отключено.
bit 25-24 IS0x<1:0>: биты субприоритета прерываний, 4 подуровня прерывай на каждом уровне прерывания.


На этой странице опишем упрощенное понятие системы прерываний которое позволит начать использовать прерывание в PIC32.

Прерывание можно описать с использование макроса __ISR. прерывание описывается как функция которая ничего не принимает и никаких параметров не возвращает

void __ISR(вектор прерывания (Vector Number), ipln*) Название_прерывания(void)
{
      /*Обработка прерывания*/
}

* n – приоритет прерывания (n=1-7);

Контроллер может работать в одновекторном режиме и в мультивекторном. В одновекторном режиме все прерывания выполняются через один адрес, этот режим аналогичен для серий PIC16 или PIV18 (с одним приоритетом). В одновекторном режиме прерывания необходимо строить аналогично младшим версиям. В много векторном для каждого прерывания выделяется свой адрес. По включению питания контроллер работает в одновекторном режиме.

Для управления прерываниями можно использовать функции библиотеки периферии или выполнить “вручную”.

Настроим работу таймера Т1 для работы с прерываниями в одно векторном режиме.

// настройка работы таймера
    T1CON =  0b001000000000110000;
/*             | |||   | || |+--- TCS:выбор источника тактовых импульсов 0 = внутренний генератор
 *             | |||   | || +---- TSYNC:управление синхронизацией 0 - игнорируется, так как тактируется от внутреннего генератора
 *             | |||   | ++------ TCKPS<1:0>: предделитель 11 = 1:256
 *             | |||   +--------- TGATE: Врата управления таймером отключен
 *             | ||+------------- TWIP: Флаг индикации режима записи в таймер TMR1
 *             | |+-------------- TWDIS: Управление компенсационной записью 0 - разрешена (1 = Запись в TMR1 игнорируются до ожидании операции записи завершает)
 *             | +--------------- SIDL: управление работой в режиме ожидания. 0 - работать всегда
 *             +----------------- ON: Включить таймер
 */
    PR1 = 0xFFFF;   // период работы

    IFS0bits.T1IF=0;    // сбросить флаг прерывания.
    IEC0bits.T1IE=1;    // разрешить прерывания от Т1
    IPC1bits.T1IP=4;    // приоритет 4
    IPC1bits.T1IS=0;    // субприоритет уровень 0

Для включения глобального прерывания используем функцию  __builtin_enable_interrupts();

Функция прерывания от таймера Т1 будет включать и выключать светодиод на порту B.

void __ISR(0, ipl4) T1Interrupt (void)
{
/*Обработка прерывания*/
     LATBINV = LED01;//инвертирование состояния светодиода
     IFS0bits.T1IF=0;//сброс флага
}
void __ISR(0, ipl4) T1Interrupt (void) 
           |     +---------------------- 4 это приоритет который настроен в IPC1bits.T1IP=4;
           +---------------------------- в одновектором режиме номер вектора всегда 0

Тестовая программа для проверки прерываний можно скачать: 

Настройку таймера можно выполнить с использованием функций библиотеки периферии?

    OpenTimer1(T1_ON | T1_SOURCE_INT | T1_PS_1_256, 0xFFFF); //
    ConfigIntTimer1(T1_INT_ON | T1_INT_PRIOR_4 | T1_INT_SUB_PRIOR_0);

Но более приемлем мультивекторный режим, в таком режиме микроконтроллер может полностью использовать свои возможности.

Для включения мультивекторного режима необходимо установить бит INTCONbits.MVEC=1;  // мультивекторный режим.

В этом режиме необходимо в описании функции прерывания указать номер вектора (Vector Number) прерывания для таймера Т1, он равен 4 (смотри описание).

void __ISR(4, ipl4) T1Interrupt (void)

или используя макросы периферийной библиотеки

void __ISR(_TIMER_1_VECTOR, ipl4) T1Interrupt (void)

Пример для тестирования 


Функции контроля и управления прерываниями (встроенные функции в компилятор)

unsigned int __builtin_get_isr_state(void)   // получить состояние прерываний, получить текущий уровень приоритета прерывания и прерывания Enable бита.
void __builtin_set_isr_state(unsigned int)   // изменить состояние прерываний, установите уровень приоритета прерывания и прерывания биты разрешения, используя значение, полученное из __builtin_get_isr_state().
void __builtin_disable_interrupts(void)     // запретить прерывания
void __builtin_enable_interrupts(void)     // разрешить прерывания


Создание функции прерывания

Атрибуты прерывания

общее написание выглядит так:

__attribute__((interrupt([IPLn[SRS|SOFT|AUTO]])))   где n – должен быть в диапазоне 1-7, это число указывает приоритет прерывания, 7-самый высокий, 1 – самый низкий.

Используйте атрибут, чтобы указать, что указанная функция является обработчиком прерывания.
Компилятор генерирует функцию, которая может использоваться в обработчике прерывания, когда этот атрибут присутствует. Сгенерированный код сохраняет контекст, либо используя конфигурацию теневого регистра (SRS) или, используя созданные программные инструкции (SOFT) которые должен описать пользователь самостоятельно для сохранения и восстановления контекста, т.е. места откуда был переход из прерывания и куда должен вернуться процессор после прерывания.

void __attribute__((interrupt(IPL7SRS))) bambam (void); где bambam – название функции прерывания.

Многие PIC32 устройства позволяют указать, с помощью битов конфигурации уровень приоритета который будет использовать теневой регистров (например, #pragma config FSRSSEL=PRIORITY_7). Необходимо обратиться к спецификации конкретного устройства, чтобы определить, поддерживает ваш ли IC32 эту функцию (PIC32MX795F512H поддерживает).

Мы должны указать, какой механизм контекста необходимо использовать для каждого обработчика прерываний. Компилятор может использовать при возможности аппаратный  механизм Теневого регистра для для такого вида: IPLnSRS; где IPLn – задаем уровень прерывания (n=1-7), SRS – указывает на использование теневого регистра это вариант является самым быстрым.

Если нам необходимо чтобы компилятор создал программный код для использования механизма сохранения контекста, то вот для этого необходимом использовать написание IPLnSOFT; где SOFT – говорит, что вся процедура будет создана компилятором на программном уровне.

PIC32 может иметь до 8 комплектов регистров (1 стандартный и 7 комплектов теневых регистров) что значит, что есть достаточно теневых регистров для каждого прерывания и уровня приоритета. Таким образом, мы должны (и можем) использовать спецификатор IPLnSRS для каждого прерывания которое нам необходимо организовать.

Компилятор также поддерживает спецификатор IPLnAUTO, который позволяет использовать значение программы во время выполнения чтобы определить, следует ли использовать программное обеспечение или SRS. Компилятор по умолчанию использует IPLnAUTO, когда спецификатор IPL, в атрибуте прерывания, опущен.
Для устройств, которые не поддерживают теневой набор регистров для сохранения контекста в прерываниях, необходимо использование
IPLnSOFT для всех обработчиков прерываний.

Обратите внимание, что: SRS имеет наименьшую задержку выполнения и SOFT характеризуется более длинной задержкой из-за сохранения регистров в стеке. AUTO добавляет несколько циклов для проверки следует использовать SRS или SOFT.


Описание функции прерывания через Interrupt Pragma.

Такое описание используется для совместимости с ранее написанными программами, например:

#pragma interrupt foo IPL4SOFT
// затем сама функция
void foo (void)

эквивалентно, если мы опишем функцию так

void __attribute__ ((interrupt(IPL4SOFT))) foo (void)

Теперь ближе к практике. Удобнее использовать макросы для написания функций прерываний, для этого (чтобы пока неиспользовать библиотеки) необходимо в начале программы сделать определение

#define __ISR(v,ipl) __attribute__((vector(v), interrupt(ipl), nomips16)) //описание функции прерывания

в самой программе описание прерывания, например для таймера 1, будет выглядеть так (для мультивекторного режима)

__ISR(4,ipl4soft) T1Interrupt (void)
{
   IFS0bits.T1IF = 0;               // сброс флага переполнения
   LATBINV = 0b0001000000000000;    // мигание светодиода
}

Проект для тестирования

Обратите внимания, для включения прерываний используется макрос __builtin_enable_interrupts();  (разрешить прерывания) и режим мультивекторный, который включается установкой бита INTCONbits.MVEC=1.


Выводы.

В одновектороном режиме необходимо использовать SOFT.

В многовектороном режиме, для типа SRS необходимо использовать тот уровень который задан в регистрах конфигурации

#pragma config FSRSSEL = PRIORITY_7      // SRS Select - SRS Priority 7

Для приведенной записи SRS или AUTO можно использовать только на 7 уровне приоритета, для остальных уровней необходимо использовать SOFT.


продолжение следует…

Поделись этим!