|
IAR EWAVR - как избавиться от лишних команд? |
|
|
|
Aug 27 2011, 14:37
|

Местный
  
Группа: Свой
Сообщений: 208
Регистрация: 6-07-04
Из: Полтава
Пользователь №: 279

|
В критичных по времени функциях использую зарезервированные РОН из нижней половины, в нижеуказанном примере r14 и r15: CODE ... volatile __regvar __no_init char Old_PINB @14; volatile __regvar __no_init char New_PINB @15; ... Old_PINB = New_PINB; New_PINB = PINB; ... Получаю в результате: CODE // 70 Old_PINB = New_PINB; MOV R14, R15 // 71 New_PINB = PINB; IN R16, 0x03 MOV R15, R16 В вышеуказанном примере последовательность команд IN R16,0x03 и MOV R15,R16 явно лишняя, достаточно было одной команды IN R15,0x03. Расходуется лишняя пара байтов и лишний такт. Казалось бы мелочь, но такого при работе с зарезервированными под переменные регистрами может набежать вполне прилично. Да, конечно, можно написать критичные по времени модули на ассемблере, но все же, если бы можно было избежать подобных несуразностей при компиляции сишного кода, было бы всяко лучше. Мог бы кто нибудь подсказать, как в EWAVR это можно побороть, или сия бага есть врожденная фича EWAVR?
|
|
|
|
|
 |
Ответов
|
Aug 27 2011, 17:12
|

Гуру
     
Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237

|
Цитата(kv_addr @ Aug 27 2011, 20:15)  В пункте Register Utilization я могу зарезервировать от одного (R15) до 12 (R4...R15) операционных регистров под глобальные переменные. Поскольку работать с переменными, расположенными в регистрах, можно быстрее, чем с переменными расположенными в ячейках ОЗУ, в критичных по времени функциях пытаюсь использовать такую возможность, что в моем случае вполне оправдано. Но компилятор генерирует не совсем оптимальный код, пример которого привел выше. Резервирование это одно, а компиляция через инструкцию IN - другое. Резервирование означает только то, что компилятору запрещается использовать эти регистры при генерации C-кода (причем за библиотеки компилятор отвественности не несет, т.к. получает их уже скомпилированными). Нечего кроме этого операция резервирование не означает. Т.е. только от этого память не станет регистром, а регистр не станет памятью. С точки зрения компилятора регистр отличается от памяти способом адресации. Хотя с точки зрения электронщика это может быть одно и тоже  . В отношении регистра компилятор использует команды IN и OUT, тогда как к памяти обращается по ее адресу. В этом и состоит это отличие. Регистры объявлены в хидере с помощью определения SFR_B или ему подобных, описанных в iomacro.h. Эти определения сильно компиляторозависимые, а потому не стоит повторять те приемы, которыми они там определятся как регистры, хотя самим SFR_B пользоваться вполне можно. Например так: SFR_B(Old_PINB, 14) SFR_B(New_PINB, 15) Но лучше, все-таки так не делать, а найти в хидере уже определенные имена регистров из области 14-го и 15-го байта. Там должно быть что-то вроде этого: SFR_B(?????, 0xE) SFR_B(?????, 0xF) Вот с этими именами, которые у меня записаны, как "?????", и нужно определить тождество через #define и тогда такие клоны тоже будут использоваться компилятором, как регистры. Попытки же использовать зарезервированное среди регистров место по адресу (@14 или @15) приводит лишь к тому, что это место используется, как память. Т.е. обращение к нему будет происходить по адресам 14 или 15, а не регистровыми опрациями IN/OUT. Цитата(kv_addr @ Aug 27 2011, 20:15)  Объясните, пожалуйста, если я хочу старое и новое значения байтов, полученных из порта PINB, хранить именно в РОН и дальше в функции работать именно с данными в этих регистрах (естественно, учитывая ограничения для нижних 16 РОН у AVR), то чем Ваши вышеуказанные дефайны могут мне помочь? Дефайны помогают тем, что отожествляют ваши имена Old_PINB и New_PINB с именами регистров, а не с памятью. А это позволяет обращаться к ним, как к регистрам, используя команды IN/OUT. А ваше определение этих имен, как переменных, с указанными для них адресами (@14 или @15), является определением для ячеек памяти. По этой причине компилятор в их отношении команды IN/OUT не использует. Я понимаю, что вы хотели бы, чтобы компилятор сам догадался, что по адресам 14 и 15 находятся регистры. Однако догадаться об этом он не может. Причина в том, что эти адреса считаются от начала сегмента кода! А где начинается сегмент кода знает только линкер, а компилятор этого не знает и знать не должен. Поэтому в данном случае вина лежит целиком на вашем корявом программировании, а не на компиляторе замечательной фирмы IAR. Цитата(kv_addr @ Aug 27 2011, 20:15)  У меня Old_PINB и New_PINB являются однобайтовыми глобальными переменными, расположенными в регистрах R14 и R15 соответственно, а отнюдь не регистры портов PORTE и PORTF. А в моем AT90USB647 по адресам 14 и 15 находятся именно регистры PORTE и PORTF! Вы ведь поленились назвать тип вашего МК? А раз так, то не имеете права выставлять мне претензий за то, что я ваши 14-ю и 15-ю ячейки неправильно отнесла. Телепатическими способностями в отношении вас я не обладаю, поэтому в своем прошлом ответе ограничилась вежливой формулировкой "имена регистров ищите в хидере, соответствующему вашему типу МК". Почему бы вам и в самом деле не посмотреть, как называются у вашего МК регистры, находящиеся в 14-ом и 15-ом байтах?
|
|
|
|
|
Aug 27 2011, 18:56
|

