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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Размещение "изменчивой" переменной в регистре, WinAVR
Snaky
сообщение May 21 2007, 02:35
Сообщение #1


Mute Beholder
***

Группа: Свой
Сообщений: 260
Регистрация: 4-04-07
Из: Третья планета от Солнца
Пользователь №: 26 754



Как добиться, чтобы WinAVR разместил переменную в регистре и не оптимизировал ее?
Т.е. есть маленькая программа, хотелось одну переменную поместить в регистр для ускорения доступа, причем изменение переменной возможно в прерывании. Если бы писал на асме, то просто разместил бы переменную в регистре по своему усмотрению и использовал бы всегда значение этого регистра, однако с WinAVR такой трюк не прошел sad.gif .

Поясню:
1) Пишу: volatile unsigned char Timer;
Результат: переменная размещена в ОЗУ (@ 0x0078), считывается каждый раз. Все логично.
Дизасм:
if (Timer > max) max = Timer; // внутри цикла
Код
    LDS     R24,0x0078      // в цикле
    CP      R25,R24         // в цикле
    BRCC    PC+0x03         // в цикле
    LDS     R25,0x0078      // в цикле

2) Пишу: register unsigned char Timer asm("r15");
Результат: переменная размещена в регистре R15, но считывание оптимизировано. Тоже логично - компилятор "не знает", что она может менятся в прерывании.
Дизасм:
if (Timer > max) max = Timer; // внутри цикла
Код
   MOV     R19,R15      // за циклом
   ...
   CP      R25,R19      // в цикле
   BRCC    PC+0x02      // в цикле
   MOV     R25,R19      // в цикле
   ...

3) Пишу оба модификатора: volatile register unsigned char Timer asm("r15");
Результат: практически тот же, что и в п.2. Компилятор "частично помнит" что переменная volatile и при копировании использует значение регистра R15, однако при сравнении в цикле все равно использует копию R15 в R19. В результате программа не работает как ожидалось.
Дизасм:
if (Timer > max) max = Timer; // внутри цикла
Код
   MOV     R19,R15      // за циклом
   ...
   CP      R25,R19      // в цикле
   BRCC    PC+0x02      // в цикле
   MOV     R25,R15      // в цикле
   ...

В результате пришлось использовать вариант 1. Расходы на чтение/запись ОЗУ в принципе небольшие - 1 команда LDS. Однако в цикле уже ощутимо, да и все же хочется иметь возможность "управлять" действиями компилятора.


--------------------
Common sense is not so common.
Go to the top of the page
 
+Quote Post
makc
сообщение May 21 2007, 04:27
Сообщение #2


Гуру
******

Группа: Админы
Сообщений: 3 621
Регистрация: 18-10-04
Из: Москва
Пользователь №: 904



Посмотрите на опцию gcc -ffixed-reg:
Цитата
-ffixed-reg

Treat the register named reg as a fixed register; generated code should never refer to it (except perhaps as a stack pointer, frame pointer or in some other fixed role).

reg must be the name of a register. The register names accepted are machine-specific and are defined in the REGISTER_NAMES macro in the machine description macro file.

This flag does not have a negative form, because it specifies a three-way choice.


--------------------
BR, Makc
В недуге рождены, вскормлены тленом, подлежим распаду. (с) У.Фолкнер.
Go to the top of the page
 
+Quote Post
mdmitry
сообщение May 21 2007, 09:19
Сообщение #3


Начинающий профессионал
*****

Группа: Свой
Сообщений: 1 215
Регистрация: 25-10-06
Из: СПб
Пользователь №: 21 648



Если в прерывании не используется более ничего, кроме указанной переменной, то прерывание описать как
__attribute__ (naked),
и руками сохранить sreg для корректности.


--------------------
Наука изощряет ум; ученье вострит память. Козьма Прутков
Go to the top of the page
 
+Quote Post
Snaky
сообщение May 21 2007, 09:35
Сообщение #4


