|
Обычная переменная для ISR и volatile для всех остальных, как лучше реализовать? |
|
|
|
Jan 24 2009, 15:32
|

Любитель
    
Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695

|
Что-то вот задумался над одной мелочью, в принципе. Есть переменная таймера, которая объявлена как volatile, так как модифицируется в обработчике прерывания. Всё бы хорошо, да только хотелось бы, чтобы эта переменная была volatile для всех, кроме самого обработчика прерываний, так как лишние сохранения/загрузки в нём - это совершенно лишнее.  Есть мысля сделать так: Код union { dword isr_timer; volatile dword timer; } и в ISR юзать isr_timer, а в других местах - просто timer. Что скажете?
|
|
|
|
|
Jan 24 2009, 16:43
|
Участник

Группа: Свой
Сообщений: 46
Регистрация: 4-02-05
Из: Москва
Пользователь №: 2 430

|
ISR сделай в отдельном файле и используй как dword timer;
а в основном объяви как extern volatile dword timer;
Сообщение отредактировал kimstik - Jan 24 2009, 16:54
|
|
|
|
|
Jan 24 2009, 19:39
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(singlskv @ Jan 24 2009, 20:55)  А я вот чего-то совсем не припоминаю из стандарта почему исходный вариант неправильный ? Он не неправильный. Он несколько... некрасивый. Как вы организуете доступ к этому безымянному unionу из другого файла? Вы вынесете его в заголовочный файл с extern, и при этом сделаете видимым не-volatile пременную. Никакой гарантии, что случайно не используете эту переменную вне прерывания. Если есть возможность железно ограничить область видимости не-volatile переменной обработчиком прерывания, сделав ее локальной - почему не использовать ее? Цитата(sonycman @ Jan 24 2009, 19:47)  А я почему-то подумал, что extern должен быть с точно таким-же типом, что и оригинальная переменная... Думаю, что он может накладывать дополнительные ограничения (volatile, const) на переменную, но не снимать их. Искать в стандарте лень, никогда не использовал такой финт.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jan 24 2009, 19:51
|

Любитель
    
Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695

|
Цитата(Сергей Борщ @ Jan 24 2009, 22:33)  Заведите внутри обработчика прерывания локальную переменную, считайте в нее timer и работайте дальше с ней. В конце, если надо, сохраните локальную переменную обратно в timer. Зачем какие-то велосипеды с выносом в другой файл? Этот счётчик необходим для класса таймеров рассредоточенных по всему проекту. Поэтому его вынос обязателен. Последовал совету kimstik. Накладывание доп. ограничений (volatile) на внешнюю переменную для внутренних нужд - это прикольно  Можно ещё и const добавить для подстраховки...
|
|
|
|
|
Jan 24 2009, 19:53
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(Сергей Борщ @ Jan 24 2009, 22:39)  Он не неправильный. Он несколько... некрасивый. Как вы организуете доступ к этому безымянному unionу из другого файла? Вы вынесете его в заголовочный файл с extern, и при этом сделаете видимым не-volatile пременную. Никакой гарантии, что случайно не используете эту переменную вне прерывания. Если есть возможность железно ограничить область видимости не-volatile переменной обработчиком прерывания, сделав ее локальной - почему не использовать ее? Безымянный глобальный union это вообще не хорошо, компилятор должен варнинг давать, поэтому конечно нужно дать имя ему. Ну а если уже дали имя и напутали к какой переменной обращаться, то сами себе злобные Буратины... А сам бы я тоже локальную просто завел... чисто по привычке.
|
|
|
|
|
Jan 24 2009, 19:55
|

Любитель
    
Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695

|
Цитата(singlskv @ Jan 24 2009, 23:53)  Безымянный глобальный union это вообще не хорошо, компилятор должен варнинг давать, поэтому конечно нужно дать имя ему. Компилер заставил поставить static. А имя - зачем оно? Лишняя писанина только... Объединение не должно быть в области видимости снаружи. Оно только для нужд прерывания. А снаружи - только volatile dword... Да ладно, это не актуально более
|
|
|
|
|
Jan 24 2009, 20:39
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Цитата(sonycman @ Jan 24 2009, 19:47)  А я почему-то подумал, что extern должен быть с точно таким-же типом, что и оригинальная переменная...  Ну вообще говоря "желательно". Прокатить такое может только если в файл с обработчиком ISR не включать тот h-файл, в котором объявлено переменную для остальных - я же предпочитаю объявлеия включать везде для проверки (если вдруг поменяю в .h uint16_t на uint32_t, а в .c забуду - компилятор выругатся. Но тогда vv.h Код extern volatile unsigned u; vv.c Код #include <vv.h> unsigned u; Компиляция: Код vv.c:2: error: conflicting type qualifiers for 'u' ./vv.h:1: error: previous declaration of 'u' was here Я как правило кеширую переменную в обработчике прерывания во веменную и сохраняю при выходе. Можно и так, набросал вот  Код template <typename T, volatile T& var> class cache_volatile { public: cache_volatile() : t(var) {} ~cache_volatile() { var = t; }
T t; };
volatile uint8_t timer;
ISR(TIMER0_OVF_vect) { cache_volatile<uint8_t, timer> tim; if( --tim.t == 0 ) { tim.t = 127; } if( PINB & 0x02) return; // тут тоже запишется назад изменённое значение if( tim.t & 0x01 ) PINB |= 0x01; } Код __vector_9: push __zero_reg__ push __tmp_reg__ in __tmp_reg__,__SREG__ push __tmp_reg__ clr __zero_reg__ push r24
lds r24,timer subi r24,lo8(-(-1)) brne .L2 ldi r24,lo8(127) .L2: sbic 54-0x20,1 rjmp .L4 sbrc r24,0 sbi 54-0x20,0 .L4: sts timer,r24
pop r24 pop __tmp_reg__ out __SREG__,__tmp_reg__ pop __tmp_reg__ pop __zero_reg__ reti
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Jan 24 2009, 22:12
|

Любитель
    
Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695

|
Хм, спасибо! Если будут проблемы с extern, то придётся именно так и поступать. Эх, пора мне, наверное, шаблоны поизучать - а то аж искры из глаз, пока силился понять, что там вы с ними "замутили" Можно, конечно, и без них обойтись...
|
|
|
|
|
Jan 25 2009, 11:43
|
Участник

Группа: Свой
Сообщений: 46
Регистрация: 4-02-05
Из: Москва
Пользователь №: 2 430

|
Я стараюсь union реже использовать - это одна из самых непереносимых и компилерозависимых вещей. Не все компилеры понимают безымяный union. Длинные бестолковые имена. Куча не всегда понятных переменных. А то что в хедер для проверки не вставить объявления - это цена вопроса. Вы же сами просили решения(хака)? Значит вам за него и отвечать.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|