реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> volatile не помагает
vROMAv
сообщение Feb 10 2011, 13:16
Сообщение #1





Группа: Участник
Сообщений: 13
Регистрация: 10-02-11
Из: Украина
Пользователь №: 62 859



Есть некоторый код, проблема в том что имеется переменная которая после выхода из прерывания восстанавливает своё значение,
т.е. независимо от volatile компилятор по ходу разместил
переменную event_flag в регистре??!!!
При чём данная ситуация возникает не часто, иногда установленное значение
в прерывании остаётся и после выхода из него((


/////////////////////////////////
// AVR Studio 4.16 Build 628 //
// WinAVR-20090313 //
// Atmega8535 //
/////////////////////////////////

............................
volatile uint8_t event_flags;
#define START 0x01
............................
#define PACK_NOW 0x20

volatile uint8_t macro_rx = 0;

ISR (USART_RX_vect)
{
.............
.............
event_flags |= PACK_NOW;
macro_rx = 1;

//тут PACK_NOW устанавливается, но после выхода из прерывания,
//в event_flags восстанавливается предыдущее значение

}

void main_loop()
{
............
............
if(macro_rx)
{
if(!(event_flags & PACK_NOW))
{
//!!!!!! ОШИБКА !!!!!!
//т.е. macro_rx так и осталась в установленном в прерывании значении
//а event_flags нет!!!
}
}
............
............
}

int main()
{
while (true)
{
main_loop();
}
}


Помогите разобраться в ситуации...
Go to the top of the page
 
+Quote Post
sonycman
сообщение Feb 10 2011, 13:40
Сообщение #2


Любитель
*****

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



Переменная сама по себе никак не может принимать произвольные значения.
Где то идёт запись в эту переменную.

Приведите весь код, работающий с данными volatile переменными.
Go to the top of the page
 
+Quote Post
vROMAv
сообщение Feb 10 2011, 13:49
Сообщение #3





Группа: Участник
Сообщений: 13
Регистрация: 10-02-11
Из: Украина
Пользователь №: 62 859



А где написано что event_flags принимает произвольные значения?
Это не весь код, в начале программы выполняется event_flags |= START;
Затем пошагово выполняю код в avr studio. Иногда натыкаюсь на вышеописанную ситуацию: В прерывании event_flags устанавливается (значение изменяется, видно в окне Watch), а на следующем шаге - выхожу из прерывания и вижу что event_flags снова равна START

Весь код проблематично привести...
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Feb 10 2011, 14:03
Сообщение #4


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Цитата(vROMAv @ Feb 10 2011, 18:49) *
Весь код проблематично привести...

Поиском найдите где эта переменная ещё меняется. И подумайте в каком из этих мест она может затираться.

Очень маловероятно чтобы эта переменная была в регистре. Листинг скажет точно.


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
vROMAv
сообщение Feb 10 2011, 14:15
Сообщение #5





Группа: Участник
Сообщений: 13
Регистрация: 10-02-11
Из: Украина
Пользователь №: 62 859



Я же описал выше: Хожу по коду пошагово по F11,
Попадаю в прерывание USARTa здесь пошагово дохожу до строчек

event_flags |= PACK_NOW;
macro_rx = 1;

Смотрю в окно watch - переменная event_flags равна установленному вначале программы значению (0x01), затем выполняю 2 вышеприведенные строчки и вижу как event_flags стало равно 0x21, а macro_rx стало равным 1, затем снова делаю шаг по F11, и выхожу из прерывания и попадаю в main_loop, В ОКНЕ watch снова event_flags равен 0x01. Т.е. никаких команд после выхода из прерывания не было, а значение поменялось. Это могу объяснить только тем что event_flag была в регистре.

Сообщение отредактировал vROMAv - Feb 10 2011, 14:16
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Feb 10 2011, 14:28
Сообщение #6


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Ходите по асм-коду. Там всё предельно ясно - в регистре или нет.


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
Oldring
сообщение Feb 10 2011, 14:39
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Цитата(vROMAv @ Feb 10 2011, 16:16) *
т.е. независимо от volatile компилятор по ходу разместил
переменную event_flag в регистре??!!!


Включите генерацию компилятором ассемблерного кода и посмотрите, где лежит переменная. Глюки компиляторов тоже встречаются, но реже, чем ошибки программистов.


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Feb 10 2011, 14:50
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



В AVRStudio добавте переменную в Watch и увидите где она расположена.
Go to the top of the page
 
+Quote Post
vROMAv
сообщение Feb 10 2011, 14:56
Сообщение #9





Группа: Участник
Сообщений: 13
Регистрация: 10-02-11
Из: Украина
Пользователь №: 62 859



В файле mega32.map переменной event_flags нет вообще это может чтонибудь значить?
Go to the top of the page
 
+Quote Post
ar__systems
сообщение Feb 10 2011, 16:06
Сообщение #10


self made
****

Группа: Свой
Сообщений: 855
Регистрация: 7-03-09
Из: Toronto, Canada
Пользователь №: 45 795



Дался вам этот волатайл. При чем тут вообще это? Обычная статическая переменная. Ей без разницы, где она лежит, в регистре или в памяти. Если компилятор ее в регистр положил, наверное этот регистр никто больше не используют. 99% процентов что ваша программа кривая.

Сообщение отредактировал ar__systems - Feb 10 2011, 16:07
Go to the top of the page
 
+Quote Post
firstvald
сообщение Feb 10 2011, 16:28
Сообщение #11


Знающий
****

Группа: Свой
Сообщений: 580
Регистрация: 3-06-08
Пользователь №: 38 041



А есть опции оптимизатора? Если есть возможность спуститься на несколклько шагов в оптимизации и посмотреть как будет работать?

Ну второе , что можно посмотреть : по мапу посмотреть какие переменные размещаются до этой переменной, если там есть массив - надо насторожиться и попробовать ему размер увеличить - может он проезжается .
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Feb 10 2011, 17:19
Сообщение #12


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(vROMAv @ Feb 10 2011, 16:16) *
// WinAVR-20090313 //
Есть и посвежее - рекомендую...

Цитата
volatile uint8_t event_flags;
Сделайте 8 байтовых переменных вместо битовых флагов - это самое простое.
Или работайте с битами атомарно (при запрещённых прерываниях, что может быть более накладно).

Цитата(ar__systems @ Feb 10 2011, 19:06) *
Дался вам этот волатайл. При чем тут вообще это?
При том... Читайте стандарт там всё подробно описано.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
XVR
сообщение Feb 11 2011, 08:34
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847



А у вас в main_loop'е случайно нет локальной переменной event_flags?
Go to the top of the page
 
+Quote Post
vROMAv
сообщение Feb 11 2011, 08:53
Сообщение #14





Группа: Участник
Сообщений: 13
Регистрация: 10-02-11
Из: Украина
Пользователь №: 62 859



Всем спасибо за помощь. Действительно в одном из участков кода проморгал атомарность((

ЗЫ: Старался всегда учитывать эту возможную бяку, но никогда ещё на неё не попадал. А ведь хорошо что попал, впредь буду более внимательно относится к битовым операциям.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Feb 11 2011, 09:05
Сообщение #15


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(vROMAv @ Feb 11 2011, 12:53) *
А ведь хорошо что попал, впредь буду более внимательно относится к битовым операциям.

Присмотритесь повнимательнее в пространство SFR - GPR0 итд - меняются легко флаги, это если не хочется в регистре переменную держать.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Feb 11 2011, 09:08
Сообщение #16


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(_Pasha @ Feb 11 2011, 12:05) *
Присмотритесь повнимательнее в пространство SFR - GPR0 итд - меняются легко флаги, это если не хочется в регистре переменную держать.

Грязный хакsm.gif
Не люблю такие заходы...


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Feb 11 2011, 09:10
Сообщение #17


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(demiurg_spb @ Feb 11 2011, 13:08) *
Грязный хакsm.gif
Не люблю такие заходы...

Если Вы о портабельности, то ее здесь нет. А если не о портабельности, то о чем?
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Feb 11 2011, 09:22
Сообщение #18


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



А я тоже без стеснений юзал битовые поля в неиспользуемых регистрах вместо переменных. Иногда байтовые, типа TWAR,TWDR.


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Feb 11 2011, 09:46
Сообщение #19


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(_Pasha @ Feb 11 2011, 12:10) *
Если Вы о портабельности, то ее здесь нет. А если не о портабельности, то о чем?


Я о том, что этот заюзаный не по своему назначению регистр может быть неожиданно востребован.
Не Вами так наследниками Вашего хозяйства (а мужики то не знали...)
Чтобы даже гипотетически не закладывать проблемы, я всегда воздерживаюсь от таких вот выкрутасов.
Ибо почити всегда есть более прямое решение, как например не использовать битовые переменные вовсе (для AVR - это отличный способ избавиться от геморроя).
Таков мой подход и я его не навязываю. Вольному - воля!


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
vROMAv
сообщение Feb 11 2011, 10:22
Сообщение #20





Группа: Участник
Сообщений: 13
Регистрация: 10-02-11
Из: Украина
Пользователь №: 62 859




Попутно ещё вопросик:
Например есть код

ISR()
{
adc_flags |= PROCESS_I_NEG;
}

loop()
{
...................
if ( adc_flags & PROCESS_UOUT_POS )
{
cli();
adc_flags &= ~PROCESS_UOUT_POS;
sei();
}
else
{
}
..........
}


Компилятор превратит во чтото следующее

;if ( adc_flags & PROCESS_UOUT_POS )

R24,adc_flags

;/////////////////////////////////
; ТУТ ВОЗНИКАЕТ ВДРУГ ПРЕРЫВАНИЕ
;(где сохраняется регистр R24, затем добавляется бит PROCESS_I_NEG к adc_flags
;и воосстанавливается R24)
;/////////////////////////////////

;далее продолжается выполнение if
SBRS R24,1<<PROCESS_UOUT_POS
RJMP m1

;adc_flags &= ~PROCESS_UOUT_POS;

А вот тут вопрос:
будет ли компилиться так (т.е. в R24 снова считывается adc_flag)
CLI
LDS R24,adc_flags
ANDI R24,~PROCESS_UOUT_POS
STS adc_flags,R24
SEI

или же возможна ситуация когда компилер
не будет считывать в R24 переменную adc_flags, а посчитает что она ранее была считана
в R24 и таким образом не учтёт изменение её в прерывании

Т.е. другими словами, необходимо ли и для if тоже использовать атомарность например в виде

cli()
rez=adc_flags & PROCESS_UOUT_POS;
sei()

if(rez)
{
.......
}
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Feb 11 2011, 10:27
Сообщение #21


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Цитата(vROMAv @ Feb 11 2011, 15:22) *
Т.е. другими словами, необходимо ли и для if тоже использовать атомарность например в виде

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

Сообщение отредактировал GetSmart - Feb 11 2011, 10:27


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
ar__systems
сообщение Feb 11 2011, 13:43
Сообщение #22


self made
****

Группа: Свой
Сообщений: 855
Регистрация: 7-03-09
Из: Toronto, Canada
Пользователь №: 45 795



Цитата(demiurg_spb @ Feb 10 2011, 12:19) *
При том... Читайте стандарт там всё подробно описано.


Переменная однобайтовая. Какая атомарность?
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Feb 11 2011, 15:39
Сообщение #23


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(ar__systems @ Feb 11 2011, 16:43) *
Переменная однобайтовая. Какая атомарность?

Да байтовая но в ней 8 бит-флагов:
как происходит изменение бита в ОЗУ, а вот так:
1 load
2 modify
3 store

так если произойдёт прерывание между пунктами 1-3 изменяющее этот же байт, то все изменения сделанные в прерывании будут похерены пунктом 3.

И напоследок:
volatile нужен для любой переменной хоть битовой хоть байтовой, хоть QWORD , если эта переменная используется (пишется или только читается) в прерываниях или является частью SFR.

Всё! Учим наизусть и повторяем вместо мантры:-)

Не хотите читать стандарт - поищите по форуму, тема про volatile уже неоднократно всплывала.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
vROMAv
сообщение Feb 11 2011, 16:12
Сообщение #24





Группа: Участник
Сообщений: 13
Регистрация: 10-02-11
Из: Украина
Пользователь №: 62 859



Цитата
Переменная однобайтовая. Какая атомарность?


Код посмотри:

Си:
adc_flags &= ~PROCESS_UOUT_POS;

Асма:
LDS R24,adc_flags
ANDI R24,~PROCESS_UOUT_POS
STS adc_flags,R24
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Feb 11 2011, 18:05
Сообщение #25


Гуру
******

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



QUOTE (demiurg_spb @ Feb 11 2011, 17:39) *
если эта переменная используется (пишется или только читается) в прерываниях или является частью SFR.
Если эта переменная используется и в прерываниях и в основном цикле (или в нескольких потоках при использовании ОС).


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
ar__systems
сообщение Feb 11 2011, 18:30
Сообщение #26


self made
****

Группа: Свой
Сообщений: 855
Регистрация: 7-03-09
Из: Toronto, Canada
Пользователь №: 45 795



Цитата(demiurg_spb @ Feb 11 2011, 10:39) *
Да байтовая но в ней 8 бит-флагов:
как происходит изменение бита в ОЗУ, а вот так:
1 load
2 modify
3 store

так если произойдёт прерывание между пунктами 1-3 изменяющее этот же байт, то все изменения сделанные в прерывании будут похерены пунктом 3.

Да volatile к этой проблеме никакого отношения не имеет, и никак не поможет! Тут единственное что поможет, так это запрет прерываний на время доступа!

Цитата
Если эта переменная используется и в прерываниях и в основном цикле (или в нескольких потоках при использовании ОС).

Да ради бога, только если у вас разграничение доступа не организвано должным образом, работать не будет все равно, volatile или нет. Иными словами, от критических секций вы все равно не избавитесь.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Feb 11 2011, 20:10
Сообщение #27


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(ar__systems @ Feb 11 2011, 21:30) *
Да ради бога, только если у вас разграничение доступа не организвано должным образом, работать не будет все равно, volatile или нет. Иными словами, от критических секций вы все равно не избавитесь.
Для байтовой переменной на AVR избавлюсь от критической секции. И работать будет только если volatile.
Я Вас не пойму. Вы что-то из пустого в порожнее всё переливаете и переливаете. К чему это?
Перечитайте Ваши сообщения в этой ветке. Либо странные утверждения либо повторение за кем-то прописных истин после доходчивого разъяснения...

Цитата(Сергей Борщ @ Feb 11 2011, 21:05) *
Если эта переменная используется и в прерываниях и в основном цикле (или в нескольких потоках при использовании ОС).
Ваша формулировка как всегда более точная:-)


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 22:50
Рейтинг@Mail.ru


Страница сгенерированна за 0.01748 секунд с 7
ELECTRONIX ©2004-2016