|
Обычная переменная для ISR и volatile для всех остальных, как лучше реализовать? |
|
|
|
Jan 26 2009, 11:55
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(sonycman @ Jan 26 2009, 14:38)  Код do
{
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) new_value = sys_tick; }
while ((new_value - old_value) < mksec); Пусть sys_tick volatile, проехали предыдущий вопрос. Если мы говорим конкретно об AVR, то дороговатая операция получается. Я бы для такого случая завел бы какой-нить байтовый кеш таймерок. Тогда не надо атомарного доступа. Портируемость AVR->ARM стремится к нулю
|
|
|
|
|
Jan 26 2009, 14:40
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(sonycman @ Jan 26 2009, 18:02)  Тогда страдает или разрешение таймера, или величина макс. выдержки. Я применял это там, где тик был медленный = 1мс. В таких условиях в мониторе событий крутился опрос "быстрого" однобайтового таймера и этот тик (в предельном случае-вместе с вызовом обработчика) генерился там же. Т.е. преследовались цели: разгрузить прерывание, минимизировать джиттер прерывания от таймера из-за частых запретов/разрешений, разделить быстрые и медленные процессы. Понятно, что на ARM "мельчить" объектами меньше чем 32 бита не только не полезно, но и вредно. И никаких извратов там не надо. И, следуя вполне нормальному желанию портировать код, завел тип timer_t - размерностью какой надо в конкретном случае. Извиняюсь если написал много банальщины. Цитата(Сергей Борщ @ Jan 26 2009, 17:24)  В варианте для AVR считывать sys_tick в цикле и сравнивать с предыдущим значением. По остальным тезисам - согласен, а тут - слишком искусственная ситуация, ибо такие циклы встречаются довольно редко. Согласитесь, чаще встречается конструкция типа Код void action (void)
{ static timer_t local_timer =0; timer_t tmp; tmp = get_tick(); if ((local_timer - tmp) < My_Time_To_DO) return; local_timer = tmp; Do_Be_Do_Be_Do();
**********
return; }
|
|
|
|
|
Jan 26 2009, 15:20
|

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

|
Цитата(_Pasha @ Jan 26 2009, 16:40)  Согласитесь, чаще встречается конструкция типа Да. Так вот Код timer_t get_tick() { timer_t Tmp1 = sys_tick; timer_t Tmp2 = sys_tick; while((Tmp2 >> 8) != (Tmp1 >> 8)) { Tmp1 = Tmp2; Tmp2 = sys_tick } return Tmp2; }
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jan 26 2009, 17:45
|

Профессионал
    
Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357

|
Цитата(Сергей Борщ @ Jan 26 2009, 11:20)  Вообще-то это требуется всегда, когда переменная изменяется неизвестным компилятору образом, например в прерывании, другом потоке или аппаратно отражает состояние внешних по отношению к ядру устройств. А также если глобальная переменная используется в нескольких функциях. Транслируя каждую функцию по отдельности, компилятор не знает, как изменяется такая переменная. Однако вы же не делаете ее volatile. Такое объявление приводит лишь к тому, что если например она используется в функции дважды, то ее значение будет считываться из памяти каждый раз, а при отсутствии volatile (и наличии оптимизатора) - только раз. Цитата(Сергей Борщ @ Jan 26 2009, 11:20)  Зато _вы_ можете сделать предположение за компилятор.  . Может он. Чтобы не мог - существует volatile. Если в конкретном случае без volatile вдруг не сделал, то при малейшем изменении исходника или версии компилятора сможет сделать и вот вам граблями в лоб - получите. Ну например, в прерывании таймера инкрементируется некая переменная, а в прерывании какого-нибудь передатчика ее значение куда-то передается. Что может знать компилятор о ее содержимом? И "малейшего" изменения исходников (а тем более версии компилятора) недостаточно для изменения ее поведения. Нужно "существенное" изменение, например, если мы попытаемся ввести какую-нибудь паузу, как написал ниже sonycman - но паузы и задержки это и есть то, для чего придуман volatile. Но с другой стороны, введение задержек в микропроцессорной системе таким способом - явный признак дурного стиля, это снижает производительность системы. Для задержек как раз и существуют таймеры.
|
|
|
|
|
Jan 26 2009, 18:56
|

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

|
Цитата(777777 @ Jan 26 2009, 21:45)  Но с другой стороны, введение задержек в микропроцессорной системе таким способом - явный признак дурного стиля, это снижает производительность системы. Для задержек как раз и существуют таймеры. Это был просто пример. Естественно в реальной системе мёртво стопорить процессор при ожидании глупо. Хотя иногда и необходимо, и такие функции существуют. Но вернёмся к теме - вы всё же считаете, что volatile не обязателен для случая с инкрементом счётчика в ISR и чтения его в основной программе?
|
|
|
|
|
Jan 26 2009, 19:18
|

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

|
Цитата(777777 @ Jan 26 2009, 19:45)  А также если глобальная переменная используется в нескольких функциях. Транслируя каждую функцию по отдельности, компилятор не знает, как изменяется такая переменная. Знает. Почитайте что такое точки последовательности, побочные эффекты. Функция исполняется от начала и до конца. Одна. Компилятор ничего не знает ни о прерываниях, ни о многопоточности. Задача прерывания - обеспечить неизменность состояния среды исполнения (state of the execution environment). Все, что изменяет это состояние является побочными эффектами (side-effects). Одним из побочных эффектов является обращение к volatile-переменной. Прочтите стандарт, чтобы не писать глупости. И компилятор имеет право встроить функцию. Так что "Транслируя каждую функцию по отдельности" бывает далеко не всегда.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|