Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Рассуждения о _regvar и register
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
kamedi_clab
IAR 4.21A помогите - что за ошибка ?

Error[Pa043]: the keyword "__regvar" is not available with the current settings. Registers must be locked with --lock_regs C:\_AN447 my\_bldc_iar\main.c 55
before __regvar can be used

Total number of errors: 1
Total number of warnings: 0

вот проект прицепил - http://slil.ru/25402589 (20 Кб)
prottoss
Цитата(kamedi_clab @ Jan 26 2008, 21:00) *
IAR 4.21A помогите - что за ошибка ?
Error[Pa043]: the keyword "__regvar" is not available with the current settings. Registers must be locked with --lock_regs C:\_AN447 my\_bldc_iar\main.c 55
before __regvar can be used Total number of errors: 1
Total number of warnings: 0 вот проект прицепил - http://slil.ru/25402589 (20 Кб)
А что не понятного? smile.gif Компилятор же вам честно говорит -

Registers must be locked with --lock_regs .... before __regvar can be used

Разберетесь - заодно и людей, читающих курс научите smile.gif



IAR for AVR, к сожалению, сейчас нет, но разве можно регистровые переменные объявлять как

Код
__no_init __regvar volatile uint16_t sineTableIncrement           @14;


Я так понимаю - __regvar - это уже тип, а вы к нему еще и uint16_t прицепили
zltigo
Цитата(prottoss @ Jan 26 2008, 17:24) *
Я так понимаю - __regvar - это уже тип, а...

Нет, это Memory Attribute - ничем принципиально не отличающийся от подобного назначения __flash, __eeprom, __far и прочих прочих....

Цитата(kamedi_clab @ Jan 26 2008, 17:00) *
Error[Pa043]...

И почему для этого вопроса была выбрана тема "глюки компилятора"????????
Qwertty
А что спецификатор типа памяти register ИАР не понимает? Зачем еще __regvar изобретать?
zltigo
Цитата(Qwertty @ Jan 26 2008, 18:50) *
А что спецификатор типа памяти register ИАР не понимает?

Понимает, точнее, как и подавляющее большинство нынешних компиляторов молча игнорирует.
Цитата
Зачем еще __regvar изобретать?

Это совсем другое - если прочитаете сообщение об ошибке - поймете, что речь идет о глобально зарезервированном для каких-то нужд регистре.
Baser
Цитата(kamedi_clab @ Jan 26 2008, 16:00) *
IAR 4.21A помогите - что за ошибка ?

Error[Pa043]: the keyword "__regvar" is not available with the current settings. Registers must be locked with --lock_regs C:\_AN447 my\_bldc_iar\main.c 55
before __regvar can be used

Компилятор вам прямо говорит, что ему не нравится и что нужно делать.
Говорит он, что при ваших установках проекта глобальные регистровые переменные неразрешены.
Нужно эти регистры заблокировать для локальных переменных и подключить библиотеки, где эти заблокированные регистры не используются. Делается это в опциях проекта:
Project->Options->C/C++ Compiler->Code->Number of registers to lock for global variables->9 [R7..R15]

Цитата(prottoss @ Jan 26 2008, 16:24) *
Я так понимаю - __regvar - это уже тип, а вы к нему еще и uint16_t прицепили

Тут это разрешено, uint16_t просто занимает не один, а два регистра. Все равно эти регистры блокируются специальным ключем компилятора.

Цитата(zltigo @ Jan 26 2008, 16:44) *
И почему для этого вопроса была выбрана тема "глюки компилятора"????????

Если принять во внимание, что и вопрос автора темы DiMonstr тоже не имел никакого отношения к глюкам компилятора, то вопрос помещен в правильную тему smile.gif
kamedi_clab
Вот по стр 189 мануала IAR

Qwertty
Цитата(zltigo @ Jan 26 2008, 18:59) *
Понимает, точнее, как и подавляющее большинство нынешних компиляторов молча игнорирует.

Ну не совсем игнорируют. Просто компилятор обычно сам решает размещать переменную в регистре или нет. Но если все переменные в доступные регистры не влезают, то объявленные с register будут иметь приоритет.
Цитата(zltigo @ Jan 26 2008, 18:59) *
Это совсем другое - если прочитаете сообщение об ошибке - поймете, что речь идет о глобально зарезервированном для каких-то нужд регистре.

Спасибо, понял. Это типа как в ГЦЦ регистр для хранения 0. Хотя не понятен смысл объявления глобальных переменных в регистрах. Слишком много это вызовет ограничений, у таких переменных даже адрес взять нельзя, возможность работы посредством указателя теряется.
kamedi_clab
Цитата(prottoss @ Jan 26 2008, 17:24) *
Я так понимаю - __regvar - это уже тип, а вы к нему еще и uint16_t прицепили