Mute Beholder
***

Группа: Свой
Сообщений: 260
Регистрация: 4-04-07
Из: Третья планета от Солнца
Пользователь №: 26 754



Цитата(mdmitry @ May 21 2007, 16:19) *
Если в прерывании не используется более ничего, кроме указанной переменной, то прерывание описать как
__attribute__ (naked),
и руками сохранить sreg для корректности.

Переменная оптимизируется в основной программе. При этом становится уже неважно как она меняется в прерывании. Конкретно в моем случае в прерывании как раз все в порядке.


--------------------
Common sense is not so common.
Go to the top of the page
 
+Quote Post
mdmitry
сообщение May 22 2007, 10:22
Сообщение #5


Начинающий профессионал
*****

Группа: Свой
Сообщений: 1 215
Регистрация: 25-10-06
Из: СПб
Пользователь №: 21 648



Посмотрел свой код и в нем объявленные переменные по варианту 3 работают как надо. Используются несколько переменных в обработчике прерывания. Делалось это с Вашей целью: недопустить обращения к временным регистрам в прерывании для ускорения работы. В прерывании счетчик, маленький расчет и кое-какие присваивания.

Сообщение отредактировал mdmitry - May 22 2007, 10:23


--------------------
Наука изощряет ум; ученье вострит память. Козьма Прутков
Go to the top of the page
 
+Quote Post
Snaky
сообщение May 23 2007, 02:43
Сообщение #6


Mute Beholder
***

Группа: Свой
Сообщений: 260
Регистрация: 4-04-07
Из: Третья планета от Солнца
Пользователь №: 26 754



Цитата(mdmitry @ May 22 2007, 16:22) *
Посмотрел свой код и в нем объявленные переменные по варианту 3 работают как надо. Используются несколько переменных в обработчике прерывания. Делалось это с Вашей целью: недопустить обращения к временным регистрам в прерывании для ускорения работы. В прерывании счетчик, маленький расчет и кое-какие присваивания.

Я вроде понятно объяснил, но вижу что вы меня не поняли (или я недопонимаю). Повторюсь:
переменная которую я привязываю к регистру R15 в обработчике прерывания изменяется правильно (меняется содержимое R15), однако код основной программы (ака функция main()) обращается с ней не как с volatile переменной - т.е. копирует ее в другой регистр (R19) и оперирует с ним в цикле, несмотря на то, что в любой момент времени R15 может измениться в прерывании.
Цитата
Посмотрите на опцию gcc -ffixed-reg

Посмотрел. Из описания я понял что это средство для фиксации регистров для определенных целей (как например в winavr R1 == перманентный ноль), и недопущение их использования не по назначению. Имхо, это немного не то. По крайней мере ключики -ffixed-reg и -ffixed-reg-r15 не помогли 05.gif .


--------------------
Common sense is not so common.
Go to the top of the page
 
+Quote Post
dxp
сообщение May 23 2007, 03:32
Сообщение #7


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



Цитата(Snaky @ May 23 2007, 09:43) *
Посмотрел. Из описания я понял что это средство для фиксации регистров для определенных целей (как например в winavr R1 == перманентный ноль), и недопущение их использования не по назначению.

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

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


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post
WHALE
сообщение May 23 2007, 05:55
Сообщение #8


Знающий
****

Группа: Свой
Сообщений: 902
Регистрация: 2-01-06
Из: Краснодар
Пользователь №: 12 768



Запретите в main во время работы с вашей переменной прерывание,где она может быть изменена.


--------------------
"Hello, word!" - 17 errors 56 warnings
Go to the top of the page
 
+Quote Post
Snaky
сообщение May 23 2007, 06:35
Сообщение #9


Mute Beholder
***

Группа: Свой
Сообщений: 260
Регистрация: 4-04-07
Из: Третья планета от Солнца
Пользователь №: 26 754