Местный
  
Группа: Свой
Сообщений: 208
Регистрация: 6-07-04
Из: Полтава
Пользователь №: 279

|
"Девушка, пожалуйста, не кричите очень громко, я Вас и так неплохо слышу"© Цитата А в моем AT90USB647 по адресам 14 и 15 находятся именно регистры PORTE и PORTF! Вы ведь поленились назвать тип вашего МК? Если Вас интересует контроллер, то в данном конкретном случае это ATmega88, хотя может быть и любой иной из атмеловских 8-биток, в том числе и Ваш AT90USB647. У них у всех имеются одни и те же 32 восьмибитных регистра общего назначения (РОН), по-импортному они еще называются General Purpose Working Registers. Ну, те самые, которые от R0 до R31 принято именовать. Вы, очень похоже, спутали их с регистрами ввода/вывода (РВВ), по-импортному I/O Registers, кои в общем адресном пространстве находятся над РОН. Видимо, ввиду атмеловских безобразий с нумерацией регистров и возникло это недоразумение. Тот же Ваш горячо любимый PORTE гады атмелцы нумеруют как 0x0E (0x2E), а PINF (не PORTF, тут Вы ошиблись) как 0x0E (0x2E). Дык, вот, как Вы могли уже заметить, я не собирался и не собираюсь использовать ни PORTE, ни даже PINF для хранения регистровых глобальных переменных, у меня запросы несколько скромнее:
А именно, как бы какое-то количество из нижних 12 РОН задействовать под быстродоступные переменные. Что в самом принципе компилятором допускается и я с удовольствием этой возможностью пользуюсь. Но вот только смущает несколько не совсем логичное поведение компилятора, плодящего избыточный код в казалось бы очевидной, однозначно интерпретируемой ситуации. Что же касательно Вашего предположения относительно того, что компилятор считает зарезервированный под переменную РОН как ячейку памяти, в которую напрямую без дополнительного РОН из старших 16, которые обычно используются компилятором в качестве локальных (в примере это R16), невозможно положить содержимое того же регистра ввода/вывода PINB, то может такое и можно было бы заподозрить, если бы для передачи байта из одного зарезервированного РОН в другой точно так же задействовался бы дополнительный РОН-костыль. Скажем, такое для переброса байта из одной ячейки в другую вполне нормально, команды ячейка/ячейка у этих контроллеров нет. Но ведь на самом деле в скомпилированном коде нет последовательности MOV R16,R15 MOV R14,R16 или нет даже попытки задействовать команды LD и ST, а байт передается одной вполне логичной командой MOV R14,R15. Т.е. здесь компилятор не пытается почесать левое ухо правой ногой. Так почему он боится напрямую передать байт из РВВ в РОН вполне логичной штатной командой, а пристегивает сюда еще один, явно не нужный РОН R16? Можно ли избежать этой несуразности компилятора? Надеюсь, я вполне внятно сформулировал вопрос?
|
|
|
|
Сообщений в этой теме
kv_addr IAR EWAVR - как избавиться от лишних команд? Aug 27 2011, 14:37 Xenia Когда переменная объявлена с адресом памяти (напри... Aug 27 2011, 15:25 kv_addr Цитата(Xenia @ Aug 27 2011, 19:25) Когда ... Aug 27 2011, 16:15 Палыч Цитата(Xenia @ Aug 27 2011, 21:12) от это... Aug 27 2011, 18:33   Палыч Цитата(Xenia @ Aug 27 2011, 23:00) ... эф... Aug 27 2011, 19:19    kv_addr Цитата(Палыч @ Aug 27 2011, 23:19) Нет, н... Aug 27 2011, 19:31     zhevak Цитата(kv_addr @ Aug 28 2011, 01:31) Собс... Aug 28 2011, 08:08      kv_addr Цитата(zhevak @ Aug 28 2011, 12:08) Ситуа... Aug 28 2011, 13:05 Xenia kv_addr, можно попросить вас выложить проектик для... Aug 28 2011, 14:14 kv_addr Цитата(Xenia @ Aug 28 2011, 18:14) kv_add... Aug 28 2011, 16:28  Xenia Цитата(kv_addr @ Aug 28 2011, 20:28) Нет ... Aug 28 2011, 19:17   kv_addr Цитата(Xenia @ Aug 28 2011, 23:17) Мне на... Aug 28 2011, 20:53   Палыч Цитата(Xenia @ Aug 28 2011, 23:17) с ваши... Aug 31 2011, 05:37   kv_addr Цитата(Xenia @ Aug 28 2011, 23:17) Мне на... Sep 2 2011, 13:41    Xenia Цитата(kv_addr @ Sep 2 2011, 17:41) И как... Sep 2 2011, 15:04     kv_addr Цитата(Xenia @ Sep 2 2011, 19:04) Никак. ... Sep 2 2011, 20:04 _Bill Цитата(kv_addr @ Aug 27 2011, 18:37) В кр... Aug 28 2011, 17:51 kv_addr Цитата(_Bill @ Aug 28 2011, 21:51) Скорее... Aug 28 2011, 18:34  _Bill Цитата(kv_addr @ Aug 28 2011, 22:34) . Эт... Aug 28 2011, 19:35
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|