Это писатели из ATMEL прицепили в AVR447 - я думаю они знали что делали.
Но проект положить в архив "забыли".

Я лишь попытался создать проект IAR под исходники и скомпилить. Получилось теперь.
prottoss
Цитата(Qwertty @ Jan 26 2008, 23:21) *
Спасибо, понял. Это типа как в ГЦЦ регистр для хранения 0. Хотя не понятен смысл объявления глобальных переменных в регистрах. Слишком много это вызовет ограничений, у таких переменных даже адрес взять нельзя, возможность работы посредством указателя теряется.
Никаких, по моему ограничений нет. Я пару лет назад делал проект на ATTiny2313 на IAR на С. Тоже много глобальных переменных делал регистровых таким же макаром. Обращаться к ним, по моему, тоже можно так же через указатели - ибо адреса регистров находятся в памяти данных с адреса 0! И код, кстати получается практически таким же, как пишешь на ассемблере. Только, в добавок, получаешь все преимущества языка высокого уровня.
Qwertty
Цитата(prottoss @ Jan 26 2008, 19:37) *
Обращаться к ним, по моему, тоже можно так же через указатели - ибо адреса регистров находятся в памяти данных с адреса 0!

К&R, second edition - " Кроме того, применительно к регистровой переменной независимо от того, выделен на самом деле для нее регистр или нет, не определено понятие адреса ". И далеко не все ядра отражают регистры на ОЗУ.
prottoss
Цитата(Qwertty @ Jan 26 2008, 23:49) *
К&R, second edition - " Кроме того, применительно к регистровой переменной независимо от того, выделен на самом деле для нее регистр или нет, не определено понятие адреса ". И далеко не все ядра отражают регистры на ОЗУ.
К К&R обсуждаемый вопрос не имеет отношения, это, как говорилось выше
Цитата
...Memory Attribute - ничем принципиально не отличающийся от подобного назначения __flash, __eeprom, __far и прочих прочих....
То бишь расширение компилятора от IAR for AVR
Baser
Цитата(Qwertty @ Jan 26 2008, 18:21) *
Спасибо, понял. Это типа как в ГЦЦ регистр для хранения 0. Хотя не понятен смысл объявления глобальных переменных в регистрах. Слишком много это вызовет ограничений, у таких переменных даже адрес взять нельзя, возможность работы посредством указателя теряется.

В регистрах обычно объявляю глобальные флаги. Операции работы с ними получаются атомарными, сама модификация бита в одну команду процессора. Доступ к флагам, сохраняемым в обычной памяти, длительный. Изменение такого флага это три команды: read-modify-write. А если при этом флаг может изменятся как из основного цикла, так и из прерывания, то приходится в основном цикле еще и запрещать прерывания sad.gif Итого пять команд вместо одной-двух.

А накладных расходов при занимании нескольких регистров немного. Библиотеки используют эти регистры только в математических функциях. Все остальное обычно помещается в стек, к нему доступ удобнее, чем к регистрам R0..R15
zltigo
Цитата(Qwertty @ Jan 26 2008, 19:21) *
Ну не совсем игнорируют.

Поверьте моему опыту - игнорирут. Посмотрите документацию на любимый компилятор и увидете чего-нибудь типа User requests for register variables are ignored.
Цитата(Qwertty @ Jan 26 2008, 19:21) *
Спасибо, понял. Это типа как в ГЦЦ регистр для хранения 0.

Ну очень ограниченое сравнение. В частности полный аналог описанного это --zero_register
Qwertty
Цитата(zltigo @ Jan 26 2008, 20:42) *
Поверьте моему опыту - игнорирут. Посмотрите документацию на любимый компилятор и увидете чего-нибудь типа User requests for register variables are ignored.

Посмотрю. Или подожду когда в тред заглянет aesok , чтобы не копаться в куче страниц wink.gif
Цитата(zltigo @ Jan 26 2008, 20:42) *
Ну очень ограниченое сравнение. В частности полный аналог описанного это --zero_register

__zero_reg__, R1, это то же самое про что Вы говорите? Или имеется ввиду R0?

