[an error occurred while processing this directive]
[an error occurred while processing this directive]
|
Допустим у Вас есть обработчик прерывания
void my_interrupt( void), из которого Вам нужно вывалиться в функцию
void my_fun( void);
Можно сделать так :
void my_fun( void) {
...
}
void my_interrupt( void) interrupt 1 {
...
// а здесь делаем вываливание
#pragma asm
MOV A,SP ; берем указатель текущего положения стека
; в нем сверху лежит то, что пушировалось в стек
; а затем 2 байта - адрес,откуда ввалились в прерывание
; допустим, у меня пушируется только 2 байта : PUSH ACC и PUSH PSW
; это надо в листинге подсмотреть
DEC A
DEC A
; добрались до адреса точки возврата
MOV R0,A ; подменим этот адрес адресом нашей функции
MOV @R0,#HIGH my_fun
DEC A
MOV R0,A
MOV @R0,#LOW my_fun
#pragma endasm
}
после подмены адреса возврата адресом функции, выход будет осуществляться прямо на функцию.
Но, я поддерживаю коллег, что такими вещами увлекаться не стОит :
1) Надо вручную подсмотреть, сколько PUSH-ей делает компилятор при входе в прерывание (чтобы добраться до адреса возврата). Если после модификации обработчика изменится число PUSH-ей, то надо будет переделывать доступ к адресу возврата - добавить или убрать DEC A.
Т. е. надо все время следить!
2) Линкер не сможет корректно посчитать адреса для локальных переменных в Вашей функции my_fun(). Как выход - делать холостые вызовы этой функции из тех мест, где разрешены прерывания и где может быть вызвана эта функция. Что-то типа
if( 0) my_fun() ;
Короче, столько гемороя, что заниматься этим не стОит.
E-mail: info@telesys.ru