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

... Дальше например можете в цикле ждать когда установится некий флажок ...

Если не использовать блокирующие операции, то и проблемы не будет.

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


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

Если не использовать блокирующие операции, то и проблемы не будет.

Это что за операции такие??

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


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

Приветствую!

 

Не забывайте о том что не только на ISR заканчивается внешний мир для переменной.

Переменная может обновляется и через DMA и из других ядер. Так что без volatile ну ни как.

И это отнюдь не "высосанный из пальца" пример, а вполне обычная практика.

 

Удачи! Rob.

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


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

jcxz, вот именное такие: "например можете в цикле ждать когда установится некий флажок" (цитирую Вас же).

 

RobFPGA, по идее вообще без разницы, где эта переменная будет изменяться, что-то мы ходим по кругу...

 

Проблема: компилятор оптимизируя вырезает кусок кода считая его лишним.

На основании чего он это делает? Он знает, что некая переменная имеет в текущий момент определенное состояние.

Значит, если на входе функции мы не присваиваем ей какое либо значение и затем не проверяем эту переменную на другие значения (что для компилятора кажется безумным и он это режет), то и volatile не нужен.

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


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

Значит, если на входе функции мы не присваиваем ей какое либо значение и затем не проверяем эту переменную на другие значения (что для компилятора кажется безумным и он это режет), то и volatile не нужен.

Похоже пациент безнадёжен....

Попробуйте когда-нить заглянуть в реальные результаты компиляции при полной оптимизации. Вы как видно никогда туда не заглядывали или у Вас нет опыта отладки вообще.

Уже 100500 раз тут повторили, что на входе в эту функцию, компилятор вполне может переместить значение переменной в регистр (или какое другое место) и другая задача/ISR/другое_процессорное_ядро никогда об этом не узнает и будет обращаться к ней по адресу в памяти, а внутри функции - обращение к этой переменной в регистре (хоть по записи хоть по чтению). Так как при оптимизации кода, оптимизатор не должен (и не может) анализировать весь ход выполнения программы и не может знать что обращения к этой переменной возможны из разных мест одновременно. Об этом должен знать программист и должен явно указать это посредством volatile.

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


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

А если включить lto то оптимизироваться будет совсем не одна функция, а кусок какой сказать заранее не выйдет. И уж там оптимизатор оторвется по полной.

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


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

jcxz, сейчас я тоже начну вас оскорблять :)

Изменять все переменные, используемые в прерывании, необходимо атомарно (или вы не в курсе?), и нам в принципе без разницы, куда компилятор запишет значение во время преобразований, хоть в регистр, хоть будет "держать в уме".

 

Пока по прежнему нет реального примера, кроме блокирующих операций, где компилятор может сделать не так, как предполагалось.

В статьях обычно об этом пишут как-то абстрактно, а никто детально не желает разобраться, как действительно все работает.

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


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

jcxz, сейчас я тоже начну вас оскорблять :)

Изменять все переменные, используемые в прерывании, необходимо атомарно (если вы не в курсе), и нам в принципе без разницы, куда компилятор запишет значение во время преобразований, хоть в регистр, хоть будет "держать в уме".

Да при чём тут атомарность-то???

Вы хотя-бы прочитали и поняли что я написал? Изменений переменной в фоновом программе может вообще не быть.

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


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

Приветствую!

 

Изменять все переменные, используемые в прерывании, необходимо атомарно (если вы не в курсе), и нам в принципе без разницы, куда компилятор запишет значение во время преобразований, хоть в регистр, хоть будет "держать в уме".

 

Пока по прежнему нет реального примера, кроме блокирующих операций, где компилятор может сделать не так, как предполагалось.

В статьях обычно об этом пишут как-то абстрактно, а никто детально не желает разобраться, как действительно все работает.

Volatile к атомарности никакого отношения не имеет! Volatile указывает компилятору что значение переменной может изменится ВНЕ текущего контекста зоны видимости переменной. Поэтому компилятор НЕ вправе оптимизировать ЧТЕНИЕ актуального состояния этой переменной.

Пример Вам уже приводили - чтение переменной в цикле. И не только как блокировка, а например очень часто при опросе регистров состояния периферии, биты которых меняются аппаратно.

 

Удачи! Rob.

 

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


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

jcxz, читаю "на входе в эту функцию, компилятор вполне может переместить значение переменной в регистр"

И каким боком из-за этого переменная может не изменяться вообще? В текущий момент пусть функция не видит изменения, при следующем входе снова прочитает по адресу и все увидит. Где проблема?

 

RobFPGA, об этом речи и не идет, атомарность делает сам программист, конечно.

Ок, добавляем еще одну ситуацию, кроме блокирующих - чтение регистров ввода/вывода, хотя они уже по умолчанию идут как volatile, и программисту об этом не надо заботиться.

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


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

Приветствую!

jcxz, читаю "на входе в эту функцию, компилятор вполне может переместить значение переменной в регистр"

И каким боком из-за этого переменная может не изменяться вообще? В текущий момент пусть функция не видит изменения, при следующем входе снова прочитает по адресу и все увидит. Где проблема?

 

RobFPGA, об этом речи и не идет, атомарность делает сам программист, конечно.

Ок, добавляем еще одну ситуацию, кроме блокирующих - чтение регистров ввода/вывода, хотя они уже по умолчанию идут как volatile, и программисту об этом не надо заботиться.