Цитата(WHALE @ May 23 2007, 11:55) *
Запретите в main во время работы с вашей переменной прерывание,где она может быть изменена.

Я даже не знаю что ответить wacko.gif
Давайте в третий раз попробую. Переменную я помечаю модификатором volatile потому что ее значение может измениться в обработчике прерываний, и программа должна это видеть. Для этого компилятору запрещено оптимизировать volatile переменные и положенно при любом обращении к переменной считывать заново ее значение. Проблема в том, что компилятор генерирует такой код, где в некоторых местах основной программы используется копия значения переменной, что неприемлемо и нарушает алгоритм работы программы.
Более того, мне непонятно зачем он это вообще делает, если оптимизацией тут даже и не пахнет: копирует один регистр в другой и использует копию теми же командами работы с регистрами.


--------------------
Common sense is not so common.
Go to the top of the page
 
+Quote Post
forever failure
сообщение May 23 2007, 07:01
Сообщение #10


Местный
***

Группа: Участник
Сообщений: 256
Регистрация: 6-03-05
Из: Екатеринбург
Пользователь №: 3 112



{
volatile register unsigned char eol_trans_uart asm ("r15");
if (PORTC & BIT (MODBUS_ENABLE_TRANS_BIT))
return;
/* ... */

}
avr-gcc --std=gnu99 -c -g -Os -ffixed-r15 -Wall -D_DEBUG -Wstrict-prototypes -mmcu=atmega8 main.c -o main.o
io.h: In function `main':
io.h:21: warning: volatile register variables don't work as you might wish

Может об этом и предупреждение ?
Go to the top of the page
 
+Quote Post
Snaky
сообщение May 23 2007, 07:12
Сообщение #11


Mute Beholder
***

Группа: Свой
Сообщений: 260
Регистрация: 4-04-07
Из: Третья планета от Солнца
Пользователь №: 26 754



Цитата(forever failure @ May 23 2007, 13:01) *
io.h:21: warning: volatile register variables don't work as you might wish
Может об этом и предупреждение ?

Очень похоже что именно об этом. Странно что у меня Build succeeded with 0 Warnings... (WinAVR 20070122).


--------------------
Common sense is not so common.
Go to the top of the page
 
+Quote Post
aesok
сообщение May 23 2007, 08:11
Сообщение #12


Знающий
****

Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484



Цитата(Snaky @ May 23 2007, 11:12) *
Очень похоже что именно об этом. Странно что у меня Build succeeded with 0 Warnings... (WinAVR 20070122).


Скорее всего причина в том что нет ключа "-Wall" в коммандной строке компилятора.

Анатолий.
Go to the top of the page
 
+Quote Post
Snaky
сообщение May 23 2007, 08:20
Сообщение #13


Mute Beholder
***

Группа: Свой
Сообщений: 260
Регистрация: 4-04-07
Из: Третья планета от Солнца
Пользователь №: 26 754



Цитата(aesok @ May 23 2007, 14:11) *
Скорее всего причина в том что нет ключа "-Wall" в коммандной строке компилятора.

Есть.


--------------------
Common sense is not so common.
Go to the top of the page
 
+Quote Post
ReAl
сообщение May 23 2007, 08:27
Сообщение #14


Нечётный пользователь.
******

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



Цитата(Snaky @ May 23 2007, 11:20) *
Есть.

Попробуй к нему добавить ключ -Wextra


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
aesok
сообщение May 23 2007, 08:30
Сообщение #15


Знающий
****

Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484



Цитата(Snaky @ May 23 2007, 12:20) *
Есть.


Почитайте про volatile <<global>> register здесь:
http://gcc.gnu.org/ml/gcc-patches/2005-11/msg00628.html

Вывод что volatile <<global>> register в GCC не работает. Почему у вас нет варинга не знаю.

Анатолий.
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 18th June 2025 - 04:20
Рейтинг@Mail.ru


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