PhX 0 16 декабря, 2008 Опубликовано 16 декабря, 2008 · Жалоба Нужно использовать различные обработчики прерывания в зависимости от случая. Например в начале программы обработчик_пр = функция 1 ISR(INT1_vect) { обработчик_пр } а затем где-то по далее необходимо заменить его на обработчик_пр = функция 2 Как это грамотно сделать в WinAVR? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
733259 0 16 декабря, 2008 Опубликовано 16 декабря, 2008 · Жалоба ИМХО никак, т.к. в AVR адреса векторов фиксированые, только в ISR вызывать функцию по условию. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrYuran 21 16 декабря, 2008 Опубликовано 16 декабря, 2008 · Жалоба Определить указатель на функцию и поставить его в тело обработчика прерывания. Указателю между делом можно присваивать адреса разных функций. Издержки - команда CALL в теле обработчика прерываний. Зато задержка будет фиксированной и независимой от условий, как в случае switch или if/else. typedef void ( *pxTBFunctionHandler ) ( void ); // объявление типа указателя на функцию pxTBFunctionHandler pxMBPortCBTimerExpired; // объявление указателя на функцию pxMBPortCBTimerExpired = (void*)xMBRTUTimerT35Expired; // инициализация указателя interrupt (TIMERA0_VECTOR) prvvMBTimerIRQHandler( void ) { ( void )pxMBPortCBTimerExpired( ); } Пример безжалостно выдран из FreeModbus. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
PhX 0 16 декабря, 2008 Опубликовано 16 декабря, 2008 · Жалоба Определить указатель на функцию и поставить его в тело обработчика прерывания. Указателю между делом можно присваивать адреса разных функций. Издержки - команда 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; ... } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ReAl 0 16 декабря, 2008 Опубликовано 16 декабря, 2008 · Жалоба int main(void) { // ля-ля тополя... ... cur_isr = isr2; ... } Оно, конечно, "само собой разумеется", но cur_isr = isr2; надо в атомарный блок взять. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Qwertty 0 16 декабря, 2008 Опубликовано 16 декабря, 2008 · Жалоба Вызов функции по указателю внутри обработчика ведет к сохранению ВСЕХ регистров в стеке. И восстановлению их при выходе. Не быстрый обработчик получается :( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 16 декабря, 2008 Опубликовано 16 декабря, 2008 · Жалоба Векторизация прерываний. Например, 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 Просто добавьте в проект... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
PhX 0 16 декабря, 2008 Опубликовано 16 декабря, 2008 · Жалоба Оно, конечно, "само собой разумеется", но cur_isr = isr2; надо в атомарный блок взять. А как это сделать? Вызов функции по указателю внутри обработчика ведет к сохранению ВСЕХ регистров в стеке. И восстановлению их при выходе. Не быстрый обработчик получается Ну хоть как-то. Не очень хорошо конечно, но что делать. Может есть способ лучше? Правда, в мем случае, быстродействия достаточно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 16 декабря, 2008 Опубликовано 16 декабря, 2008 · Жалоба Просто добавьте в проект... Ммм... забыл добавить сохранение/восстановление SREG. Исправлено. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aesok 0 16 декабря, 2008 Опубликовано 16 декабря, 2008 · Жалоба Векторизация прерываний. Например, 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 регстры. Если их не сохранять то программа не будет работать. Анатолий. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 16 декабря, 2008 Опубликовано 16 декабря, 2008 · Жалоба Компилятор не просто так сохраняет r0, r1 и call-used регстры. Про r0 r1 - такида, надо добавить, а вот call-used все-же должны отсутствовать по причине того, что обработчики прерываний у нас без параметров. Правильно? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
733259 0 16 декабря, 2008 Опубликовано 16 декабря, 2008 · Жалоба А в своем теле функция никакие регистры не использует? Даже r24? ИМХО можно так делать, если вызываемые функции написать на ассемблере (проанализировать листинг) и самостоятельно сохранять регистры. Кстати Ваш ужас реализуется куда короче и с правильным сохранением: SYGNAL(SIG_INTERRUPT1){ asm("icall"::"z"(vector_int1); } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 16 декабря, 2008 Опубликовано 16 декабря, 2008 · Жалоба А в своем теле функция никакие регистры не использует? Понятно. Забыл о том, что из асма сишные функции никогда в жизни не вызывал и что за сохранение call-used отвечает вызывающий. Тогда это действительно проблема. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ARV 1 16 декабря, 2008 Опубликовано 16 декабря, 2008 · Жалоба в некоторых случаях можно делать перезапись векторов прямо во flash... правда, при условии, что это будет достаточно редко... очень редко :) а если достаточно всего пары вариантов обработчиков - то можно манипулировать IVSEL, переключая таблицы... все эти варианты - не для любого AVR, разумеется... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 16 декабря, 2008 Опубликовано 16 декабря, 2008 · Жалоба Компилятор не просто так сохраняет r0, r1 и call-used регстры. Последний релиз сохраняет минимум пару лишних регистров. Если интересно, завтра выложу код. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться