Variable optimized out

Кто любит RISC в жизни, заходим, не стесняемся.
Accel
Первый раз сказал Мяу!
Сообщения: 27
Зарегистрирован: Ср фев 13, 2019 15:07:44

Variable optimized out

Сообщение Accel »

Доброго времени суток.

Перехожу с аврок на стм32, приходится писать на С. Столкнулся с проблемой: при включении оптимизации компилятора нижеприведенный код (приведен в упрощенном виде) выщёлкивается из итогового образа напрочь.

Код: Выделить всё

void InitRCC_HSE() {
	uint32_t cycle_counter;

	cycle_counter = 0;

	//Ждем заданное количество циклов флага стабильности частоты HSE
	while (READ_BIT(RCC->CR, RCC_CR_HSERDY) == 0U) {
		cycle_counter++;

		if (cycle_counter == HSE_READY_TIMEOUT) {
			//дальше обработка ошибки
		}
	}
[/color]
Если cycle_counter объявить как volatile - всё работает, но если нет, то цикл при включенной оптмизиации в итоговый код не попадает.
Как же так, условие в while(...) же не статическое, RCC->CR в коде CMSIS объявлено как __IO uint32_t CR; где __IO - алиас для того же volatile, соответственно, его значение на этапе компиляции не определено. Чтобы выкинуть кусок кода, компилятор должен быть уверен, что код никогда не будет выполнен. Здесь же он вполне себе выполняется из-за того, что значение регистра меняется извне, и об этом компилятору дана соответствующая директива (__IO uint32_t CR;).

Вопрос - в чем логика такого поведения компилятора (gcc@STM32CubeIDE).
Реклама
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Re: Variable optimized out

Сообщение Reflector »

Такой код компилятор выкидывать не должен, мой gcc 10 ничем подобным и не занимается.
Реклама
parovoZZ
Мудрый кот
Сообщения: 1759
Зарегистрирован: Пт июн 01, 2018 07:28:45

Re: Variable optimized out

Сообщение parovoZZ »

должен быть квалификатор volatile
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Variable optimized out

Сообщение Аlex »

[uquote="parovoZZ",url="/forum/viewtopic.php?p=4052491#p4052491"]должен быть квалификатор volatile[/uquote]
Аргументируйте. Тоже не вижу ничего плохого в этом коде.
Реклама
Эиком - электронные компоненты и радиодетали
Accel
Первый раз сказал Мяу!
Сообщения: 27
Зарегистрирован: Ср фев 13, 2019 15:07:44

Re: Variable optimized out

Сообщение Accel »

Спасибо всем, кто откликнулся, стал копать на тему того, конкретно какие инструкции вылетают и нашел свою ошибку. Оказалось, что:

а). Да, действительно локальную переменную компилятор оптимизирует без последствий, но не прям выкинув, а используя на участке кода под ее значение один из регистров общего назначения (не выделяя под нее sram), загрузив на старте в него непосредственное значение (HSE_READY_TIMEOUT, в моем случае равном 250), и декрементируя на каждой итерации цикла и сравнивая с нулём для выполнения условного перехода (поэтому в дебаггере я не мог посмотреть на значение переменной, которой нет, поэтому "variable optimized out").

б). Я выбрал слишком маленькое значение этой константы: на другом кварце частота HSE фиксировалась ещё до 80й итерации цикла, поэтому в константе задал с некоторым запасом (250). Оказалось, что новый кварц стабилизируется дольше. На неоптимизированной версии стабилизация происходила чуть раньше 250й итерации цикла, а на оптимизированной - чуть после (повезло :facepalm:), т.к. неоптмизированный код цикла содержал 3 лишних ассемблерных инструкции, соответственно, в абсолютном выражении работал чуть дольше. Поэтому одна версия впритирку пролазила в таймаут стабилизации HSE, а другая - валилась в ошибку. Увеличил таймаут до 2000 - всё стало ок :beer:.
Реклама
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: Variable optimized out

Сообщение VladislavS »

Не надо впритирку. Это же защитный механизм. Завтра другая температура, контролер, кварц или ёмкости и опять "не успет". Я бы ещё на пару порядков счётчик увеличил. Какая разница, через 1, 10 или 100 мс вы узнаете о неисправности кварца.
Реклама
jcxz
Мудрый кот
Сообщения: 1725
Зарегистрирован: Вт авг 15, 2017 10:51:13

Re: Variable optimized out

Сообщение jcxz »

[uquote="Accel",url="/forum/viewtopic.php?p=4052505#p4052505"]Увеличил таймаут до 2000 - всё стало ок :beer:.[/uquote]250 - пальцем в небо, 2000 - опять наугад. Да ещё и - зависимо от того, насколько оптимальным будет код... :facepalm:
А ведь в даташитах/юзер-мануалах обычно приводят времена стабилизации генераторов.