Это если за Вас уже позаботились сделав правильный BSP, а если эта периферия сидит например во внешней FPGA которая отмаплена на память?

И не только регистры, а например буфера данных которые пишутся через DMA, а проц их только читает для обработки.

И что с оптимизирует компилятор в этом случае если НИГДЕ в Вашей программе нет ЗАПИСИ в этот буфер/переменную?

 

Удачи! Rob.

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


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

jcxz, читаю "на входе в эту функцию, компилятор вполне может переместить значение переменной в регистр"

И каким боком из-за этого переменная может не изменяться вообще? В текущий момент пусть функция не видит изменения, при следующем входе снова прочитает по адресу и все увидит. Где проблема?

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

А вот если прерывание тоже изменяет это значение, то это значение пропадет, так как функция при выходе сохранит в эту переменную свое значение.

 

А если глобально про volatile, то я не слишком часто его применяю, только там, где вышеприведенные эффекты могут иметь место или есть опасность выкидывания компилятором моего кода.

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

А если простая передача данных по флагам из/в прерывания, то и так все работает.

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


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

RobFPGA, думаю, если буфер объявлен глобально, то компилятор не вырежет код, даже если "НИГДЕ в Вашей программе нет ЗАПИСИ в этот буфер/переменную".

Имхо, компилятор работает исключительно локально, относительно кода функции, и не проверяет, в каком месте и пишутся ли вообще данные в глобальные переменные.

 

А вот если прерывание тоже изменяет это значение, то это значение пропадет, так как функция при выходе сохранит в эту переменную свое значение.
Ну как бы изменения делаем атомарно, это уже обсудили.

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


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

RobFPGA, по идее вообще без разницы, где эта переменная будет изменяться, что-то мы ходим по кругу...

Переменная не может где-то изменяться. Она находится всегда там, где определена изначально: глобальная - в памяти, регистровая - в регистре, временная в стеке.

И только так. Никаких "путешествий" она не производит по стекам и регистрам она не производит: в стек и регистры компилятор записывает копии значения переменных.

Компилятор производит компиляцию исходя из предположения по умолчанию, что копия значения переменной всегда тождественна оригинальному, и как раз

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

Изменено пользователем aiwa

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


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

И каким боком из-за этого переменная может не изменяться вообще? В текущий момент пусть функция не видит изменения, при следующем входе снова прочитает по адресу и все увидит. Где проблема?

У меня возникает ощущение что Вы троллите всех тут....

Как можно не понимать очевидных вещей??

Пример (жизненный, написал специально для Вас):

enum {F_NONE, F_SLEEP_STATE, F_TIMER, F_SERVICE_REQUEST_1, F_SERVICE_REQUEST_2};
int flag = F_NONE;
void f()
{
 if (flag == F_NONE) {
   //ТОЧКА1
   ENTR_CRT_SECTION(); //входим в критическую секцию (просто запрет прерывания)
   if (flag == F_NONE) {
     flag = F_SLEEP_STATE;
     EXIT_CRT_SECTION(); //покидаем критическую секцию
     Sleep();
   } else EXIT_CRT_SECTION();
 }
 int i = flag;
 flag = F_NONE;
 switch (flag) {
   case F_TIMER: return;
   case F_SERVICE_REQUEST_1:
     ... //обслуживание сервиса 1
     break;
   case F_SERVICE_REQUEST_2:
     ... //обслуживание сервиса 2
     break;
 }
}
void isr1()
{
 PeripheralIntReqReset1();
 if (flag == F_SLEEP_STATE) WakeUp();
 else if (flag != F_NONE && flag != F_TIMER) return;
 flag = F_SERVICE_REQUEST_1;
}
void isr2()
{
 PeripheralIntReqReset2();
 if (flag == F_SLEEP_STATE) WakeUp();
 else if (flag != F_NONE && flag != F_TIMER) return;
 flag = F_SERVICE_REQUEST_2;
}
void isrTimer()
{
 if (flag == F_SLEEP_STATE) WakeUp();
 else if (flag != F_NONE) return;
 flag = F_TIMER;
}

Теперь представьте что эта функция вызывается периодически (суперцикл или корпоративная многозадачность).

Включена максимальная оптимизация и на входе в функцию f() при первом обращении компилятор перенёс переменную flag в регистр, а в месте ТОЧКА1 происходит какое-либо прерывание, которое пишет запрос обслуживания в flag.

Так вот - при компиляции с макс. оптимизацией, этот код будет сбоить (терять запросы на обслуживание). Но если к определению flag добавить volatile, всё будет прекрасно работать с любым уровнем оптимизации.

Чтобы пресечь возможные доводы типа "искусственный пример", допустим: isr1()/isr2() к примеру - это ISR-ы о готовности данных к чтению в FIFO-буфере некоей периферии, которая однократно выставляет флаг готовности при достижении некоего уровня заполнения FIFO. Эти данные надо считать. Причём считать до прихода след. данных чтобы избежать потерь.

И можно 1000 подобных примеров придумать и с более сложными зависимостями.

 

думаю, если буфер объявлен глобально, то компилятор не вырежет код, даже если "НИГДЕ в Вашей программе нет ЗАПИСИ в этот буфер/переменную".

Опять неправда.

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

А потом компоновщик увидит, что к этой переменной нет ни одного обращения и удалит её за ненадобностью.

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


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

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

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

Гость
Ответить в этой теме...

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

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

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

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

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

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