|
Рассуждения о _regvar и register, Вынесено из темы "Глюки компилятора.." |
|
|
|
Jan 26 2008, 14:00
|
Местный
  
Группа: Новичок
Сообщений: 239
Регистрация: 5-10-06
Пользователь №: 21 004

|
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 Кб)
Сообщение отредактировал kamedi_clab - Jan 26 2008, 14:08
|
|
|
|
|
 |
Ответов
(1 - 49)
|
Jan 26 2008, 14:24
|

Гуру
     
Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659

|
Цитата(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 Кб) А что не понятного?  Компилятор же вам честно говорит - Registers must be locked with --lock_regs .... before __regvar can be usedРазберетесь - заодно и людей, читающих курс научите IAR for AVR, к сожалению, сейчас нет, но разве можно регистровые переменные объявлять как Код __no_init __regvar volatile uint16_t sineTableIncrement @14; Я так понимаю - __regvar - это уже тип, а вы к нему еще и uint16_t прицепили
--------------------
|
|
|
|
|
Jan 26 2008, 14:44
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(prottoss @ Jan 26 2008, 17:24)  Я так понимаю - __regvar - это уже тип, а... Нет, это Memory Attribute - ничем принципиально не отличающийся от подобного назначения __flash, __eeprom, __far и прочих прочих.... Цитата(kamedi_clab @ Jan 26 2008, 17:00)  Error[Pa043]... И почему для этого вопроса была выбрана тема "глюки компилятора"????????
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jan 26 2008, 15:59
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(Qwertty @ Jan 26 2008, 18:50)  А что спецификатор типа памяти register ИАР не понимает? Понимает, точнее, как и подавляющее большинство нынешних компиляторов молча игнорирует. Цитата Зачем еще __regvar изобретать? Это совсем другое - если прочитаете сообщение об ошибке - поймете, что речь идет о глобально зарезервированном для каких-то нужд регистре.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jan 26 2008, 15:59
|

Просто Che
    
Группа: Свой
Сообщений: 1 567
Регистрация: 22-05-07
Из: ExUSSR
Пользователь №: 27 881

|
Цитата(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 тоже не имел никакого отношения к глюкам компилятора, то вопрос помещен в правильную тему
|
|
|
|
|
Jan 26 2008, 16:21
|
Местный
  
Группа: Свой
Сообщений: 408
Регистрация: 21-10-06
Из: Санкт-Петербург
Пользователь №: 21 527

|
Цитата(zltigo @ Jan 26 2008, 18:59)  Понимает, точнее, как и подавляющее большинство нынешних компиляторов молча игнорирует. Ну не совсем игнорируют. Просто компилятор обычно сам решает размещать переменную в регистре или нет. Но если все переменные в доступные регистры не влезают, то объявленные с register будут иметь приоритет. Цитата(zltigo @ Jan 26 2008, 18:59)  Это совсем другое - если прочитаете сообщение об ошибке - поймете, что речь идет о глобально зарезервированном для каких-то нужд регистре. Спасибо, понял. Это типа как в ГЦЦ регистр для хранения 0. Хотя не понятен смысл объявления глобальных переменных в регистрах. Слишком много это вызовет ограничений, у таких переменных даже адрес взять нельзя, возможность работы посредством указателя теряется.
|
|
|
|
|
Jan 26 2008, 16:30
|
Местный
  
Группа: Новичок
Сообщений: 239
Регистрация: 5-10-06
Пользователь №: 21 004

|
Цитата(prottoss @ Jan 26 2008, 17:24)  Я так понимаю - __regvar - это уже тип, а вы к нему еще и uint16_t прицепили Это писатели из ATMEL прицепили в AVR447 - я думаю они знали что делали. Но проект положить в архив "забыли". Я лишь попытался создать проект IAR под исходники и скомпилить. Получилось теперь.
|
|
|
|
|
Jan 26 2008, 16:37
|

Гуру
     
Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659

|
Цитата(Qwertty @ Jan 26 2008, 23:21)  Спасибо, понял. Это типа как в ГЦЦ регистр для хранения 0. Хотя не понятен смысл объявления глобальных переменных в регистрах. Слишком много это вызовет ограничений, у таких переменных даже адрес взять нельзя, возможность работы посредством указателя теряется. Никаких, по моему ограничений нет. Я пару лет назад делал проект на ATTiny2313 на IAR на С. Тоже много глобальных переменных делал регистровых таким же макаром. Обращаться к ним, по моему, тоже можно так же через указатели - ибо адреса регистров находятся в памяти данных с адреса 0! И код, кстати получается практически таким же, как пишешь на ассемблере. Только, в добавок, получаешь все преимущества языка высокого уровня.
--------------------
|
|
|
|
|
Jan 26 2008, 16:49
|
Местный
  
Группа: Свой
Сообщений: 408
Регистрация: 21-10-06
Из: Санкт-Петербург
Пользователь №: 21 527

|
Цитата(prottoss @ Jan 26 2008, 19:37)  Обращаться к ним, по моему, тоже можно так же через указатели - ибо адреса регистров находятся в памяти данных с адреса 0! К&R, second edition - " Кроме того, применительно к регистровой переменной независимо от того, выделен на самом деле для нее регистр или нет, не определено понятие адреса ". И далеко не все ядра отражают регистры на ОЗУ.
Сообщение отредактировал Qwertty - Jan 26 2008, 16:50
|
|
|
|
|
Jan 26 2008, 16:59
|

Гуру
     
Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659

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

Просто Che
    
Группа: Свой
Сообщений: 1 567
Регистрация: 22-05-07
Из: ExUSSR
Пользователь №: 27 881

|
Цитата(Qwertty @ Jan 26 2008, 18:21)  Спасибо, понял. Это типа как в ГЦЦ регистр для хранения 0. Хотя не понятен смысл объявления глобальных переменных в регистрах. Слишком много это вызовет ограничений, у таких переменных даже адрес взять нельзя, возможность работы посредством указателя теряется. В регистрах обычно объявляю глобальные флаги. Операции работы с ними получаются атомарными, сама модификация бита в одну команду процессора. Доступ к флагам, сохраняемым в обычной памяти, длительный. Изменение такого флага это три команды: read-modify-write. А если при этом флаг может изменятся как из основного цикла, так и из прерывания, то приходится в основном цикле еще и запрещать прерывания  Итого пять команд вместо одной-двух. А накладных расходов при занимании нескольких регистров немного. Библиотеки используют эти регистры только в математических функциях. Все остальное обычно помещается в стек, к нему доступ удобнее, чем к регистрам R0..R15
|
|
|
|
|
Jan 26 2008, 17:42
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(Qwertty @ Jan 26 2008, 19:21)  Ну не совсем игнорируют. Поверьте моему опыту - игнорирут. Посмотрите документацию на любимый компилятор и увидете чего-нибудь типа User requests for register variables are ignored. Цитата(Qwertty @ Jan 26 2008, 19:21)  Спасибо, понял. Это типа как в ГЦЦ регистр для хранения 0. Ну очень ограниченое сравнение. В частности полный аналог описанного это --zero_register
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jan 26 2008, 18:19
|
Местный
  
Группа: Свой
Сообщений: 408
Регистрация: 21-10-06
Из: Санкт-Петербург
Пользователь №: 21 527

|
Цитата(zltigo @ Jan 26 2008, 20:42)  Поверьте моему опыту - игнорирут. Посмотрите документацию на любимый компилятор и увидете чего-нибудь типа User requests for register variables are ignored. Посмотрю. Или подожду когда в тред заглянет aesok , чтобы не копаться в куче страниц Цитата(zltigo @ Jan 26 2008, 20:42)  Ну очень ограниченое сравнение. В частности полный аналог описанного это --zero_register __zero_reg__, R1, это то же самое про что Вы говорите? Или имеется ввиду R0? С флагами в регистрах понятно, но я все же иду на сохранение/восстановление прерываний. Все равно немедленной реакции на установленный флаг не будет ( иначе что мешает сразу выполнить обработчик взведенного флага), так что пару лишних команд/тактов на это выделить можно. Зато из за таких "фокусов", хотя и не только из за них, С-ные программы чаще всего непереносимы с платформы на платформу. Никакие HAL тут уже не помогут... По поводу ИАР-овских расширений - если расширения начинают противоречить стандартам языка, то я например, не стал бы ими пользоваться. А тут противоречие налицо - возможен указатель на регистровую переменную. Нафиг такие расширения
|
|
|
|
|
Jan 26 2008, 18:49
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(zltigo @ Jan 26 2008, 20:42)  Поверьте моему опыту - игнорирут. Посмотрите документацию на любимый компилятор и увидете чего-нибудь типа User requests for register variables are ignored. А если любимый gcc ? Он не игнорирует и я этим иногда пользуюсь, только нужно проявлять осторожность при использовании библиотек в случае объявления большого количества регистровых переменных(ну или листинг смотреть...).
|
|
|
|
|
Jan 26 2008, 18:52
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(Qwertty @ Jan 26 2008, 21:19)  __zero_reg__, R1, это то же самое про что Вы говорите? Или имеется ввиду R0? Нет, R15 - да бог с ними. Цитата По поводу ИАР-овских расширений - если расширения начинают противоречить стандартам языка, то я например, не стал бы ими пользоваться. Заодно можете перестать пользоватся простенькими с контроллерами, которые вследствии этого имеют дивное количество вариантов памятей с уникальными адресациями. Ресурсов у таких контроллеров тоже не густо, посему АСMообразные финты тоже бывают много более полезны, нежели у свежих собратьев. Для, например, ARM контроллеров у того-же IAR расшрений языка абсолютный минимум.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jan 26 2008, 19:05
|
Местный
  
Группа: Свой
Сообщений: 408
Регистрация: 21-10-06
Из: Санкт-Петербург
Пользователь №: 21 527

|
Цитата(prottoss @ Jan 26 2008, 21:32)  ...если расширения начинают противоречить стандартам языка... - слишком громко сказанно:-) Украл батон - преступление? Или слишком громко сказано?  Из мелочей все и состоит, тут отступим, там переиначим, глядишь и получим из C Джаву  Цитата(prottoss @ Jan 26 2008, 21:32)  ИМХО фишка с регистрами, нууу оччень для мелких камней типа Tiny. Программы для них зачастую заточены только под эти камни. Да и, в принципе, перенести такой код не проблема - к ногтю __reg_var и все дела, так же как и при смене архитектуры CPU __flash меняется на const Ну разве что заточены и переносить на другой никогда не понадобится. А к ногтю __reg_var и потом вылавливать странные баги из-за незапрещенных прерываний во время модификации флага вне прерывания это хорошо? И с __flash не все так очевидно, можно получить например массив шрифта в ... ОЗУ, с запретом его модифицировать  Цитата(singlskv @ Jan 26 2008, 21:49)  А если любимый gcc ? Он не игнорирует и я этим иногда пользуюсь, только нужно проявлять осторожность при использовании библиотек в случае объявления большого количества регистровых переменных(ну или листинг смотреть...). Тоже проигнорирует, особенно в случае большого количества регистровых переменных. Я правда больше пары штук не пробовал, обычно индекс массива или указатель объявляю как register. А можете поподробнее про осторожность? Чего опасаться?
|
|
|
|
|
Jan 26 2008, 19:21
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(singlskv @ Jan 26 2008, 21:49)  А если любимый gcc ? Он не игнорирует и я этим иногда пользуюсь, Исключения, только подтверждают правила  . Цитата только нужно проявлять осторожность при использовании библиотек в случае объявления большого количества регистровых переменных(ну или листинг смотреть...). Да ну? У Вас совершенно ошибочные  представления о квалификаторе register, даже в случаях если он не игнорируется в принципе, он носит только рекомендательный характер. Цитата(Qwertty @ Jan 26 2008, 22:05)  А можете поподробнее про осторожность? Чего опасаться? Абсолютно нечего - безопасно.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jan 26 2008, 19:46
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

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

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(singlskv @ Jan 26 2008, 22:46)  Эксперименты ставить будем ?  Нет для начала будем читать (пост #69) о чем идет речь речь идет о квалификаторе register. Цитата Для затравки, предлагаю объявить регистры R0,R1 байтовыми переменными... Давайте - есть квалификатор register описанный в стандарте языка. Давайте попробуйте с его помощью сделать вышеобещанное. Готов внимать. Цитата Если не убедит, подгоню примеры повеселее....  Да и так уже не скучно.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jan 26 2008, 20:09
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(zltigo @ Jan 26 2008, 23:03)  Нет для начала будем читать (пост #69) о чем идет речь речь идет о квалификаторе register. Давайте - есть квалификатор register описанный в стандарте языка. Давайте попробуйте с его помощью сделать вышеобещанное. Готов внимать. register unsigned char mynull asm("r0"); ...... mynull=255; попробуйте, не пожалеете...
|
|
|
|
|
Jan 26 2008, 20:22
|

Просто Che
    
Группа: Свой
Сообщений: 1 567
Регистрация: 22-05-07
Из: ExUSSR
Пользователь №: 27 881

|
Цитата(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. Так что все абсолютно безопасно
|
|
|
|
|
Jan 26 2008, 20:47
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(zltigo @ Jan 26 2008, 23:22)  Если Вы это срьезно, то ну и каша у Вас в голове  . Ну кашу я вобще не ем, кроме разьве что гречневой, так что в голове она у меня редкая гостья  ну перечитываем тогда что ли пост №68 с которого и началась дискуссия: Цитата(Qwertty @ Jan 26 2008, 18:50)  А что спецификатор типа памяти register ИАР не понимает? Зачем еще __regvar изобретать? так вот gcc его понимает и пользуется им для размещения переменных в регистрах...
|
|
|
|
|
Jan 26 2008, 20:52
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(singlskv @ Jan 26 2008, 23:47)  ...так что в голове она у меня редкая гостья  1. Это не С, это асмовская вставка в стиле одного из диалектов со всеми вытекающими последствиями для компиляции и оптимизации. 2. Читаем стандарт языка C99. 3. Без register должно быть аналогично.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jan 26 2008, 21:01
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

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

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(singlskv @ Jan 27 2008, 00:01)  Тока Вы похоже опять забыли... Я прекрасно помню, на какой конкретный вопрос конкретно по register лично я отвечал :-E.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jan 26 2008, 21:17
|
Местный
  
Группа: Свой
Сообщений: 462
Регистрация: 26-06-07
Пользователь №: 28 723

|
Цитата(Qwertty @ Jan 27 2008, 00:06)  Это просто я тогда не понял, о чем идет речь. Вот и спросил о register и IAR. Я тоже сижу на ГЦЦ, и проблем с размещением в регистрах не испытывал. Правда номер регистра жестко не задаю. В документации к avr-libs указывается, что компилятор не контролирует конфликты в случае жесткого указания номера регистра. Документированные грабли и не грабли вовсе, а так, особенности реализации  Вообще говоря, не понимаю, зачем вообще при написании кода самим создавать себе проблемы - жестко указывать номера регистров для размещения переменных компилятору ? Выгоды практически никакой, а переносимость и надежность могут конкретно пострадать. Можно понять, если регистр особенный и с этой переменной надо что-то специфичное делать, но такой кусочек кода надо бы оформлять маленькой препроцессорной вставочкой/подпрограммкой, и подробно комментить.
|
|
|
|
|
Jan 26 2008, 21:19
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(Qwertty @ Jan 27 2008, 00:06)  Правда номер регистра жестко не задаю. В документации к avr-libs указывается, что компилятор не контролирует конфликты в случае жесткого указания номера регистра. Скажем так(насколько я ничего не понимаю...), R2-R8 можно почти всегда безболезненно, R9-R15 с контролем листинга, регистр без указания месторасположения почти не имеет смысла... по последнему пункту не уверен точно, тк в своих прогах предпочитаю месторасположение указывать явно... ЗЫ. конечно R2-R7 и R8-R15 ...
|
|
|
|
|
Jan 26 2008, 21:22
|
Знающий
   
Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484

|
Используя модификатор 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 не дает предупреждения, но это факт. Анатолий.
|
|
|
|
|
Jan 26 2008, 21:34
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

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

|
Цитата(singlskv @ Jan 27 2008, 00:19)  регистр без указания месторасположения почти не имеет смысла...
по последнему пункту не уверен точно, тк в своих прогах предпочитаю месторасположение указывать явно... Имеет, хотя ГЦЦ и сам достаточно умный и может разместить переменную в регистре даже без указания. Правда к глобальным это не относится, во всяком случае я такого не видел ни разу. А насчет смысла - например указатель выгодно хранить в регистре, тогда его изменении (++ или --) проходят гораздо быстрее. А так как такие операции обычно происходят в циклах, которые являются узким местом в программе, то использование регистров дает возможность сильно уменьшить время. При этом мне совсем не важно, в каких конкретно регистрах находится указатель. Правда оптимизатор и так обычно такой указатель разместит в регистрах  А вот явное месторасположение имеет смысл в основном для встроенного ассемблера.
|
|
|
|
|
Jan 26 2008, 21:48
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(Qwertty @ Jan 27 2008, 00:38)  А насчет смысла - например указатель выгодно хранить в регистре, тогда его изменении (++ или --) проходят гораздо быстрее. А так как такие операции обычно происходят в циклах, которые являются узким местом в программе, то использование регистров дает возможность сильно уменьшить время. Вот как раз для такой оптимизации использование register абслоютно беcсмысленно и может даже(в принципе) помешать компилятору.... Для таких кусков кода нужно грамотно использовать локальные переменные. Если хотите примеров, покажите кусок кода где register дал выигрыш, и я покажу как нужно было написать просто с локальными переменными.
|
|
|
|
|
Jan 26 2008, 21:55
|
Местный
  
Группа: Свой
Сообщений: 408
Регистрация: 21-10-06
Из: Санкт-Петербург
Пользователь №: 21 527

|
Цитата(singlskv @ Jan 27 2008, 00:34)  Вы можете спросить почему это не написано на асм. Потому что в качестве бонуса я получаю возможность обращаться к регистровым переменным как к обычным С переменным в обычном С коде... В свете того, что выше написал aesok о регистровых переменных и квалификаторе volatile, возможность обращаться к регистровым переменным, модифицируемым в прерывании, из С кода весьма сомнительна. Цитата(singlskv @ Jan 27 2008, 00:48)  Вот как раз для такой оптимизации использование register абслоютно беcсмысленно и может даже(в принципе) помешать компилятору.... Для таких кусков кода нужно грамотно использовать локальные переменные. Если хотите примеров, покажите кусок кода где register дал выигрыш, и я покажу как нужно было написать просто с локальными переменными. Это и есть локальная переменная. Я выше писал, что не объявляю глобальных переменных регистровыми. Сам по себе register даст выигрыщ только если локальных переменных много, тогда это будет подсказка оптимизатору о том, какие размещать в регистрах в первую очередь. Если локальная переменная одна, то она станет регистровой сама по себе  И перестанет показывать свое значение в студии  А вот помешать компилятору вряд-ли удастся, он просто молча проигнорирует register и все, даже варнинга не даст.
|
|
|
|
|
Jan 26 2008, 22:00
|
Местный
  
Группа: Свой
Сообщений: 462
Регистрация: 26-06-07
Пользователь №: 28 723

|
Код //------------------------------------------------------------------- // Прерывание системного таймера // используются только регистровые переменные // никакие регистры не сохраняются // SREG не сохраняется // ОБЯЗАТЕЛЬНО ПРОВЕРИТЬ СГЕНЕРИРОВАННЫЙ КОД !!!!!!!!!!!!!!!!!!!!! //------------------------------------------------------------------- там всего 8 команд + reti Но я точно знаю что я делаю. Так нельзя делать даже из самых лучших побуждений. Код, работающий по прерыванию и при этом портящий регистры и статус процессора - нонсенс, т.к. его исполнение может оказаться прервано другим таким же с большим приоритетом - с соответствующей порчей данных. Не говоря уже о том, что уменьшение числа регистров, доступных компилятору, ухудшает оптимизацию, и дополнительные загрузки-выгрузки легко съедят весь эффект, полученный в частной подпрограмме. Я однажды еще на ассемблере делал системный таймер в регистре процессора для системы быстрой регистрации, но код отработки прерывания не изменял в процессоре НИЧЕГО, кроме регистра таймера. Если хочется сэкономить такты - практичнее подумать над алгоритмом в целом или поменять МК, если экономится память - это вообще нонсенс, т.к. цена версий МК с разной памятью не сильно отличается. Чтобы окупить затраты на отладку такого "кода", потребуются многотысячные тиражи, и то не факт, что это рационально - резервов для апгрейда не останется. Еще для ускорения при отработке прерываний можно использовать теневой банк регистров (дополнительные банки есть у многих МК, от 8051 и Z80 до PIC32).
|
|
|
|
|
Jan 26 2008, 22:03
|
Местный
  
Группа: Свой
Сообщений: 408
Регистрация: 21-10-06
Из: Санкт-Петербург
Пользователь №: 21 527

|
Цитата(SIA @ Jan 27 2008, 01:00)  т.к. его исполнение может оказаться прервано другим таким же с большим приоритетом - с соответствующей порчей данных. У AVR этого никогда не произойдет  Я видел один раз похожий прием, правда на ассемблере - на Телесисах лежит проект генератора Л.И. Ридико. Там обработчик вообще начинается с адреса вектора и самая короткая ветка не сохраняет SREG. Но это сделано для того, чтобы выжать из контроллера все что можно и видимо такие задачи крайне редки. Хотя тоже имеют право на жизнь.
Сообщение отредактировал Qwertty - Jan 26 2008, 22:10
|
|
|
|
|
Jan 26 2008, 22:07
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(Qwertty @ Jan 27 2008, 00:55)  В свете того, что выше написал aesok о регистровых переменных и квалификаторе volatile, возможность обращаться к регистровым переменным, модифицируемым в прерывании, из С кода весьма сомнительна. По большому счету, квалификаторы register и volatile одновременно не применимы. При "жестком" расположении переменной в регистре volatile просто теряет смысл... Я не знаю примеров в которых "жестко" заданная регистровая переменная может портиться. Цитата Это и есть локальная переменная. Я выше писал, что не объявляю глобальных переменных регистровыми. Сам по себе register даст выигрыщ только если локальных переменных много, тогда это будет подсказка оптимизатору о том, какие размещать в регистрах в первую очередь. Если локальная переменная одна, то она станет регистровой сама по себе  И перестанет показывать свое значение в студии  А вот помешать компилятору вряд-ли удастся, он просто молча проигнорирует register и все, даже варнинга не даст. В таком варианте, согласен.
|
|
|
|
|
Jan 26 2008, 22:13
|
Знающий
   
Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484

|
Цитата(singlskv @ Jan 27 2008, 01:07)  По большому счету, квалификаторы register и volatile одновременно не применимы. При "жестком" расположении переменной в регистре volatile просто теряет смысл... Я не знаю примеров в которых "жестко" заданная регистровая переменная может портиться. В таком варианте, согласен. Почитайте пост, там описана проблема: http://electronix.ru/forum/index.php?showtopic=42140GCC ведет себя также. До веррсии 4.1 он выдавал предупреждение, потом перестал. Есть ключик чтобы его включть. Анатолий.
|
|
|
|
|
Jan 26 2008, 22:29
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(SIA @ Jan 27 2008, 01:00)  Так нельзя делать даже из самых лучших побуждений. Код, работающий по прерыванию и при этом портящий регистры и статус процессора - нонсенс, т.к. его исполнение может оказаться прервано другим таким же с большим приоритетом - с соответствующей порчей данных. Может конечно и нельзя .... Но я точно знаю что я делаю.используются только зарезервированные регистры и регистры переферии, код написан таким образом что SREG просто не меняется, напоминание "ПРОВЕРИТЬ КОД" именно про то, чтобы проверить что компилятор не начудил и не вставил инструкции меняющие SREG. Цитата(aesok @ Jan 27 2008, 01:13)  Почитайте пост, там описана проблема: http://electronix.ru/forum/index.php?showtopic=42140GCC ведет себя также. До веррсии 4.1 он выдавал предупреждение, потом перестал. Есть ключик чтобы его включть. Я не только читал но и писал в той ветке... Про проблемы с повтором констант я знаю, более того примерно с год назад я поднимал этот вопрос на форуме (ссылку лень искать сейчас, что то типа"Проблемы оптимизации WinAVR"). У меня все проблемы сводились к тому что код оказывался просто очень не оптимальным. У Вас есть пример кода для GCC который будет в такой ситуации некорректным ?
|
|
|
|
|
Jan 26 2008, 22:31
|
Местный
  
Группа: Свой
Сообщений: 462
Регистрация: 26-06-07
Пользователь №: 28 723

|
Цитата(singlskv @ Jan 27 2008, 01:17)  Может конечно и нельзя .... Но я точно знаю что я делаю.используются только зарезервированные регистры и регистры переферии, код написан таким образом что SREG просто не меняется, напоминание "ПРОВЕРИТЬ КОД" именно про то, чтобы проверить что компилятор не начудил и не вставил инструкции меняющие SREG. IMHO, это приемлемо только для очень маленького проекта, строк на 300-500. Более крупный при использовании таких методов становится слишком непрактичным. p.s. Эпоху, когда экономили каждый такт, я еще застал. Но не думаю, что сейчас это правильно - проще взять более мощный процессор, они сейчас недороги.
|
|
|
|
|
Jan 26 2008, 23:39
|
Знающий
   
Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484

|
Цитата(singlskv @ Jan 27 2008, 01:29)  Цитата Почитайте пост, там описана проблема: http://electronix.ru/forum/index.php?showtopic=42140GCC ведет себя также. До веррсии 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Анатолий.
|
|
|
|
|
Jan 27 2008, 09:30
|

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

|
Цитата(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-битных целых и, к примеру, плавающей точки, никто туда и не залазит, но я просто решил для себя - если желание разместить глобальные переменные в регистрах возникнет, значит это будет задача под чистый асм :-), "ведь играл писал же я их в молодости" (С) актёрская шутка.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Jan 27 2008, 10:03
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(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.
|
|
|
|
|
Jan 27 2008, 10:25
|
Знающий
   
Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484

|
Цитата(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 небезопасно использовать глобальные регистровые переменные. Только локальные. Анатолий.
|
|
|
|
|
Jan 27 2008, 20:23
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(ReAl @ Jan 27 2008, 12:30)  Можно ещё было поразбираться - какие именно функции залазят в эти регистры - возможно, кроме 64-битных целых и, к примеру, плавающей точки, никто туда и не залазит, .... Насколько я ничего не знаю, еще setjmp() и longjmp() могут портить R2-R7, но если все вышеописаное не применяется, то вполне можно пользоваться ими как зарезервированными. Для себя, в случае такого резервирования, просто выработал правило после сборки проверять листинг(просто поиском) на использование в тексте "чужих" конструкций с зарезервированными мною регистрами.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|