Добавлено after 6 minutes 12 seconds:
[uquote="VladislavS",url="/forum/viewtopic.php?p=4052523#p4052523"]Я бы ещё на пару порядков счётчик увеличил. Какая разница, через 1, 10 или 100 мс вы узнаете о неисправности кварца.[/uquote]Для некоторых классов устройств регламентируется максимально допустимое время выхода устройства в рабочий режим после подачи питания. Или же - максимально допустимое время начала выполнения какой-то определённой критичной функции (даже если в целом весь функционал устройства ещё не запустился к этому моменту). И 100мс может оказаться слишком много. Да даже и 10.
Accel
Первый раз сказал Мяу!
Сообщения: 27
Зарегистрирован: Ср фев 13, 2019 15:07:44

Re: Variable optimized out

Сообщение Accel »

[uquote="jcxz",url="/forum/viewtopic.php?p=4052630#p4052630"][uquote="Accel",url="/forum/viewtopic.php?p=4052505#p4052505"]Увеличил таймаут до 2000 - всё стало ок :beer:.[/uquote]250 - пальцем в небо, 2000 - опять наугад. Да ещё и - зависимо от того, насколько оптимальным будет код... :facepalm:[/uquote]
Согласен, но в даташите тоже указано "Startup time - 2ms" с припиской, что может меняться в больших пределах, в зависимости от качества кварца. Видимо, по фен-шую всё-таки заюзаю SysTick, чтобы отмерять интервалы им, и добавлю конский запас. Спасибо.
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: Variable optimized out

Сообщение VladislavS »

[uquote="jcxz",url="/forum/viewtopic.php?p=4052630#p4052630"]И 100мс может оказаться слишком много. Да даже и 10.[/uquote]Кто мешает сделать критическпе вещи, если они действительно есть, до старта кварца? Заодно и время ожидания зря не пройдёт.
Аватара пользователя
AVI-crak
Прорезались зубы
Сообщения: 202
Зарегистрирован: Сб янв 09, 2016 15:51:17
Контактная информация:

Re: Variable optimized out

Сообщение AVI-crak »

[uquote="Accel",url="/forum/viewtopic.php?p=4052481#p4052481"]при включении оптимизации компилятора нижеприведенный код (приведен в упрощенном виде) выщёлкивается из итогового образа напрочь[/uquote]
Макрос в цикле разворачивается до:

Код: Выделить всё

#define READ_BIT(REG, BIT)    ((REG) & (BIT))
При этом первый параметр имеет атрибут volatile на чтение и запись, однако к нему применяется дополнительный оператор "И" в теле макроса, отчего атрибут теряется.
Для того чтобы обойти это ограничение, достаточно не использовать макрос. Так и запись получается короче, и проще.

Код: Выделить всё

cycle_counter = HSE_READY_TIMEOUT;
while ((!(RCC->CR & RCC_CR_HSERDY)) && --cycle_counter);
if(cycle_counter == 0) {флаг не взвёлся}
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Re: Variable optimized out

Сообщение Reflector »

[uquote="AVI-crak",url="/forum/viewtopic.php?p=4052976#p4052976"]Макрос в цикле разворачивается до:

Код: Выделить всё

#define READ_BIT(REG, BIT)    ((REG) & (BIT))
При этом первый параметр имеет атрибут volatile на чтение и запись, однако к нему применяется дополнительный оператор "И" в теле макроса, отчего атрибут теряется.[/uquote]
Оператор "И" применяется к прочитанному из регистра значению, никакие атрибуты там не теряются.
Аватара пользователя
AVI-crak
Прорезались зубы
Сообщения: 202
Зарегистрирован: Сб янв 09, 2016 15:51:17
Контактная информация:

Re: Variable optimized out

Сообщение AVI-crak »

[uquote="Reflector",url="/forum/viewtopic.php?p=4052986#p4052986"]никакие атрибуты там не теряются.[/uquote]
Наследие атрибута сохраняется до первого применения внешнего оператора. Название макроса является именем новой переменной уже без атрибутов (да, они именно так и работают). Кроме того, по документации не взведённый RCC_CR_HSERDY равен нулю - первоначальный код вообще не рабочий, в том числе и ограничитель времени (там вообще ересь).
jcxz
Мудрый кот
Сообщения: 1725
Зарегистрирован: Вт авг 15, 2017 10:51:13

Re: Variable optimized out

Сообщение jcxz »

[uquote="VladislavS",url="/forum/viewtopic.php?p=4052842#p4052842"]Кто мешает сделать критическпе вещи, если они действительно есть, до старта кварца? Заодно и время ожидания зря не пройдёт.[/uquote]"Критически важные вещи" могут включать запуск каких-то служб, для запуска которых нужно например чтение из внешнего чипа SPI-флешь (конфиг и т.д.). Хранение этого конфига во флешь может осуществляться в сложных структурах: кольцевые буфера, ФС, ...
Предлагаете писать два набора API для работы с флешь и структурами хранения данных в ней: для работы до старта кварца и для работы с кварцем?? :facepalm:
К тому же - и все эти службы, время запуска которых критично, они тоже должны как-то плавно пережить переключение источника тактирования....
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Re: Variable optimized out

