Перейти к содержанию
    

Замена обработчика прерывания в WinAVR

Нужно использовать различные обработчики прерывания в зависимости от случая. Например в начале программы

обработчик_пр = функция 1

ISR(INT1_vect)
{
обработчик_пр
}

а затем где-то по далее необходимо заменить его на

обработчик_пр = функция 2

Как это грамотно сделать в WinAVR?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

ИМХО никак, т.к. в AVR адреса векторов фиксированые, только в ISR вызывать функцию по условию.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Определить указатель на функцию и поставить его в тело обработчика прерывания. Указателю между делом можно присваивать адреса разных функций. Издержки - команда CALL в теле обработчика прерываний. Зато задержка будет фиксированной и независимой от условий, как в случае switch или if/else.

 

typedef void ( *pxTBFunctionHandler ) ( void );  // объявление типа указателя на функцию

pxTBFunctionHandler pxMBPortCBTimerExpired; // объявление указателя на функцию

pxMBPortCBTimerExpired = (void*)xMBRTUTimerT35Expired; // инициализация указателя



interrupt (TIMERA0_VECTOR) prvvMBTimerIRQHandler( void ) 
{     
    ( void )pxMBPortCBTimerExpired(  ); 
}

Пример безжалостно выдран из FreeModbus.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Определить указатель на функцию и поставить его в тело обработчика прерывания. Указателю между делом можно присваивать адреса разных функций. Издержки - команда CALL в теле обработчика прерываний. Зато задержка будет фиксированной и независимой от условий, как в случае switch или if/else.

+1 :)

Кстати это очень удобно.

//Прототипы функций
void isr1(void);
void isr2(void);
//Указатель на функцию обработчик
void (* cur_isr)(void) = isr1;


void isr1(void)
{
// тело обработчика 1
}

void isr2(void)
{
// тело обработчика 2
}

ISR(INT1_vect)
{
(* cur_isr)();
}

int main(void) 
{
// ля-ля тополя...
...
cur_isr = isr2;
...
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

int main(void) 
{
// ля-ля тополя...
...
cur_isr = isr2;
...
}

Оно, конечно, "само собой разумеется", но cur_isr = isr2; надо в атомарный блок взять.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вызов функции по указателю внутри обработчика ведет к сохранению ВСЕХ регистров в стеке. И восстановлению их при выходе. Не быстрый обработчик получается :(

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Векторизация прерываний. Например, int1

Soft_vectors.S

#include <avr/io.h>
.extern vector_int1
.global INT1_vect
INT1_vect:
  push r30
  in  r30,SREG
  push r30
  push r31
  lds   r30,vector_int1
  lds   r31,(vector_int1+1)
  icall
  pop  r31
  pop  r30
  out  SREG,r30
  pop  r30
  reti

Просто добавьте в проект...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Оно, конечно, "само собой разумеется", но cur_isr = isr2; надо в атомарный блок взять.

А как это сделать?

Вызов функции по указателю внутри обработчика ведет к сохранению ВСЕХ регистров в стеке. И восстановлению их при выходе. Не быстрый обработчик получается

Ну хоть как-то. Не очень хорошо конечно, но что делать. Может есть способ лучше?

Правда, в мем случае, быстродействия достаточно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Просто добавьте в проект...

Ммм... забыл добавить сохранение/восстановление SREG. Исправлено.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Векторизация прерываний. Например, int1

Soft_vectors.S

#include <avr/io.h>
.extern vector_int1
.global INT1_vect
INT1_vect:
  push r30
  in  r30,SREG
  push r30
  push r31
  lds   r30,vector_int1
  lds   r31,(vector_int1+1)
  icall
  pop  r31
  pop  r30
  out  SREG,r30
  pop  r30
  reti

Просто добавьте в проект...

 

Что вам такого плохого сделали люди, что бы советовать им такую гадость???? Компилятор не просто так сохраняет r0, r1 и call-used регстры. Если их не сохранять то программа не будет работать.

 

 

Анатолий.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Компилятор не просто так сохраняет r0, r1 и call-used регстры.

Про r0 r1 - такида, надо добавить, а вот call-used все-же должны отсутствовать по причине того, что обработчики прерываний у нас без параметров. Правильно?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А в своем теле функция никакие регистры не использует?

Даже r24?

ИМХО можно так делать, если вызываемые функции написать на ассемблере (проанализировать листинг) и самостоятельно сохранять регистры.

Кстати Ваш ужас реализуется куда короче и с правильным сохранением:

SYGNAL(SIG_INTERRUPT1){
  asm("icall"::"z"(vector_int1);
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А в своем теле функция никакие регистры не использует?

Понятно. Забыл о том, что из асма сишные функции никогда в жизни не вызывал и что за сохранение call-used отвечает вызывающий. Тогда это действительно проблема.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

в некоторых случаях можно делать перезапись векторов прямо во flash... правда, при условии, что это будет достаточно редко... очень редко :)

а если достаточно всего пары вариантов обработчиков - то можно манипулировать IVSEL, переключая таблицы...

 

все эти варианты - не для любого AVR, разумеется...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Компилятор не просто так сохраняет r0, r1 и call-used регстры.

Последний релиз сохраняет минимум пару лишних регистров. Если интересно, завтра выложу код.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...