Директива #pragma interrupt должна непосредственно предшествовать реализации функции, например:
#pragma interrupt void SPORT0_Receive_Handler(int sig);
void SPORT0_Receive_Handler(int sig)
{
int a;
...
return;
}
Эта директива указывает компилятору на то, что функция должна быть скомпилирована не как подпрограмма, а как обработчик прерывания. В частности, это приводит к тому, что все регистры (в том числе Scratch-регистры) должны быть сохранены и восстановлены при выходе из обработчика – это отличие от обычной процедуры. Выход из процедуры по rti, а не как из С-функции по jump.
Эту директиву необходимо использовать только с диспетчерами, зарегистрированными функциями interruptss() и signalss().
Особенности организации доступа к данным в С-модулях в программах с прерываниями
При описании данных, которые могут модифицироваться в обработчиках прерываний, обычно используется модификатор volatile, который сообщает компилятору, что значение этой переменной может изменяться в любой момент времени внешним (по отношению к исполняемой в данный момент функции) кодом. Это предотвращает выполнение компилятором обычных оптимизаций. Например
int a, b, c, d;
...
c = x+a+b;
... // код не меняющий ни x, ни a
d = x+a;
Здесь (x+a) - общее подвыражение, и при вычислении переменной с компилятор сохраняет его в каком-либо временном регистре, чтобы затем подставить при вычислении переменной d, поскольку "видит", что между этими двумя выражениями x не изменялся. Если же если переменная x объявлена как volatile, то компилятор скорее всего не будет его оптимизировать.
Другой пример.
while (x<5) {
// что-то не меняющее x
};
Здесь очевидно, что условие цикла, не будь x – volatile, не меняется. То есть его можно "соптимизировать", вынеся лишние вычисления из цикла
if (x<5)
while(1) {
//....
}
Если же x – volatile, то компилятор такой оптимизации делать не будет.
Исходный текст программы | Код, сгенерированный компилятором |
int x=1; int y=2; int z=3; int a,b; ... a = x+y+z; b = x+y; | r2=6; r12=3; dm(_a)=r2; dm(_b)=r12; |
volatile int x=1; int y=2; int z=3; int a,b; ... a = x+y+z; b = x+y; | r2=dm(_x.0); r12=5; r2=r2+r12; dm(_a)=r2; r12=dm(_x.0); r8=2; r12=r12+r8; dm(_b)=r12; |
Отсутствие модификатора volatile в некоторых случаях может привести к неверной работе программы. С другой стороны, излишне частое его использование не позволит компилятору выполнить эффективную оптимизацию кода.