В составе VisualDSP имеются удобные библиотечные функции для установки обработчиков прерываний (ISR) с заданным приоритетом - register_handler и register_handler_ex, использование которых можно подключить заголовочным файлом sys/exception.h (сами функции определены в модуле Blackfin\lib\src\libc\crt\reghdlr_s.c). После вызова этих функций в таблице векторов прерываний появляются настроенные адреса (вектора прерываний), указывающие на ISR.
// Файл Blackfin\lib\src\libc\crt\reghdlr_s.c
/*************************************************************************
** Регистрирует обработчик прерывания (ISR) в таблице векторов прерываний (EVT).
** Вернет предыдущее значение, если ISR уже был назначен.
*/
ex_handler_fn register_handler(interrupt_kind kind, ex_handler_fn fn)
{
return register_handler_ex(kind, fn, EX_INT_ENABLE);
}
/*
** Расширенная функция регистрации ISR в EVT.
** Вернет старый ISR.
**
** Если параметр enable == EX_INT_ALWAYS_ENABLE, то установит функцию fn
** (если fn != EX_INT_IGNORE и fn != EX_INT_DISABLE), и затем разрешит
** прерывание через IMASK.
**
** Если fn == EX_INT_iGNORE, то прерывание будет запрещено.
** Если fn == EX_INT_DEFAULT, то из EVT будет удалена ссылка на ISR, и
** прерывание будет запрещено через IMASK.
** Иначе будет установлен новый ISR. Далее,
** если enable == EX_INT_DISABLE, то прерывание будет запрещено через IMASK
** если enable == EX_INT_ENABLE, то прерывание будет разрешено через IMASK
** иначе состояние прерывания останется неизменным.
*/
ex_handler_fn register_handler_ex(interrupt_kind kind, ex_handler_fn fn,
int enable)
{
volatile ex_handler_fn *evt = (volatile ex_handler_fn *)EX_EVENT_VECTOR_TABLE;
ex_handler_fn old;
if (ik_emulation <= kind && kind <= ik_ivg15)
{
old = evt[kind];
if (enable == EX_INT_ALWAYS_ENABLE)
{
// Всегда хочу выйти с разрешенным прерыванием
if (fn != EX_INT_IGNORE && fn != EX_INT_DISABLE)
{
evt[kind] = fn;
}
enable_int(kind);
return old;
}
if (fn == EX_INT_IGNORE)
{
disable_int(kind);
}
else if (fn == EX_INT_DEFAULT)
{
disable_int(kind);
evt[kind] = 0;
}
else
{
if (enable == EX_INT_DISABLE)
{
disable_int(kind);
}
evt[kind] = fn;
if (enable == EX_INT_ENABLE)
{
enable_int(kind);
}
}
return old;
}
return EX_INT_IGNORE;
}
Как можно увидеть из кода функций, отличие register_handler от register_handler_ex состоит только в том, что register_handler является упрощенной - она сама пользуется вызовом функции register_handler_ex. Если при вызове register_handler прерывание на эту запись EVT уже настроено, то ничего не произойдет, иначе будет настроено новое прерывание. У функции register_handler_ex поведение более сложное - можно на выходе запрещать, разрешать прерывания, переназначать обработчик прерывания в EVT.