Запрет/разрешение прерываний. Инструкция DISI. Разрешение прерываний. Использование инструкции DISI

Страницы работы

Содержание работы

MPLAB® C30 COMPILER

8.8 ЗАПРЕТ/РАЗРЕШЕНИЕПРЕРЫВАНИЙ

Каждый источник прерывания может быть индивидуально разрешен или запрещен. Бит разрешения прерывания для каждого IRQ находится в соответствующем регистре Управления Разрешением Прерывания (IECn). Установка бита разрешения прерывания в единицу (1)  разрешает соответствующее прерывание, сброс  бита разрешения прерывания в ноль (0) это прерывание запрещает. После сброса контроллера все биты разрешения прерываний сброшены в ноль. Кроме того, процессор имеет инструкцию запрещения прерывания (DISI), запрещающую все прерывания на определенное количество циклов инструкции.

Примечание: Исключения, например исключение ошибки адреса, запретить нельзя. Запретить можно только IRQs.

Инструкция DISI может использоваться в C программе как ассемблерная вставка. Например, ассемблерная вставка:

__asm__ volatile ("disi #16"); встроит инструкцию DISI в ту точку программы, где эта строка указана. Использование инструкции DISI в таком виде неудобно, поскольку программист не всегда знает, как компилятор транслирует С-код в машинные инструкции, отчего бывает трудно решить, сколько циклов определить для команды DISI. Эту неопределенность можно обойти, заключив критическую секцию в скобки инструкциями DISI, первая из которых устанавливает счетчик командных циклов в максимум, а вторая сбрасывает счетчик в ноль. Например,

__asm__ volatile("disi #0x3FFF"); /* запрет прерываний */

/* ... защищённый C-код ... */

__asm__ volatile("disi #0x0000"); /* разрешение прерываний */

Разрешение прерываний можно выполнить непосредственной записью в регистр DISICNT. Регистр DISICNT может быть изменен только после инструкции DISI и только если значение регистра DISICNT не равно нулю.

__asm__ volatile("disi #0x3FFF"); /* запрет прерываний */

/* ... защищённый C-код ... */

DISICNT = 0x0000;                   /* разрешение прерываний */

Некоторые приложения требуют запрета и 7го уровня прерывания. Это может быть выполнено только модификацией поля COROCON IPL. Для безопасного изменения значения IPL в файлах поддержки имеются макросы:

SET_CPU_IPL(ipl)

SET_AND_SAVE_CPU_IPL(saved_to, ipl)  

RESTORE_CPU_IPL(saved_to)

Например, Вы желаете защитить критическую секцию от прерываний. Следующий код установит нужное  значение IPL и, после завершения критической секции, восстановит IPL в прежнее состояние.

void foo(void) {     int current_cpu_ipl;

      SET_AND_SAVE_CPU_IPL(current_cpu_ipl,7); /* запрет прерываний */

    /* здесь защищенный Си-код*/

   RESTORE_CPU_IPL(current_cpu_ipl);

}

113  MPLAB® C30 COMPILER

ПРИМЕР 9-9:  ПРИМЕНЕНИЕ VOLATILE ASM 

Для предотвращения удаления, перемещения или объединения asm инструкций компилятором при оптимизации нужно указать ключевое слово volatile после asm Например:

#define disi(n)           \ asm volatile ("disi #%0"  \ : /* нет выходов */       \

: "i" (n))

В этом случае ограничение буквой “i” обозначает непосредственный операнд, как того требует инструкция DISI. 

                                                                                                                                        125

Похожие материалы

Информация о работе