MPLAB® C30 COMPILER
Каждый источник прерывания может быть индивидуально разрешен или запрещен. Бит разрешения прерывания для каждого 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);
}
ПРИМЕР 9-9: ПРИМЕНЕНИЕ VOLATILE ASM
Для предотвращения удаления, перемещения или объединения asm инструкций компилятором при оптимизации нужно указать ключевое слово volatile после asm Например:
#define disi(n) \ asm volatile ("disi #%0" \ : /* нет выходов */ \
: "i" (n))
В этом случае ограничение буквой “i” обозначает непосредственный операнд, как того требует инструкция DISI.
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.