|
Использование битовых областей в IAR (ATMega128) |
|
|
|
Feb 9 2010, 14:21
|
Частый гость
 
Группа: Участник
Сообщений: 136
Регистрация: 2-01-06
Пользователь №: 12 772

|
Перешел на ATMega128 после 51-го. Не нашел здесь битового пространства. Т.е. либо использовать регистровый файл, либо р-ры I/O 0-1F. С р-рами в/в я уже обжегся, использовав бит аппаратного прерывания. Хотя в документации написано, что данный бит программно R/W. Начал использовать общие р-ры 8-13: __no_init bitfield FLAG_2@0x08; #define flag_wait FLAG_2.bit0 #define flag_ESC FLAG_2.bit1 #define flag_in FLAG_2.bit2 Но вот в некоторых случаях начали проявляться программные глюки - самопроизвольное изменение некоторых бит. В одном случае это было при использовании retrurn atoi(...); В другом случае при использовании локальных переменых в п/п. При входе в п/п мои р-ры сохранялись, а на их место определялись локальные переменные. Не выходя из этой п/п (т.е. не восстанавливая мои биты) я захожу в другую п/п, где использую указанные биты, которых там уже нет. И я, вроде, делаю все правильно и компилятор тоже. Как выйти из такой ситуации?. Не использовать р-ровый файл? А что использовать? Р-ры в/в? RAM не хотелось бы использовать, а то при каждой установке/сбросе выполняется аж 5 команд: str.bitOne=1; LDI R30, LOW(str) LDI R31, (str) >> 8 LD R16, Z ORI R16, 0x01 ST Z, R16 Кто что может посоветовать? IAR только начал изучать. Может есть какие настройки, чтобы избежать подобных ситуаций?
Сообщение отредактировал IF_P - Feb 9 2010, 14:25
|
|
|
|
|
Feb 9 2010, 16:52
|
Участник

Группа: Участник
Сообщений: 53
Регистрация: 3-07-06
Из: Харьков
Пользователь №: 18 533

|
Цитата(IF_P @ Feb 9 2010, 16:21)  Перешел на ATMega128 после 51-го. Не нашел здесь битового пространства. Т.е. либо использовать регистровый файл, либо р-ры I/O 0-1F. С р-рами в/в я уже обжегся, использовав бит аппаратного прерывания. Хотя в документации написано, что данный бит программно R/W. Начал использовать общие р-ры 8-13: __no_init bitfield FLAG_2@0x08; #define flag_wait FLAG_2.bit0 #define flag_ESC FLAG_2.bit1 #define flag_in FLAG_2.bit2 Но вот в некоторых случаях начали проявляться программные глюки - самопроизвольное изменение некоторых бит. В одном случае это было при использовании retrurn atoi(...); В другом случае при использовании локальных переменых в п/п. При входе в п/п мои р-ры сохранялись, а на их место определялись локальные переменные. Не выходя из этой п/п (т.е. не восстанавливая мои биты) я захожу в другую п/п, где использую указанные биты, которых там уже нет. И я, вроде, делаю все правильно и компилятор тоже. Как выйти из такой ситуации?. Не использовать р-ровый файл? А что использовать? Р-ры в/в? RAM не хотелось бы использовать, а то при каждой установке/сбросе выполняется аж 5 команд: str.bitOne=1; LDI R30, LOW(str) LDI R31, (str) >> 8 LD R16, Z ORI R16, 0x01 ST Z, R16 Кто что может посоветовать? IAR только начал изучать. Может есть какие настройки, чтобы избежать подобных ситуаций? Если вы хотите работать с анонимными битовыми полями,попробуйте вот это: // в хидере,например, flags.h,делаем объявление __no_init volatile union { unsigned char flags; struct { unsigned char flag_wait :1; unsigned char flag_ESC :1; unsigned char flag_in :1; }; }@<здесь пропишите адрес ОЗУ,где будет храниться этот юнион,например,начальный адрес свободного ОЗУ,по вкусу>; Далее инклудите этот хидер в модули,где есть обращение к нужным флажкам,и спокойно работаете с ними,например: if(flag_wait) flag_ESC = 0; else flag_in = 1; Компилятор создаст в ОЗУ переменную _A_flags и будет дергать биты командами установки/сброса конкретного бита. Многократное объявление переменной в разных программных модулях(#include flags.h) здесь до лампады, как-бы гуру-супермодераторы не возмущались по этому поводу ;-)
|
|
|
|
|
Feb 10 2010, 00:11
|
Частый гость
 
Группа: Участник
Сообщений: 136
Регистрация: 2-01-06
Пользователь №: 12 772