Сообщение Reflector »

[uquote="AVI-crak",url="/forum/viewtopic.php?p=4053049#p4053049"]Наследие атрибута сохраняется до первого применения внешнего оператора. Название макроса является именем новой переменной уже без атрибутов (да, они именно так и работают).[/uquote]
Первый раз подобное слышу :) Если изначально было:

Код: Выделить всё

while (READ_BIT(RCC->CR, RCC_CR_HSERDY) == 0U) 
то после обработки препроцессором получим:

Код: Выделить всё

while (((RCC->CR) & (RCC_CR_HSERDY)) == 0U)
И я это не выдумал, а скопировал из вывода gcc после скармливания ему ключа "-E". Где тут новая переменная?
Аватара пользователя
AVI-crak
Прорезались зубы
Сообщения: 202
Зарегистрирован: Сб янв 09, 2016 15:51:17
Контактная информация:

Re: Variable optimized out

Сообщение AVI-crak »

[uquote="Reflector",url="/forum/viewtopic.php?p=4053098#p4053098"]Первый раз подобное слышу :)[/uquote]
Лучше поздно, чем никогда. :)
Я повторюсь, значение атрибута сохраняется до первого оператора присвоения. И оно там не в воздухе висит, для него даже имя есть, точно такое-же как у названия макроса. Это естественное ограничение GCC, от присвоения volatile всем переменным проекта.
В операцию сравнения идёт имя макроса, а не его содержимое.
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Re: Variable optimized out

Сообщение Reflector »

[uquote="AVI-crak",url="/forum/viewtopic.php?p=4053122#p4053122"]Я повторюсь, значение атрибута сохраняется до первого оператора присвоения. И оно там не в воздухе висит, для него даже имя есть, точно такое-же как у названия макроса. Это естественное ограничение GCC, от присвоения volatile всем переменным проекта.[/uquote]
При разворачивании макроса происходит простая подстановка, в этот момент компилятор еще не знает что такое RCC->CR, определено ли оно где-то и какие там у него атрибуты, а после подстановки, т.е. когда наличие volatile может иметь значение, уже нет никаких макросов...
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: Variable optimized out

Сообщение VladislavS »

[uquote="jcxz",url="/forum/viewtopic.php?p=4053052#p4053052"]К тому же - и все эти службы, время запуска которых критично, они тоже должны как-то плавно пережить переключение источника тактирования....[/uquote]Сова на глобусе. Если кварц запускается, в штатном режиме, никаких лишних задержек не будет. А в аварийном режиме действительно КРИТИЧЕСКАЯ служба должна уметь без кварца работать. Иначе никакая она не критическая.

Добавлено after 16 minutes 16 seconds:
[uquote="AVI-crak",url="/forum/viewtopic.php?p=4053122#p4053122"]В операцию сравнения идёт имя макроса, а не его содержимое.[/uquote]Надеюсь, это просто жара...
Аватара пользователя
AVI-crak
Прорезались зубы
Сообщения: 202
Зарегистрирован: Сб янв 09, 2016 15:51:17
Контактная информация:

Сообщение AVI-crak »

VladislavS, Reflector - Всегда можно проверить на практике.
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Re:

Сообщение Reflector »

[uquote="AVI-crak",url="/forum/viewtopic.php?p=4053380#p4053380"]Всегда можно проверить на практике.[/uquote]
Я же вчера продемонстрировал как будет выглядеть код после стадии препроцессинга... Можно чуть поменять макрос и тогда получим точно такую строку как ты сам и предлагал. Так, например. Справа промежуточное представление кода, мы просто тормознули компилятор на этой стадии, никто ведь не станет доказывать что одинаковые строки скомпилируются по-разному просто потому, что раньше в одной из них был макрос :) И все компиляторы которые там можно выбрать естественно выдают одно и то же.
jcxz
Мудрый кот
Сообщения: 1725
Зарегистрирован: Вт авг 15, 2017 10:51:13

Re: Variable optimized out

Сообщение jcxz »

[uquote="VladislavS",url="/forum/viewtopic.php?p=4053362#p4053362"]Если кварц запускается, в штатном режиме, никаких лишних задержек не будет. А в аварийном режиме действительно КРИТИЧЕСКАЯ служба должна уметь без кварца работать. Иначе никакая она не критическая.[/uquote]Разговор не про "критические службы", а про службы время старта которых, после включения_питания/сброса критично, не должно превышать максимально допустимое. И тупо ждать 100мс чего-то (когда это не нужно), до того как запустить такую службу - слишком расточительно.
Ответить

Вернуться в «ARM»