С флагами в регистрах понятно, но я все же иду на сохранение/восстановление прерываний. Все равно немедленной реакции на установленный флаг не будет ( иначе что мешает сразу выполнить обработчик взведенного флага), так что пару лишних команд/тактов на это выделить можно. Зато из за таких "фокусов", хотя и не только из за них, С-ные программы чаще всего непереносимы с платформы на платформу. Никакие HAL тут уже не помогут...
По поводу ИАР-овских расширений - если расширения начинают противоречить стандартам языка, то я например, не стал бы ими пользоваться. А тут противоречие налицо - возможен указатель на регистровую переменную. Нафиг такие расширения smile.gif
prottoss
Цитата(Qwertty @ Jan 27 2008, 01:19) *
По поводу ИАР-овских расширений - если расширения начинают противоречить стандартам языка, то я например, не стал бы ими пользоваться. А тут противоречие налицо - возможен указатель на регистровую переменную. Нафиг такие расширения smile.gif
...если расширения начинают противоречить стандартам языка... - слишком громко сказанно:-) ИМХО фишка с регистрами, нууу оччень для мелких камней типа Tiny. Программы для них зачастую заточены только под эти камни. Да и, в принципе, перенести такой код не проблема - к ногтю __reg_var и все дела, так же как и при смене архитектуры CPU __flash меняется на const
singlskv
Цитата(zltigo @ Jan 26 2008, 20:42) *
Поверьте моему опыту - игнорирут. Посмотрите документацию на любимый компилятор и увидете чего-нибудь типа User requests for register variables are ignored.
А если любимый gcc ?
Он не игнорирует и я этим иногда пользуюсь,
только нужно проявлять осторожность при использовании библиотек в случае
объявления большого количества регистровых переменных(ну или листинг смотреть...).
zltigo
Цитата(Qwertty @ Jan 26 2008, 21:19) *
__zero_reg__, R1, это то же самое про что Вы говорите? Или имеется ввиду R0?

Нет, R15 - да бог с ними.
Цитата
По поводу ИАР-овских расширений - если расширения начинают противоречить стандартам языка, то я например, не стал бы ими пользоваться.

Заодно можете перестать пользоватся простенькими с контроллерами, которые вследствии этого имеют дивное количество вариантов памятей с уникальными адресациями. Ресурсов у таких контроллеров тоже не густо, посему АСMообразные финты тоже бывают много более полезны, нежели у свежих собратьев. Для, например, ARM контроллеров у того-же IAR расшрений языка абсолютный минимум.
Qwertty
Цитата(prottoss @ Jan 26 2008, 21:32) *
...если расширения начинают противоречить стандартам языка... - слишком громко сказанно:-)

Украл батон - преступление? Или слишком громко сказано? smile.gif Из мелочей все и состоит, тут отступим, там переиначим, глядишь и получим из C Джаву smile.gif
Цитата(prottoss @ Jan 26 2008, 21:32) *
ИМХО фишка с регистрами, нууу оччень для мелких камней типа Tiny. Программы для них зачастую заточены только под эти камни. Да и, в принципе, перенести такой код не проблема - к ногтю __reg_var и все дела, так же как и при смене архитектуры CPU __flash меняется на const

Ну разве что заточены и переносить на другой никогда не понадобится. А к ногтю __reg_var и потом вылавливать странные баги из-за незапрещенных прерываний во время модификации флага вне прерывания это хорошо? И с __flash не все так очевидно, можно получить например массив шрифта в ... ОЗУ, с запретом его модифицировать smile.gif

Цитата(singlskv @ Jan 26 2008, 21:49) *
А если любимый gcc ?
Он не игнорирует и я этим иногда пользуюсь,
только нужно проявлять осторожность при использовании библиотек в случае
объявления большого количества регистровых переменных(ну или листинг смотреть...).

Тоже проигнорирует, особенно в случае большого количества регистровых переменных. Я правда больше пары штук не пробовал, обычно индекс массива или указатель объявляю как register.
А можете поподробнее про осторожность? Чего опасаться?
zltigo
Цитата(singlskv @ Jan 26 2008, 21:49) *
А если любимый gcc ?
Он не игнорирует и я этим иногда пользуюсь,

Исключения, только подтверждают правила smile.gif.
Цитата
только нужно проявлять осторожность при использовании библиотек в случае
объявления большого количества регистровых переменных(ну или листинг смотреть...).

Да ну? У Вас совершенно ошибочные sad.gif представления о квалификаторе register, даже в случаях если он не игнорируется в принципе, он носит только рекомендательный характер.
Цитата(Qwertty @ Jan 26 2008, 22:05) *
А можете поподробнее про осторожность? Чего опасаться?

Абсолютно нечего - безопасно.
Baser
Цитата(Qwertty @ Jan 26 2008, 21:05) *
Украл батон - преступление? Или слишком громко сказано? smile.gif Из мелочей все и состоит, тут отступим, там переиначим, глядишь и получим из C Джаву smile.gif

Ну разве что заточены и переносить на другой никогда не понадобится. А к ногтю __reg_var и потом вылавливать странные баги из-за незапрещенных прерываний во время модификации флага вне прерывания это хорошо? И с __flash не все так очевидно, можно получить например массив шрифта в ... ОЗУ, с запретом его модифицировать smile.gif

