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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Использование битовых областей в IAR (ATMega128)
IF_P
сообщение Feb 9 2010, 14:21
Сообщение #1


Частый гость
**

Группа: Участник
Сообщений: 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(...);

В другом случае при использовании локальных переменых в п/п. При входе в п/п мои р-ры сохранялись, а на их место определялись локальные переменные. Не выходя из этой п/п (т.е. не восстанавливая мои биты) я захожу в другую п/п, где использую указанные биты, которых там уже нет.
И я, вроде, делаю все правильно и компилятор тоже.
Как выйти из такой ситуации?. Не использовать р-ровый файл? А что использовать? Р-ры в/в? crying.gif
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
Go to the top of the page
 
+Quote Post
Stanislav_S
сообщение Feb 9 2010, 14:32
Сообщение #2


извечный пессимист
*****

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



Для начала почитайте - AVR035: Efficient C Coding for AVR. Станет немного понятней. Если сильно хотите, то можно использовать регистрв ввода вывода, например регистры таймеров которые не используются, но надо понимать что у АВР нет такого битового пространства как в 51. А лучше все таки почитайте для начала документ.


--------------------
Slaves are those of this world
Given freedom to lay chains upon The Master
The wolf is no longer free
Release the chains and come for me
Go to the top of the page
 
+Quote Post
V_G
сообщение Feb 9 2010, 14:58
Сообщение #3


Профессионал
*****

Группа: Свой
Сообщений: 1 818
Регистрация: 15-10-09
Из: Владивосток
Пользователь №: 52 955



Я переходил с 51 на Мегу где-то лет 7-8 назад. Программирую на ассемблере до сих пор. Тоже не хватало битового массива, отвожу несколько регистров из регистрового файла под аналог этого массива. Проблем с самопроизвольным изменением битов нет.
Go to the top of the page
 
+Quote Post
SergeyTT
сообщение Feb 9 2010, 16:52
Сообщение #4


Участник
*

Группа: Участник
Сообщений: 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(...);

В другом случае при использовании локальных переменых в п/п. При входе в п/п мои р-ры сохранялись, а на их место определялись локальные переменные. Не выходя из этой п/п (т.е. не восстанавливая мои биты) я захожу в другую п/п, где использую указанные биты, которых там уже нет.
И я, вроде, делаю все правильно и компилятор тоже.
Как выйти из такой ситуации?. Не использовать р-ровый файл? А что использовать? Р-ры в/в? crying.gif
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) здесь до лампады,
как-бы гуру-супермодераторы не возмущались по этому поводу ;-)
Go to the top of the page
 
+Quote Post
IF_P
сообщение Feb 10 2010, 00:11
Сообщение #5


Частый гость
**

Группа: Участник
Сообщений: 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

Так что придется снова возвращаться к р-рам в/в. Только вот что делать, если в будущем придется задействовать эти р-ры?
Go to the top of the page
 
+Quote Post
SSerge
сообщение Feb 10 2010, 02:09
Сообщение #6


Профессионал
*****

Группа: Свой
Сообщений: 1 719
Регистрация: 13-09-05
Из: Novosibirsk
Пользователь №: 8 528



Неужели эти несколько тактов так критичны, что Вы пускаетесь во все тяжкие?

Оставьте ассемблерные привычки, пишите на С.
Регистры процессора, счётчик команд, указатель стека и регистр состояния - всё это забота компилятора, пусть он ими занимается.
Установите в настройках проекта максимальный уровень оптимизации по скорости и больше не сокрушайтесь об эффективности, лучше потратить время на оптимизацию алгоритма на верхнем уровне, больше выиграете.
Листинг, впрочем, иногда смотреть полезно.


--------------------
Russia est omnis divisa in partes octo.
Go to the top of the page
 
+Quote Post
alux
сообщение Feb 10 2010, 03:33
Сообщение #7


Знающий
****

Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447



Цитата(IF_P @ Feb 10 2010, 04:11) *
Так что придется снова возвращаться к р-рам в/в. Только вот что делать, если в будущем придется задействовать эти р-ры?

В будущем (и настоящем) можно без проблем заменить на новую ATmega1281. В новых микроконтроллерах есть для этой цели отдельные General Purpose I/O Register 0/1/2.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Feb 10 2010, 05:09
Сообщение #8


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(SergeyTT @ Feb 9 2010, 19:52) *
Многократное объявление переменной в разных программных модулях(#include flags.h) здесь до лампады,

Если Вы самоубийца, то зачем тянуть за собой остальную компанию?
Go to the top of the page
 
+Quote Post
V_G
сообщение Feb 10 2010, 06:51
Сообщение #9


Профессионал
*****

Группа: Свой
Сообщений: 1 818
Регистрация: 15-10-09
Из: Владивосток
Пользователь №: 52 955



На ассемблере для регистрового файла есть битовые операции записи из флага T в бит регистра:
BLD reg,bit
и чтения из регистра во флаг T:
BST reg,bit

Установка/сброс флага T: SET/CLT

Проверка бита на 0: SBRC reg,bit
На 1: SBRS reg,bit

Логика операций с битами несколько отличается от 51 машины, но в принципе достаточно быстра и при работе на ассемблере проблем не вызывает
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Feb 10 2010, 07:18
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(IF_P @ Feb 9 2010, 17:21) *
Кто что может посоветовать?

Побыстрее бросайте эти немотивированные изыски.
Памяти не хватает? Быстродействия?
Если точно не хватает, замените контроллер.
Зачем плодить непереносимый код - не понимаю.


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
IF_P
сообщение Feb 10 2010, 11:44
Сообщение #11


Частый гость
**

Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Feb 10 2010, 20:04
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 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, и т.д. Решение - запрет прерываний.
Работа с битами на уровне МК, в общем то, не хуже.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Feb 10 2010, 21:39
Сообщение #13


;
******

Группа: Участник
Сообщений: 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;
итд итп
}
}
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Feb 11 2010, 10:03
Сообщение #14


Гуру
******

Группа: Модераторы
Сообщений: 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)
Go to the top of the page
 
+Quote Post
IF_P
сообщение Feb 11 2010, 10:30
Сообщение #15


Частый гость
**

Группа: Участник
Сообщений: 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 команд). Так что, имеем то, что имеем wassat.gif
Go to the top of the page
 
+Quote Post

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

 


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


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