|
Цитата(SergeyTT @ Feb 9 2010, 18:52)  Если вы хотите работать с анонимными битовыми полями,попробуйте вот это: // в хидере,например, flags.h,делаем объявление __no_init volatile union
...
flag_ESC = 0;
Компилятор создаст в ОЗУ переменную _A_flags Так я ведь в своем первом посте тоже привел пример битовой переменной, как элемента структуры и ее ассемблерную мнемонику. Только опустил описание самой структуры. Все это я использовал. Но не хотел размещать в RAM, т.к. это уже работа с байтами. При описании структуры в RAM получим: flag_ESC=1;LDI R30, 15 (дизассемб) LDI R31, 0 LD R16, Z ORI R16, 0x01 ST Z, R16 А при использовании р/р в/в (ADCH) уже совсем иначе: __no_init volatile bitfield Flag_W@0x25; #define Flag_W1 Flag_W.bit0 #define Flag_W2 Flag_W.bit1 Flag_W1=1; SBI 0x05, 0x00 Flag_W2=0; CBI 0x05, 0x01 Так что придется снова возвращаться к р-рам в/в. Только вот что делать, если в будущем придется задействовать эти р-ры?
|
|
|
|
|
Feb 10 2010, 02:09
|
Профессионал
    
Группа: Свой
Сообщений: 1 719
Регистрация: 13-09-05
Из: Novosibirsk
Пользователь №: 8 528

|
Неужели эти несколько тактов так критичны, что Вы пускаетесь во все тяжкие?
Оставьте ассемблерные привычки, пишите на С. Регистры процессора, счётчик команд, указатель стека и регистр состояния - всё это забота компилятора, пусть он ими занимается. Установите в настройках проекта максимальный уровень оптимизации по скорости и больше не сокрушайтесь об эффективности, лучше потратить время на оптимизацию алгоритма на верхнем уровне, больше выиграете. Листинг, впрочем, иногда смотреть полезно.
--------------------
Russia est omnis divisa in partes octo.
|
|
|
|
|
Feb 10 2010, 03:33
|
Знающий
   
Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447

|
Цитата(IF_P @ Feb 10 2010, 04:11)  Так что придется снова возвращаться к р-рам в/в. Только вот что делать, если в будущем придется задействовать эти р-ры? В будущем (и настоящем) можно без проблем заменить на новую ATmega1281. В новых микроконтроллерах есть для этой цели отдельные General Purpose I/O Register 0/1/2.
|
|
|
|
|
Feb 10 2010, 07:18
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(IF_P @ Feb 9 2010, 17:21)  Кто что может посоветовать? Побыстрее бросайте эти немотивированные изыски. Памяти не хватает? Быстродействия? Если точно не хватает, замените контроллер. Зачем плодить непереносимый код - не понимаю.
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Feb 10 2010, 11:44
|
Частый гость
 
Группа: Участник
Сообщений: 136
Регистрация: 2-01-06
Пользователь №: 12 772