А так-ли важно блюсти чистоту Си и бояться применять расширения, если речь идет о небольших МК и о работе с прерываниями и другой аппаратной периферией? Это уровень драйверов. А этот уровень никогда не был особенно переносимым. Если говорить об алогитмах верхнего уровня, то там заботится о переносимости есть смысл.
singlskv
Цитата(zltigo @ Jan 26 2008, 22:21) *
Да ну? У Вас совершенно ошибочные sad.gif представления о квалификаторе register, даже в случаях если он не игнорируется в принципе, он носит только рекомендательный характер.
Абсолютно нечего - безопасно.
Эксперименты ставить будем ? smile.gif
Для затравки, предлагаю объявить регистры R0,R1 байтовыми переменными и присвоить
им значение например 255 ...
Если не убедит, подгоню примеры повеселее.... smile.gif
zltigo
Цитата(singlskv @ Jan 26 2008, 22:46) *
Эксперименты ставить будем ? smile.gif

Нет для начала будем читать (пост #69) о чем идет речь речь идет о квалификаторе register.
Цитата
Для затравки, предлагаю объявить регистры R0,R1 байтовыми переменными...

Давайте - есть квалификатор register описанный в стандарте языка. Давайте попробуйте с его помощью сделать вышеобещанное. Готов внимать.
Цитата
Если не убедит, подгоню примеры повеселее.... smile.gif

Да и так уже не скучно.
singlskv
Цитата(zltigo @ Jan 26 2008, 23:03) *
Нет для начала будем читать (пост #69) о чем идет речь речь идет о квалификаторе register.
Давайте - есть квалификатор register описанный в стандарте языка. Давайте попробуйте с его помощью сделать вышеобещанное. Готов внимать.

register unsigned char mynull asm("r0");
......

mynull=255;

попробуйте, не пожалеете... smile.gif
Baser
Цитата(singlskv @ Jan 26 2008, 21:46) *
Для затравки, предлагаю объявить регистры R0,R1 байтовыми переменными и присвоить
им значение например 255 ...

А это что, gcc позволяет проделывать такие финты!??

IAR такого не дает. Если речь идет о стандартном классе памяти register, то компилятор сам решает, какие регистры использовать.
Если речь о глобальных регистровых переменных __regvar (--lock_regs), то они могут размещаться в регистрах R4-R15.
Если об опции --zero_register, то это только R15==0.
При выделении регистров под глобальные нужды все конфликты с библиотеками отслеживает линкер и при наличии этих конфликтов ругается:
Цитата
The linker will issue a link-time error if any incompatibilities arise.

Так что все абсолютно безопасно smile.gif
zltigo
Цитата(singlskv @ Jan 26 2008, 23:09) *
попробуйте

Если Вы это срьезно, то ну и каша у Вас в голове sad.gif.
singlskv
Цитата(zltigo @ Jan 26 2008, 23:22) *
Если Вы это срьезно, то ну и каша у Вас в голове sad.gif.
Ну кашу я вобще не ем, кроме разьве что гречневой, так что в
голове она у меня редкая гостья smile.gif

ну перечитываем тогда что ли пост №68 с которого и началась дискуссия:
Цитата(Qwertty @ Jan 26 2008, 18:50) *
А что спецификатор типа памяти register ИАР не понимает? Зачем еще __regvar изобретать?


так вот gcc его понимает и пользуется им для размещения переменных в регистрах...
zltigo
Цитата(singlskv @ Jan 26 2008, 23:47) *
...так что в голове она у меня редкая гостья smile.gif

1. Это не С, это асмовская вставка в стиле одного из диалектов со всеми вытекающими последствиями для компиляции и оптимизации.
2. Читаем стандарт языка C99.
3. Без register должно быть аналогично.
singlskv
Цитата(zltigo @ Jan 26 2008, 23:52) *
1. Это не С, это асмовская вставка в стиле одного из диалектов со всеми вытекающими последствиями для компиляции и оптимизации.
нет, это спецконструкция с использованием резервированного register которая
придает более точный смысл register, те указание точного месторасположения.
Цитата
2. Читаем стандарт языка C99.
Читаем, читаем...
Тока Вы похоже опять забыли с чего началось все обсуждение, там вроде как было про __regvar
при чем здесь стандарт.... непонимаю
Цитата
3. Без register должно быть аналогично.
ЧТО ДОЛЖНО БЫТЬ АНАЛОГИЧНО ???
zltigo
Цитата(singlskv @ Jan 27 2008, 00:01) *
Тока Вы похоже опять забыли...

Я прекрасно помню, на какой конкретный вопрос конкретно по register лично я отвечал :-E.
Qwertty
Цитата(singlskv @ Jan 26 2008, 23:47) *
ну перечитываем тогда что ли пост №68 с которого и началась дискуссия:
так вот gcc его понимает и пользуется им для размещения переменных в регистрах...

Это просто я тогда не понял, о чем идет речь. Вот и спросил о register и IAR. Я тоже сижу на ГЦЦ, и проблем с размещением в регистрах не испытывал. Правда номер регистра жестко не задаю. В документации к avr-libs указывается, что компилятор не контролирует конфликты в случае жесткого указания номера регистра. Документированные грабли и не грабли вовсе, а так, особенности реализации smile.gif
SIA
Цитата(Qwertty @ Jan 27 2008, 00:06) *
Это просто я тогда не понял, о чем идет речь. Вот и спросил о register и IAR. Я тоже сижу на ГЦЦ, и проблем с размещением в регистрах не испытывал. Правда номер регистра жестко не задаю. В документации к avr-libs указывается, что компилятор не контролирует конфликты в случае жесткого указания номера регистра. Документированные грабли и не грабли вовсе, а так, особенности реализации smile.gif

Вообще говоря, не понимаю, зачем вообще при написании кода самим создавать себе проблемы - жестко указывать номера регистров для размещения переменных компилятору ? Выгоды практически никакой, а переносимость и надежность могут конкретно пострадать. Можно понять, если регистр особенный и с этой переменной надо что-то специфичное делать, но такой кусочек кода надо бы оформлять маленькой препроцессорной вставочкой/подпрограммкой, и подробно комментить.
singlskv
Цитата(Qwertty @ Jan 27 2008, 00:06) *
Правда номер регистра жестко не задаю. В документации к avr-libs указывается, что компилятор не контролирует конфликты в случае жесткого указания номера регистра.
Скажем так(насколько я ничего не понимаю...),
R2-R8 можно почти всегда безболезненно,
R9-R15 с контролем листинга,
регистр без указания месторасположения почти не имеет смысла...

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

ЗЫ. конечно R2-R7 и R8-R15 ...
aesok
Используя модификатор register вы просите компилятор разместить переменную в регистрах процессора, предполагая что таким образом получите более оптимальный код, но компилятор вправе игнорировать вашу просьбу, если сочтет генерируемый что код в результате будет хуже.

Используя код:
Код
register unsigned char counter asm("r3");

Вы заставляете компилятор разместить переменную counter в регистре r3 контроллера. И всю ответственность за этот поступок берете на себя.

В GCC полностью безопасно использовать регистры r2..r7 для объявления переменных. (С точки зрения компилятора, если только Вы сами не будете их изменять в ассемблерных вставках.) Возможно использование r8..r15, но эти регистры могут использоваться компилятором для передачи аргументов функций. Тоесть если все функции в проекте не передают в аргументах больше 10 байт, то регистры r8..r15 в вашем распоряжении. Если 12 байт то регистры r8-r9 будут использоваться компилятором, и переменная расположенная в них исказиться.
avr-libc-user-manual FAQ#3:How to permanently bind a variable to a register? и
FAQ#13 What registers are used by the C compiler?

Не используйте модификатор volatile с регистровыми переменными, его работа не гарантируется. К сожалению GCC не дает предупреждения, но это факт.

Анатолий.
singlskv
Цитата(SIA @ Jan 27 2008, 00:17) *
Вообще говоря, не понимаю, зачем вообще при написании кода самим создавать себе проблемы - жестко указывать номера регистров для размещения переменных компилятору ? Выгоды практически никакой, а переносимость и надежность могут конкретно пострадать.
Выгода может быть в разы, в 2-3 раза легко...
О переносимости такого кода речи нет, это используется только на самом низком уровне и только
при условии что ты знаешь что делаешь.
Цитата
Можно понять, если регистр особенный и с этой переменной надо что-то специфичное делать, но такой кусочек кода надо бы оформлять маленькой препроцессорной вставочкой/подпрограммкой, и подробно комментить.
Вот пример моих коментариев из реального проекта:
Код
//-------------------------------------------------------------------
// Прерывание системного таймера
//   используются только регистровые переменные
//   никакие регистры не сохраняются
//   SREG не сохраняется
//   ОБЯЗАТЕЛЬНО ПРОВЕРИТЬ СГЕНЕРИРОВАННЫЙ КОД !!!!!!!!!!!!!!!!!!!!!
//-------------------------------------------------------------------

там всего 8 команд + reti
Но я точно знаю что я делаю.

Вы можете спросить почему это не написано на асм.
Потому что в качестве бонуса я получаю возможность обращаться к регистровым переменным
как к обычным С переменным в обычном С коде...
Qwertty
Цитата(singlskv @ Jan 27 2008, 00:19) *
регистр без указания месторасположения почти не имеет смысла...

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

Имеет, хотя ГЦЦ и сам достаточно умный и может разместить переменную в регистре даже без указания.
Правда к глобальным это не относится, во всяком случае я такого не видел ни разу. А насчет смысла - например указатель выгодно хранить в регистре, тогда его изменении (++ или --) проходят гораздо быстрее. А так как такие операции обычно происходят в циклах, которые являются узким местом в программе, то использование регистров дает возможность сильно уменьшить время. При этом мне совсем не важно, в каких конкретно регистрах находится указатель. Правда оптимизатор и так обычно такой указатель разместит в регистрах smile.gif А вот явное месторасположение имеет смысл в основном для встроенного ассемблера.
singlskv
Цитата(Qwertty @ Jan 27 2008, 00:38) *
А насчет смысла - например указатель выгодно хранить в регистре, тогда его изменении (++ или --) проходят гораздо быстрее. А так как такие операции обычно происходят в циклах, которые являются узким местом в программе, то использование регистров дает возможность сильно уменьшить время.
Вот как раз для такой оптимизации использование register абслоютно беcсмысленно
и может даже(в принципе) помешать компилятору....
Для таких кусков кода нужно грамотно использовать локальные переменные.
Если хотите примеров, покажите кусок кода где register дал выигрыш, и я покажу
как нужно было написать просто с локальными переменными.
Qwertty
Цитата(singlskv @ Jan 27 2008, 00:34) *
Вы можете спросить почему это не написано на асм.
Потому что в качестве бонуса я получаю возможность обращаться к регистровым переменным
как к обычным С переменным в обычном С коде...

В свете того, что выше написал aesok о регистровых переменных и квалификаторе volatile, возможность обращаться к регистровым переменным, модифицируемым в прерывании, из С кода весьма сомнительна.

Цитата(singlskv @ Jan 27 2008, 00:48) *
Вот как раз для такой оптимизации использование register абслоютно беcсмысленно
и может даже(в принципе) помешать компилятору....
Для таких кусков кода нужно грамотно использовать локальные переменные.
Если хотите примеров, покажите кусок кода где register дал выигрыш, и я покажу
как нужно было написать просто с локальными переменными.

Это и есть локальная переменная. Я выше писал, что не объявляю глобальных переменных регистровыми. Сам по себе register даст выигрыщ только если локальных переменных много, тогда это будет подсказка оптимизатору о том, какие размещать в регистрах в первую очередь. Если локальная переменная одна, то она станет регистровой сама по себе smile.gif И перестанет показывать свое значение в студии sad.gif А вот помешать компилятору вряд-ли удастся, он просто молча проигнорирует register и все, даже варнинга не даст.
SIA
Код
//-------------------------------------------------------------------
// Прерывание системного таймера
//   используются только регистровые переменные
//   никакие регистры не сохраняются
//   SREG не сохраняется
//   ОБЯЗАТЕЛЬНО ПРОВЕРИТЬ СГЕНЕРИРОВАННЫЙ КОД !!!!!!!!!!!!!!!!!!!!!
//-------------------------------------------------------------------

там всего 8 команд + reti
Но я точно знаю что я делаю.


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

Я однажды еще на ассемблере делал системный таймер в регистре процессора для системы быстрой регистрации, но код отработки прерывания не изменял в процессоре НИЧЕГО, кроме регистра таймера.

Если хочется сэкономить такты - практичнее подумать над алгоритмом в целом или поменять МК, если экономится память - это вообще нонсенс, т.к. цена версий МК с разной памятью не сильно отличается. Чтобы окупить затраты на отладку такого "кода", потребуются многотысячные тиражи, и то не факт, что это рационально - резервов для апгрейда не останется.
Еще для ускорения при отработке прерываний можно использовать теневой банк регистров (дополнительные банки есть у многих МК, от 8051 и Z80 до PIC32).
Qwertty
Цитата(SIA @ Jan 27 2008, 01:00) *
т.к. его исполнение может оказаться прервано другим таким же с большим приоритетом - с соответствующей порчей данных.

У AVR этого никогда не произойдет smile.gif
Я видел один раз похожий прием, правда на ассемблере - на Телесисах лежит проект генератора Л.И. Ридико. Там обработчик вообще начинается с адреса вектора и самая короткая ветка не сохраняет SREG. Но это сделано для того, чтобы выжать из контроллера все что можно и видимо такие задачи крайне редки. Хотя тоже имеют право на жизнь.
singlskv
Цитата(Qwertty @ Jan 27 2008, 00:55) *
В свете того, что выше написал aesok о регистровых переменных и квалификаторе volatile, возможность обращаться к регистровым переменным, модифицируемым в прерывании, из С кода весьма сомнительна.
По большому счету, квалификаторы register и volatile одновременно не применимы.
При "жестком" расположении переменной в регистре volatile просто теряет смысл...
Я не знаю примеров в которых "жестко" заданная регистровая переменная может портиться.
Цитата
Это и есть локальная переменная. Я выше писал, что не объявляю глобальных переменных регистровыми. Сам по себе register даст выигрыщ только если локальных переменных много, тогда это будет подсказка оптимизатору о том, какие размещать в регистрах в первую очередь. Если локальная переменная одна, то она станет регистровой сама по себе smile.gif И перестанет показывать свое значение в студии sad.gif А вот помешать компилятору вряд-ли удастся, он просто молча проигнорирует register и все, даже варнинга не даст.
В таком варианте, согласен.
aesok
Цитата(singlskv @ Jan 27 2008, 01:07) *
По большому счету, квалификаторы register и volatile одновременно не применимы.
При "жестком" расположении переменной в регистре volatile просто теряет смысл...
Я не знаю примеров в которых "жестко" заданная регистровая переменная может портиться.
В таком варианте, согласен.


Почитайте пост, там описана проблема:
http://electronix.ru/forum/index.php?showtopic=42140

GCC ведет себя также. До веррсии 4.1 он выдавал предупреждение, потом перестал. Есть ключик чтобы его включть.

Анатолий.
singlskv
Цитата(SIA @ Jan 27 2008, 01:00) *
Так нельзя делать даже из самых лучших побуждений.
Код, работающий по прерыванию и при этом портящий регистры и статус процессора - нонсенс, т.к. его исполнение может оказаться прервано другим таким же с большим приоритетом - с соответствующей порчей данных.
Может конечно и нельзя .... 07.gif
Но я точно знаю что я делаю.
используются только зарезервированные регистры и регистры переферии,
код написан таким образом что SREG просто не меняется,
напоминание "ПРОВЕРИТЬ КОД" именно про то, чтобы проверить что компилятор не начудил
и не вставил инструкции меняющие SREG.


Цитата(aesok @ Jan 27 2008, 01:13) *
Почитайте пост, там описана проблема:
http://electronix.ru/forum/index.php?showtopic=42140
GCC ведет себя также. До веррсии 4.1 он выдавал предупреждение, потом перестал. Есть ключик чтобы его включть.
Я не только читал но и писал в той ветке...
Про проблемы с повтором констант я знаю, более того примерно с год назад я поднимал
этот вопрос на форуме (ссылку лень искать сейчас, что то типа"Проблемы оптимизации WinAVR").
У меня все проблемы сводились к тому что код оказывался просто очень не оптимальным.
У Вас есть пример кода для GCC который будет в такой ситуации некорректным ?
SIA
Цитата(singlskv @ Jan 27 2008, 01:17) *
Может конечно и нельзя .... 07.gif
Но я точно знаю что я делаю.
используются только зарезервированные регистры и регистры переферии,
код написан таким образом что SREG просто не меняется,
напоминание "ПРОВЕРИТЬ КОД" именно про то, чтобы проверить что компилятор не начудил
и не вставил инструкции меняющие SREG.

IMHO, это приемлемо только для очень маленького проекта, строк на 300-500. Более крупный при использовании таких методов становится слишком непрактичным.

p.s. Эпоху, когда экономили каждый такт, я еще застал. Но не думаю, что сейчас это правильно - проще взять более мощный процессор, они сейчас недороги.
aesok
Цитата(singlskv @ Jan 27 2008, 01:29) *
Цитата
Почитайте пост, там описана проблема:
http://electronix.ru/forum/index.php?showtopic=42140
GCC ведет себя также. До веррсии 4.1 он выдавал предупреждение, потом перестал. Есть ключик чтобы его включть.

У Вас есть пример кода для GCC который будет в такой ситуации некорректным ?


Да нашел на www.avrfreaks.net.

Код
volatile register uint16_t s1 asm("r2");
ISR(INT0_vect)
{

   if(bit_is_set(PINC,0))    s1++;
   else            s1--;
}

int main{
//...
      sei();
   OCR0+=10;
   while(s1<10);
//...
}


Регистровая переменная объявлена как volatile, код на уровне оптимизации -Os:
Код

205:         sei();
SEI
208:         OCR0+=10;
IN      R24,0x31
SUBI    R24,0xF6
OUT     0x31,R24
MOVW    R24,R2  //!!!
209:         while(s3<10);
CPI     R24,0x0A
CPC     R25,R1  
BRCS    PC-0x02


Происходит копирование R2:R3 в R24:R25, и в цикле анализируеться копия переменой s1 в R24:R25, а не она сама в R2:R3.

Так что не используйте в GCC 'volatile register' переменые и добавте в свои макефайлы ключик '-Wvolatile-register-var'.

Если интересно почему GCC так работает то, можно почитать здесь: http://gcc.gnu.org/ml/gcc-patches/2005-11/msg00657.html

Анатолий.
ReAl
Цитата(aesok @ Jan 26 2008, 23:22) *
Используя код:
Код
register unsigned char counter asm("r3");

Вы заставляете компилятор разместить переменную counter в регистре r3 контроллера. И всю ответственность за этот поступок берете на себя.

В GCC полностью безопасно использовать регистры r2..r7 для объявления переменных. (С точки зрения компилятора, если только Вы сами не будете их изменять в ассемблерных вставках.)
Вот этим-то я и интересовался, ещё когда порт scmRTOS 1.x на avr-gcc обсуждался. И результат - в общем случае в avr-gcc лучше обойтись без -ffixed-reg и register ...asm("rX").
В некоторых функциях библиотек эти r2-r7 таки используются (в частности, a/b при uint64_t a, b задействует их все). Да, они их сохраняют и восстанавливают, но ведь обработчики прерываний об этом не знают.
На этом я и остановился - не стал разбираться, можно ли перекомпилировать библиотеки с запрещёнными к использованию несколькими регистрами (даст ли это что-то, не используются ли они в частях библиотек, кодированных на асме и т.д.). Можно ещё было поразбираться - какие именно функции залазят в эти регистры - возможно, кроме 64-битных целых и, к примеру, плавающей точки, никто туда и не залазит, но я просто решил для себя - если желание разместить глобальные переменные в регистрах возникнет, значит это будет задача под чистый асм :-), "ведь играл писал же я их в молодости" (С) актёрская шутка.
singlskv
Цитата(aesok @ Jan 27 2008, 02:39) *
У Вас есть пример кода для GCC который будет в такой ситуации некорректным ?
Да нашел на www.avrfreaks.net.
Код
...........

Регистровая переменная объявлена как volatile, код на уровне оптимизации -Os:
Происходит копирование R2:R3 в R24:R25, и в цикле анализируеться копия переменой s1 в R24:R25, а не она сама в R2:R3.

Проверил на WinAVR 200604...
Код генериться одинаковый и с и без volatile
Код
16:         sei();
+00000045:   9478        SEI                      Global Interrupt Enable
17:         TCNT0+=10;
+00000046:   B782        IN      R24,0x32         In from I/O location
+00000047:   5F86        SUBI    R24,0xF6         Subtract immediate
+00000048:   BF82        OUT     0x32,R24         Out to I/O location
18:         while(s1<10);
+00000049:   E08A        LDI     R24,0x0A         Load immediate
+0000004A:   1628        CP      R2,R24           Compare
+0000004B:   0431        CPC     R3,R1            Compare with carry
+0000004C:   F3E0        BRCS    PC-0x03          Branch if carry set
Вроде все правильно.
C volatile выдает warning.
aesok
Цитата(ReAl @ Jan 27 2008, 12:30) *
Вот этим-то я и интересовался, ещё когда порт scmRTOS 1.x на avr-gcc обсуждался. И результат - в общем случае в avr-gcc лучше обойтись без -ffixed-reg и register ...asm("rX").
В некоторых функциях библиотек эти r2-r7 таки используются (в частности, a/b при uint64_t a, b задействует их все). Да, они их сохраняют и восстанавливают, но ведь обработчики прерываний об этом не знают.

Получаеться в GCC небезопасно использовать глобальные регистровые переменные. Только локальные.

Анатолий.
singlskv
Цитата(ReAl @ Jan 27 2008, 12:30) *
Можно ещё было поразбираться - какие именно функции залазят в эти регистры - возможно, кроме 64-битных целых и, к примеру, плавающей точки, никто туда и не залазит, ....

Насколько я ничего не знаю, еще setjmp() и longjmp() могут портить R2-R7,
но если все вышеописаное не применяется, то вполне можно пользоваться ими
как зарезервированными.
Для себя, в случае такого резервирования, просто выработал правило после сборки
проверять листинг(просто поиском) на использование в тексте "чужих" конструкций с
зарезервированными мною регистрами.
defunct
Цитата(prottoss @ Jan 26 2008, 19:37) *
Обращаться к ним, по моему, тоже можно так же через указатели - ибо адреса регистров находятся в памяти данных с адреса 0!

Да все так и есть R0-R31 лежат в адресном пространстве SRAM с адресами 0x00-0x1F.

Цитата(prottoss @ Jan 26 2008, 21:32) *
__flash меняется на const

#define __flash const
smile.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.