|
Цитата(SSerge @ Feb 10 2010, 04:09)  Неужели эти несколько тактов так критичны, что Вы пускаетесь во все тяжкие? ... Оставьте ассемблерные привычки, пишите на С. ... Листинг, впрочем, иногда смотреть полезно. Так ведь и речь идет о С. На ассемблере этих проблем нет. И именно из листинга я и привел ассемблерную мнемонику С-шных команд. Что касается "несколько тактов", то у меня около 10 байт битовых переменных, которые активно используются (установка, сброс, анализ). В даном случае для меня абсолютно не критично ни количество тактов, ни размер памяти. Вопрос был в том, чтобы разобраться с использованием битов. А что касается оптимизации компилятором, то я считаю,что лучше самому продумать, по возможности, все варианты оптимизации и до и во время написания программы, чем полагаться на компилятор. Ведь компиляторы тоже пишут люди и они ошибаются. Мне уже приходилось по несколько дней искать "глюки" (Franklin, Keil). А потом оказывается, что это "глюк" компилятора. И абсолютно правильно написанный код приходится переписывать под компилятор. У каждого свой подход к программированию. "Делай как можно лучше. А оно все равно будет хуже". Так меня еще в детстве мать учила. А если делать кое-как, то результат может быть плачевным. Я не претендую на истину, но каждому свое. Спасибо всем за советы. To alux:Только General Purpose I/O Register 0 находится в бит-адресуемой области. Остальные за ее пределами (0x1F). Так что по битовым опрециям AVR уступает 8051. Цитата(SergeyTT @ Feb 9 2010, 18:52)  Многократное объявление переменной в разных программных модулях(#include flags.h) здесь до лампады, Для этих целей я обычно использую extern: extern bit Enable_Display; // CS для дешифратора LCD P1.0 extern bit DISPLAY_E; Это для Keil 51-го. Хотя там тоже были проблемы с их использованием http://electronix.ru/forum/index.php?showt...st&p=525347Для AVR и IAR пока не сталкивался.
Сообщение отредактировал IF_P - Feb 10 2010, 11:49
|
|
|
|
|
Feb 10 2010, 20:04
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Цитата(IF_P @ Feb 10 2010, 14:44)  Так ведь и речь идет о С. На ассемблере этих проблем нет. И именно из листинга я и привел ассемблерную мнемонику С-шных команд. Что касается "несколько тактов", то у меня около 10 байт битовых переменных, которые активно используются (установка, сброс, анализ). В даном случае для меня абсолютно не критично ни количество тактов, ни размер памяти. Вопрос был в том, чтобы разобраться с использованием битов. Тогда не понимаю в чём проблема. Используйте узаконенные в Си операции. Код struct { uint32_t Master :1, LoadActivCom :1, Str : 3, .... gEnd:1; } Flag; ....
if(Flag.Master) .... ....
Flag.Master = 1; // а хотите TRUE ... Flag.Master = Flag.gEnd; Flag.Str = 5; Чем не устраивает, или я чего-то не понимаю? Хотя я, в последнее время использую для этих целей байты. ======== Кстати о atxmega. Есть битовое поле и в ATMEGA88(48/168). The ATmega48/88/168 contains three General Purpose I/O Registers. These registers can be used for storing any information, and they are particularly useful for storing global variables and Status Flags. General Purpose I/O Registers within the address range 0x00 - 0x1F are directly bit-accessible using the SBI, CBI, SBIS, and SBIC instructions. PS: Если речь идет об атомарности доступа, то тут есть проблемы не только с битами, но и с любыми интегральными типами. Для x51, например, с int16/32, и т.д. Решение - запрет прерываний. Работа с битами на уровне МК, в общем то, не хуже.
|
|
|
|
|
Feb 10 2010, 21:39
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(IF_P @ Feb 10 2010, 15:44)  А что касается оптимизации компилятором, то я считаю,что лучше самому продумать, по возможности, все варианты оптимизации и до и во время написания программы, чем полагаться на компилятор. Ведь компиляторы тоже пишут люди и они ошибаются. Мне уже приходилось по несколько дней искать "глюки" (Franklin, Keil). А потом оказывается, что это "глюк" компилятора. И абсолютно правильно написанный код приходится переписывать под компилятор. Ну, это уж слишком! Глюки компилятора, во-первых, интенсивно фикcятся большим кол-вом людей, во-вторых, можно просто заглянуть в листинг и все там увидеть. По поводу битовых полей. Структуры с размером в 1 бит, объединенные в байты - это самое оптимальное и единственно прямое решение на данной архитектуре, без намека на оверхед. Код union { uint8_t flags; struct { unsigned flag0:1; unsigned flag1:1; итд итп } }
|
|
|
|
|
Feb 11 2010, 10:03
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(IF_P @ Feb 10 2010, 13:44)  Мне уже приходилось по несколько дней искать "глюки" (Franklin, Keil). А потом оказывается, что это "глюк" компилятора. Приносите, показывайте. Тут на весь форум реальных глюков компилятора обнаруживается 2-3 за год, все остальные - от незнания стандарта писателем программы или его же нежелания прочесть документацию на компилятор. Нет, можно конечно предположить, что вы такой везучий и вам их (настоящих глюков) попалось значительно больше, но верится в это с трудом. "Код в студию!".
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Feb 11 2010, 10:30
|
Частый гость
 
Группа: Участник
Сообщений: 136
Регистрация: 2-01-06
Пользователь №: 12 772

|
Цитата(SasaVitebsk @ Feb 10 2010, 22:04)  Тогда не понимаю в чём проблема. Используйте узаконенные в Си операции.
Чем не устраивает, или я чего-то не понимаю? Да я это все давно использую. Только заглянув в листинг я увидел, что для установки/сброса одного бита выполняется целый ряд команд, котрые я и указал в первом посте. Привожу еще раз: str.bitOne=1; - установка бита в структуре str а это ассемблерная мнемоника этой же команды: LDI R30, LOW(str) LDI R31, (str) >> 8 LD R16, Z ORI R16, 0x01 ST Z, R16 Т.е. , вместо одной команды SBI, CBI,... выполняется целых 5. Вот я и начал разбираться. В 51-м для этих целей существует битовое поле. Аналогичное я начал искать здесь. Оказывается AVR этим не богат. Битовые операции поддерживают только р-ры в/в с адресами 0x0-0x1F. А для своих нужд здесь ничего нет. И даже из указанных вами General Purpose I/O Registers только один находится в бит-адресуемом пространстве. К двум другим обращение будет идти указанным выше способом 5 команд). Так что, имеем то, что имеем
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|