Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Порты AVR и компиляция
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Страницы: 1, 2
allexmor
Очень долго работал с разными МК(51, в основном ARM) решил попробовать AVR вопросы:
У этих AVR что нет удобного побитового доступа к портам?
Какой компилятор делает наиболее красивый код?
defunct
Цитата(allexmor @ Sep 26 2007, 18:26) *
У этих AVR что нет удобного побитового доступа к портам?

есть, на запись - cbi/sbi
на чтение - sbic/sbis
но это будет "очень" побитовый доступ.

Такого как в ARM - IOSET/IOCLR в AVR нет.

Зато есть и хорошая сторона - такого "гонива" как в ARM - потребность применять 2 команды для записи конкретного значения в порт - в AVR'е тоже нет.
Пишете сразу действующее значение (пример):

PORTB = 0x55; // на выводах порта 0x55
PORTB = 0xAA; // на выводах порта 0xAA

Цитата
Какой компилятор делает наиболее красивый код?

IAR
Marian
Цитата(allexmor @ Sep 26 2007, 18:26) *
Очень долго работал с разными МК(51, в основном ARM) решил попробовать AVR вопросы:
У этих AVR что нет удобного побитового доступа к портам?


CVAVR дает побитовый доступ к портам (правда в некоторых процах не ко всем)

Код
PORTB.0 = 1;
DDRB.3  = 0;
sensor_ua
Цитата
такого гонива как потребность применять 2 команды для записи конкретного значения в порт как в ARM в AVR'е тоже нет.

Хм... Вы слегка заблуждаетесь, если говорите об LPC. В них совсем необязательно использовать IOSET/IOCLR - Вы можете просто модифицировать (чтение-модификация-запись) регистр IOPIN

Writing to the IOPIN register stores the value in the port output register, bypassing the
need to use both the IOSET and IOCLR registers to obtain the entire written value. This
feature should be used carefully in an application since it affects the entire port.

Чтение-модификация-запись возможно более привычная операция, но она неатомарна и без FIO дороже по времени (шина-то периферийная узковата). Неатомарность заставляет задумываться об использовании портов в обработчиках прерываний.
bodja74
Зато сразу IOPIN=0x5555AAAA; smile.gif smile.gif smile.gif
defunct
Цитата(sensor_ua @ Sep 26 2007, 19:48) *
Writing to the IOPIN register stores the value in the port output register, bypassing the
need to use both the IOSET and IOCLR registers to obtain the entire written value. This
feature should be used carefully in an application since it affects the entire port.

Ну... В реалиях этой фичей особо не попользуешься, особенно когда всего 1 порт, и после включения периферии остаются разрозненные, хаотически пронумерованные пины...
IOSET/IOCLR the only way to go в этом случае.

В AVR'е те же 32 пина разбиты на 4 порта, отсюда возможность проектирования девайса так, что можно обойтись без чтения-модификации-записи.
allexmor
Цитата(defunct @ Sep 27 2007, 02:19) *
Ну... В реалиях этой фичей особо не попользуешься, особенно когда всего 1 порт, и после включения периферии остаются разрозненные, хаотически пронумерованные пины...
IOSET/IOCLR the only way to go в этом случае.

В AVR'е те же 32 пина разбиты на 4 порта, отсюда возможность проектирования девайса так, что можно обойтись без чтения-модификации-записи.



Ну с портами все понятно.
На какой среде разработки остановиться?
в CodeVAVR - можно ли в проект загнать не один файл?
sensor_ua
Фаворит IAR. WinAVR вполне юзабилен, но когда нужно чуть более, чем дрыгать пинами, то с нуля нужно тратить больше времени для эффективного использования. CV - ничего не скажу, т.к. не пользую. Замечу только, что в последнее время автор предупреждает пользователей, что леченный продукт распознаётся и может не так чтобы совсем не работать, а генерировать неадекватный результат.
allexmor
Цитата(sensor_ua @ Sep 27 2007, 09:04) *
Фаворит IAR. WinAVR вполне юзабилен, но когда нужно чуть более, чем дрыгать пинами, то с нуля нужно тратить больше времени для эффективного использования. CV - ничего не скажу, т.к. не пользую. Замечу только, что в последнее время автор предупреждает пользователей, что леченный продукт распознаётся и может не так чтобы совсем не работать, а генерировать неадекватный результат.



Где можно IAR скачать? ну и крэк?
alexander55
Цитата(allexmor @ Sep 27 2007, 09:08) *
Где можно IAR скачать? ну и крэк?

Есть ветка про IAR. Там есть ответы на все вопросы (зачем здесь оффтоп).
mdmitry
WinAvr(gcc)+Eclipse - хорошая бесплатная связка для разработки. IAR поймал однажды на тесте с худшим результатом компиляции, чем gcc. Наверно, тест такой был sad.gif GNU как-то спокойнее, а то как его не ломали, а IAR - не ясно. Есть удобные макросы для работы.
P.S. Просьба не начинать религиозные войны по качеству кодогенерации компиляторов, они на форуме уже были.
IJAR
IMHO: После IAR другие компиляторы даже пробовать не хочется, ну все что было нужно
он делать умеет.
defunct
Цитата(IJAR @ Sep 27 2007, 09:51) *
IMHO: После IAR другие компиляторы даже пробовать не хочется, ну все что было нужно
он делать умеет.

Ну почему же. Упомянутый WinAVR очень не плох, к тому же бесплатный.
"глобальное" отличие между WinAVR и IAR лишь в использовании различных адресных пространств. В IAR это сделано на порядок лучше - __flash, __eeprom.
GDI
В CodeVision можно сделать несколько файлов в проекте, ну и несомненное его достоинство по сравнению с остальными - это наличие мастера проекта, который сам сделает все стартап коды, но когда появляются собственные библиотеки для IAR или GCC то надобность в мастере отпадает, как правило. Сам я работаю в ИАРе, но держу КодеВижон, именно для создания инитов.
Qwertty
Цитата(defunct @ Sep 27 2007, 12:56) *
Ну почему же. Упомянутый WinAVR очень не плох, к тому же бесплатный.
"глобальное" отличие между WinAVR и IAR лишь в использовании различных адресных пространств. В IAR это сделано на порядок лучше - __flash, __eeprom.

Ну да - __flash, __eeprom на порядок превосходят EEMEM, PROGMEM smile.gif
По теме - если дрыгать ножками, то любой. Если что-то серьезнее то WinAvr. Под него пишут сотни тысяч человек и в отличии от IAR их труды доступны в сети. Не придется адаптировать, бери и пользуйся. С ИАР-ом же придется в большинстве случаев решать все проблемы самому - типа файловых систем и т.п. Ну или адаптировать код от Winavr smile.gif У ИАРа одно преимущество - ассемблер встраивать легче.
defunct
Цитата(Qwertty @ Sep 27 2007, 15:58) *
Ну да - __flash, __eeprom на порядок превосходят EEMEM, PROGMEM smile.gif

Вы хотите сказать, что в WinAvr уже можно EEMEM или PROGMEM переменную просто взять и присвоить обычной переменной без использования read_eeprom_byte и прочих вспомогательных функций?

В IAR можно.
Сергей Борщ
Цитата(Qwertty @ Sep 27 2007, 15:58) *
Ну да - __flash, __eeprom на порядок превосходят EEMEM, PROGMEM smile.gif
На два. defunct объяснил почему.
Цитата(Qwertty @ Sep 27 2007, 15:58) *
С ИАР-ом же придется в большинстве случаев решать все проблемы самому - типа файловых систем и т.п. Ну или адаптировать код от Winavr smile.gif
1) При наличии опыта адаптация происходит быстро.
2) Все равно придется что-то править, а в процессе адаптации глубже вникаешь в чужие исходники.
3) По закону подлости нужный код будет под какой-нибудь третий компилятор и вообще не под AVR.
4) По размеру кода ИАР сильно обгоняет WinAVR (по личному опыту, последний эксперимент - AES loader AVR231 буквально вчера. У ИАРа остается свободное место в 2К области, у WinAVRа код вылазит почти на 1К).
Цитата(Qwertty @ Sep 27 2007, 15:58) *
У ИАРа одно преимущество - ассемблер встраивать легче.
С точностью до наоборот. Вот уж что-что, а инлайн асм у WinAVR шикарный, а у IAR вообще никакой и они сами его не рекомендуют. А в обработке отдельного асм-исходника возможности у них практически одинаковые.
singlskv
Цитата(defunct @ Sep 27 2007, 17:10) *
Вы хотите сказать, что в WinAvr уже можно EEMEM или PROGMEM переменную просто взять и присвоить обычной переменной без использования read_eeprom_byte и прочих вспомогательных функций?
В IAR можно.

Цитата
На два. defunct объяснил почему.

А как дела обстоят в IAR c обратной операцией, те присвоением переменной __flash или
__eeprom значения обычной переменной ?

Цитата
4) По размеру кода ИАР сильно обгоняет WinAVR (по личному опыту, последний эксперимент - AES loader AVR231 буквально вчера. У ИАРа остается свободное место в 2К области, у WinAVRа код вылазит почти на 1К).
Задачи таки разные бывают,
я уже предлагал вариант задачки для сравнения IAR и WinAVR,
но никто не соглашается sad.gif
defunct
Цитата(singlskv @ Sep 27 2007, 17:48) *
А как дела обстоят в IAR c обратной операцией, те присвоением переменной __flash или
__eeprom значения обычной переменной ?


Код
__flash char flChar;
__eeprom char eeChar;
char Ch;

int main( void )
{
  eeChar = Ch;  // <--- OK
  flChar = Ch;  // <-- Error [Ta015] Cannot write to flash memory
singlskv
Цитата(defunct @ Sep 27 2007, 19:14) *
Отлично,
Код
__flash char flChar;
__eeprom char eeChar;
char Ch;

int main( void )
{
  eeChar = Ch;  // <--- OK  <--- сколько времени выполняется эта операция ???
  flChar = Ch;  // <-- Error [Ta015] Cannot write to flash memory
<--- запись не из бутлодера ???

eeChar = Ch , Вам не кажется что такая запись просто вводит в заблуждение программера ?
т.е. он то думает что присвоил значение и побежал дальше, а в реальности мы там ждем
как минимум 3,5мс.
Привыкнув к такой простоте, программер не будет такое присваивание
употреблять например в прерываниях ?
ИТД...
defunct
Цитата(singlskv @ Sep 27 2007, 18:27) *
eeChar = Ch , Вам не кажется что такая запись просто вводит в заблуждение программера ?

Это был просто ответ на ваш вопрос. А так мне кажется, что одиночному "чару" вне функции вообще нечего делать. Сколько-нибудь уважающий себя "программер" волен объявить структуру с подобающим именем, которое будет кричать о том, что поля располагаются в eeprom.

Цитата
Привыкнув к такой простоте, программер не будет такое присваивание употреблять например в прерываниях ?

Это из оперы - программисты не ищут простых путей? Или как понимать?
Давайте также покритикуем возможность винды выделять гигабайтные массивы, ведь программист выделивший такой массив может думать, что весь массив лежит в ОП.

PS: к сожалению мне редко приходится наслаждаться возможностями IAR'а, потому что конечный продукт у меня собирается в WinAvr. При портировании с IAR'а на WinAvr частенько приходится поматериться sad.gif в местах работы со строками во флеш и данными в eeprom.
Qwertty
Цитата(defunct @ Sep 27 2007, 17:10) *
Вы хотите сказать, что в WinAvr уже можно EEMEM или PROGMEM переменную просто взять и присвоить обычной переменной без использования read_eeprom_byte и прочих вспомогательных функций?

В IAR можно.

Согласен, можно. И в CV можно. А еще в CV можно сделать так - PORTB.1=1. Следуя Вашей логике- "CV на порядок превосходит IAR". smile.gif
Меня лично не напрягают eeprom_read_byte(), зато помогают больше работать с указателями, что в итоге дает более быстрый и компактный код. При портировании проектов с IAR результирующий размер практически одинаков, но как-то было преимущество WinAvr процентов на 10.
И главное - мне не надо искать кряки, пилюли, пургены успокаивать совесть типа - ничего, у них и так денег много... Чистая совесть это тоже немало.
singlskv
Цитата(defunct @ Sep 27 2007, 19:33) *
Это был просто ответ на ваш вопрос. А так мне кажется, что одиночному "чару" вне функции вообще нечего делать. Сколько-нибудь уважающий себя "программер" волен объявить структуру с подобающим именем, которое будет кричать о том, что поля располагаются в eeprom.
Вопрос все-таки был не о именовании структуры с кричащим именем
EEPROM_xxx, а о том что присвоение переменной хранящейся в EEROM занимает кучу времени.
Цитата
Это из оперы - программисты не ищут простых путей? Или как понимать?
Давайте также покритикуем возможность винды выделять гигабайтные массивы, ведь программист выделивший такой массив может думать, что весь массив лежит в ОП.
Нет, это из оперы что программисты должны понимать чем это грозит.
Цитата
PS: к сожалению мне редко приходится наслаждаться возможностями IAR'а, потому что конечный продукт у меня собирается в WinAvr. При портировании с IAR'а на WinAvr частенько приходится поматериться sad.gif в местах работы со строками во флеш и данными в eeprom.
Дык переходите на Gcc, и будет Вам счастье smile.gif
Не, я почти серьезно.
Qwertty
Цитата(Сергей Борщ @ Sep 27 2007, 18:23) *
На два. defunct объяснил почему.

Ну-ну... Про преимущества CV- выше smile.gif
Цитата(Сергей Борщ @ Sep 27 2007, 18:23) *
1) При наличии опыта адаптация происходит быстро.
2) Все равно придется что-то править, а в процессе адаптации глубже вникаешь в чужие исходники.

Значит если я хочу ездить на машине, мне нужно ее купить, разобрать,собрать, ведь я так глубже вникну в ее устройство. Мне нужно например подключить харддрайв, считать один файл,и может больше никогда в жизни мне это не понадобиться. Зачем мне вникать во внутреннее устройсто FAT32?
А если и понадобиться, лет через 5-10, то все равно придется вникать заново.
Цитата(Сергей Борщ @ Sep 27 2007, 18:23) *
3) По закону подлости нужный код будет под какой-нибудь третий компилятор и вообще не под AVR.
4) По размеру кода ИАР сильно обгоняет WinAVR (по личному опыту, последний эксперимент - AES loader AVR231 буквально вчера. У ИАРа остается свободное место в 2К области, у WinAVRа код вылазит почти на 1К).

Мое имхо - загрузчик должен вполне помещаться в бутовую область любых контроллеров мега. И если у ИАР загрузчик помещается в эти жалких 2 килобайта и еще 2 килобайта свободно, то мне кажется тут что-то не то smile.gif
Цитата(Сергей Борщ @ Sep 27 2007, 18:23) *
С точностью до наоборот. Вот уж что-что, а инлайн асм у WinAVR шикарный, а у IAR вообще никакой и они сами его не рекомендуют. А в обработке отдельного асм-исходника возможности у них практически одинаковые.

Возможно, что с ассемблером в ИАР тоже не все хорошо, я сам вставок в нем не делал, только видел чужие. Они не показались мне уж такими страшными. А вот WinAvr-овские вещь тяжелая, я предпочитаю ими не пользоваться. Все выношу в S файл.
singlskv
Цитата(Qwertty @ Sep 27 2007, 20:36) *
Значит если я хочу ездить на машине, мне нужно ее купить, разобрать,собрать, ведь я так глубже вникну в ее устройство. Мне нужно например подключить харддрайв, считать один файл,и может больше никогда в жизни мне это не понадобиться.
Ездить тоже можно по
разному, можно просто купить и ездить не о чем не задумываясь, чисто для своего удовольствия,
а можно и разобрать/собрать, понять как оно работает, ну и дальше выбрать
для себя, или ездить для удовольствия, или гонятся професионально...
SasaVitebsk
Есть ещё один момент для WinAvr. Только за последних пару лет его пересобирали раз десять. Регулярно что-то меняли в том числе координальное. Так что насчёт совместимости и большого количества проектов это не вся правда. Править придётся. То там то тут выскакивают сообщения - пересобрал - неработает. Работать с ним отнюдь не легче чем с IARом. Хотя и IAR к числу лёгких в освоении пакетов не относится. Документация разбросана по всему интернету. Никакой упорядоченности. Что-то надо - полез искать. Чаще всего если и найдёшь, то в каком нибудь FAQе.

Короче очень геморойная вещь. Ясно что если освоил, то тогда нормально.

Выпад по поводу данных в EEPROM и FLASH - явно бредовый. Удобная вещь - она всегда удобная.

Зачем мне для обращения к Flash переменной обращаться ч/з подпрограмму? А если у меня в одной формуле/операторе используются переменные Flash и RAM? Например знакогенератор в видеоозу вывожу. IAR отличный код генерит и прекрасно оптимизирует такие места. А чтобы по ошибке не использовать переменные EEPROM, выход простой. defunct его фактически указал. Обзавите переменную eeMyInt. И всё для вас будет ясно.

Это просто яркий пример как можно всё с ног на голову поставить.
kv_addr
Цитата(Marian @ Sep 26 2007, 19:38) *
CVAVR дает побитовый доступ к портам (правда в некоторых процах не ко всем)

PORTB.0 = 1;
DDRB.3 = 0;

Эквивалент в EWAVR:
PORTB_Bit1 = 1;
DDRB_Bit3 = 0;
mdmitry
Увы! Началась религиозная война!
По поводу автоматической генерации кода: пришлось использовать CodeWarrior для MC56F8346. Есть для него ProcessorExpert. Если скорость не важна, а важно быстро что-то сделать, то работает хорошо. Если аппаратные ресурсы заняты сильно, то не работала программа: из-за накладных расходов автоматической кодогенерации. В CV такая же ситуация или нет? Если большие накладные расходы, то есть ли смысл в больших проектах использовать?
Сергей Борщ
Цитата(Qwertty @ Sep 27 2007, 19:36) *
Ну-ну... Про преимущества CV- выше smile.gif
1)Хорошо, но не совсем: не для всех потров такая конструкция работает, поэтому я не могу сделать, скажем, #define LED PORTA.1 а потом безболезненно изменить на #define LED PORTE.7, в то время как конструкция PORT |= (1 << BIT); с макросами поверх нее не страдает подобным недостаком.
2)Собственно на этом преимущества CV заканчиваются и его нельзя рассматривать как серьезный инструмент из-за отсутствия раздельной компиляции и всеми вытекающими несоответствиями стандарту. Вопрос обсуждался, я излагал подробные аргументы. Если интересно, поищите по ключевому слову CV и моему имени.
Цитата(Qwertty @ Sep 27 2007, 19:36) *
Значит если я хочу ездить на машине, мне нужно ее купить, разобрать,собрать, ведь я так глубже вникну в ее устройство.
Если мы говорим о любительстве - не за чем Но не уверен, что у любителя все пойдет сразу и без доработок напильником. Если о профессиональной работе - не помешает.
Цитата(Qwertty @ Sep 27 2007, 19:36) *
Мое имхо - загрузчик должен вполне помещаться в бутовую область любых контроллеров мега. И если у ИАР загрузчик помещается в эти жалких 2 килобайта и еще 2 килобайта свободно, то мне кажется тут что-то не то smile.gif
Вы меня не поняли. ИАР выдал код размером ~1800 байт, WinAVR - около 2700.
Цитата(Qwertty @ Sep 27 2007, 19:36) *
Возможно, что с ассемблером в ИАР тоже не все хорошо, я сам вставок в нем не делал, только видел чужие. Они не показались мне уж такими страшными.
Естественно. Чем примитивнее инструмент, тем меньше вы им можете сделать. Вот цитата из мануала:
Цитата
Inline assembler is therefore often best avoided. If there is no suitable intrinsic function available, we recommend the use of modules written in assembler language instead of inline assembler, because the function call to an assembler routine normally causes less performance reduction.
Цитата(Qwertty @ Sep 27 2007, 19:36) *
А вот WinAvr-овские вещь тяжелая, я предпочитаю ими не пользоваться. Все выношу в S файл.
Если вы не умеете пользоваться инструментом потому, что он слишком сложный - это не значит, что инструмент плохой. На уровне ИАРовского инлайн-асма вы в винавре напишете ровно столько же и практически так же.
Marian
Цитата(Сергей Борщ @ Sep 28 2007, 11:27) *
1)Хорошо, но не совсем: не для всех потров такая конструкция работает, поэтому я не могу сделать, скажем, #define LED PORTA.1 а потом безболезненно изменить на #define LED PORTE.7, в то время как конструкция PORT |= (1 << BIT); с макросами поверх нее не страдает подобным недостаком.


Я не рекламирую CVAVR, но работать можно и на нем.
Я и писал
Цитата
CVAVR дает побитовый доступ к портам (правда в некоторых процах не ко всем)

но заменить например в Atmege16 :
#define LED PORTA.1
на
#define LED PORTD.3
несоставит труда.
singlskv
Цитата(SasaVitebsk @ Sep 28 2007, 00:02) *
Выпад по поводу данных в EEPROM и FLASH - явно бредовый. Удобная вещь - она всегда удобная.

Зачем мне для обращения к Flash переменной обращаться ч/з подпрограмму?

Это просто яркий пример как можно всё с ног на голову поставить.
Давайте посмотрим, на Вашем любимом IAR:
Код
#include <string.h>

__eeprom char eeString[]="Prived !";
char String[10]="ABCDEFGHIJ";

int main(void)
{
  memcpy(String,  (void const *)eeString, 10);
  memcpy((void *)eeString, String, 10);
  return 0;
}

Скомпилируйте этот код и пройдитесь по нему отладчиком,
я думаю что результат Вас сильно порадует, особенно второй memcpy biggrin.gif

P.S Тока не нужно мне рассказывать что этот пример высосан из пальца...
Прямое преобразование типов конечно вставлено специально,
тока где и когда Вы наткнетесь на такой результат в реальной программе будете знать
тока Вы и Ваш доктор в дурке (после отладки такого кода) smile.gif
SasaVitebsk
Преимущества они и в Африке преимущества.

Вы прекрасно понимаете, что ими можно не пользоваться. Иными словами, если вас не устраивает по какой то причине прямое обращение к EEPROM либо FLASH памяти, вы можете использовать обращение аналогичное применяемому в WinAVR. Никаких проблем не вижу. Более того вы, естественно можете переписать и сами процедуры обращения. Или использовать свои библиотеки.

У меня действительно один раз было, при применении в одном операторе различных видов памяти, компилятор неверно (точнее не так как я хотел) компильнул. Проблема обнаружилась легко. После локализации места, прошёл оператор по шагам на асме в отладчике. Обнаружил ошибку. Устранилась легко. Прямым приведением типа.

Трагедии никакой здесь нет. Я думаю в WinAVR тоже найдётся немало скелетов в шкафу.

Я, совершенно не приумаляю достоинства WinAVR. Я просто отметил что им не так уж просто пользоваться и привёл свои аргументы. Исключительно исходя из своих наблюдений. Мне оказалось проще и приятнее работать в IAR. В то же время, если человек свободно программирует и в IAR и в WinAVR, то ему это только плюс. Знаний, как известно, лишних не бывает.
SergeiCh
Если хочется писать PORTB_0 = 1, это можно сделать средствами любого ANSI C совместимого компилятора. Например, как в SDCC для HC08:

Код
struct __hc08_bits
{
  unsigned int bit0:1;
  unsigned int bit1:1;
  unsigned int bit2:1;
  unsigned int bit3:1;
  unsigned int bit4:1;
  unsigned int bit5:1;
  unsigned int bit6:1;
  unsigned int bit7:1;
};

#define PTB PORTB              /* Alias for PORTB */
  #define PTB0 ((struct __hc08_bits *)(&PTB))->bit0
  #define PTB1 ((struct __hc08_bits *)(&PTB))->bit1
  #define PTB2 ((struct __hc08_bits *)(&PTB))->bit2
  #define PTB3 ((struct __hc08_bits *)(&PTB))->bit3
  #define PTB4 ((struct __hc08_bits *)(&PTB))->bit4
  #define PTB5 ((struct __hc08_bits *)(&PTB))->bit5
  #define PTB6 ((struct __hc08_bits *)(&PTB))->bit6
  #define PTB7 ((struct __hc08_bits *)(&PTB))->bit7

Изменил одну строчку, чтобы работало для AVR. PTB0 = 1, и даже PTB0 = PTB2 будет работать без проблем, причем для всех портов (где-то как sbi/cbi, где-то lds + sts). Написали один раз что-нибудь типа bitio.h, и пользуйтесь. Но лучше (надеюсь, грамотные люди со мной согласятся) для конкретной задачи шевеления ногой писать макросы или online функции типа led_busy_on(), led_busy_off() и в коде использовать уже их. led_busy = 1, IMHO, хуже, разве что led_busy = ON smile.gif ...

Операцию = можно перегрузить для eeprom, но это уже будет C++.

Про генерацию кода ничего не скажу. Сам использую gcc для разных платформ, включая PC.
defunct
Цитата(singlskv @ Sep 29 2007, 01:37) *
P.S Тока не нужно мне рассказывать что этот пример высосан из пальца...
Прямое преобразование типов конечно вставлено специально,
тока где и когда Вы наткнетесь на такой результат в реальной программе будете знать
тока Вы и Ваш доктор в дурке (после отладки такого кода) smile.gif

Ок, аналогичный пример:
Код
char Str[]="Hello";
char SomeChar;
int main(void)
{
     memcpy( (void *)SomeChar, Str, sizeof(Str));
}

Проблема здесь та же самая что и в вашем примере, и даже без переменных в eeprom.
Поэтому можете также вместе с доктором ковырять и этот код. Ибо когда нет понимания, что происходит в программе и что может происходить - забудьте про (void *).
Сергей Борщ
Цитата(singlskv @ Sep 29 2007, 01:37) *
Прямое преобразование типов конечно вставлено специально,
И совершенно без понимания. Отсюда сюрпризы и жалобы на компилятор. Подсказка - любой указатель (на RAM) приводится к void * автоматически. Имеено поэтому в прототипе данной функции используется указатель на void* а не на char*. А любой указатель на флеш автоматически приводится к void __flash *. Поэтому в прототипе memcpy_P в качестве источника использован void __flash *. Чтобы если вы ошибетесь - компилятор мог распознать эту ошибку. Аналогично с указателями на __eeprom. Если вы примените __eeprom указатель как аргумент memcpy, компилятор вам выругался, что вы хотите невозможного. Если после этого вы тупо делаете явное приведение (и тем самым отключаете контроль типов) - то кто же вам злобный буратина? Вот вам встречный пример:
Код
typedef struct
{
    uint8_t     ParamA;
    uint32_t    ParamB;
    my_struct_t ParamC;
}config_t;

config_t const __flash Defaults =
{
    1,
    0x12345678,
    {
        'a',
        1,
        2,
    }
};

struct
{
    config_t   Config;
    uint8_t    CRC;
} cfg_RAM, __eeprom cfg_EE;

void ReadConfig()
{
    cfg_RAM = cfg_EE;
    if( CRC(&cfg_RAM, sizeof(cfg_RAM)) != 0)
    {
        cfg_RAM = Defaults;
        cfg_RAM.CRC = CRC(&cfg_RAM.Config, sizeof(config_t))
        cfg_EE = cfg_RAM;
    }
}
Напишите с функциями то же самое. Как минимум код будет менее понятный и вы не обойдетесь без приведений типов - а они источник потенциальных ошибок, что вы нам продемонстрировали сами чуть выше.
singlskv
Цитата(defunct @ Sep 29 2007, 15:54) *
Ок, аналогичный пример:
Код
....................

Проблема здесь та же самая что и в вашем примере, и даже без переменных в eeprom.
Ну все таки не совсем одно и тоже, я свой пример показал только с точки зрения
потенциально проблемной части в использовании __eeprom, а в вашем примере просто
нарисован баг который из-за преобразования типов не смог поймать компилятор.

Насколько я знаю, в стандарте С вобще нет такого типа void __eeprom * smile.gif

А вот теперь представьте себе:
Код
__eeprom char eeString[]="Prived !";
char String[10]="ABCDEFGHI";
int Int=1;
long Long=2;

typedef struct
{
    void *ptr;
    int  size;
} SomeData;

SomeData* MassivHrenZnaetSKakimiDannimy[10];
......................
  {
    MassivHrenZnaetSKakimiDannimy[0].ptr = eeString;
    MassivHrenZnaetSKakimiDannimy[0].size = sizeof(eeString);
    MassivHrenZnaetSKakimiDannimy[1].ptr = String;
    MassivHrenZnaetSKakimiDannimy[1].size = sizeof(String);
    MassivHrenZnaetSKakimiDannimy[2].ptr = &Int;
    MassivHrenZnaetSKakimiDannimy[2].size = sizeof(Int);
    MassivHrenZnaetSKakimiDannimy[3].ptr = &Long;
    MassivHrenZnaetSKakimiDannimy[3].size = sizeof(Long);
.............................
.............................
.............................
    memcpy(KudatoTam,  MassivHrenZnaetSKakimiDannimy[x].ptr, MassivHrenZnaetSKakimiDannimy[x].size);
..........................
..........................
  }

Хрен знает какие данные оказались не совсем хрен знает какими, а все по тому что
кое кто придумал свой новый тип данных... __eeprom xxx
singlskv
Цитата(Сергей Борщ @ Sep 29 2007, 16:46) *
И совершенно без понимания. Отсюда сюрпризы и жалобы на компилятор.
А я жаловался на компилятор ?
Нет, ну конечно было пару раз когда я указывал на проблемы с оптимизацией, но не более того...
Разговор о том что нету в С таких типов __flash xxx и что не стоит этими придуманными типами
пользоваться как обычными типами.
Цитата
Вот вам встречный пример:
Код
................
Напишите с функциями то же самое. Как минимум код будет менее понятный и вы не обойдетесь без приведений типов - а они источник потенциальных ошибок, что вы нам продемонстрировали сами чуть выше.
Менее понятен/более понятен, это все таки очень субъективные вещи,
для меня например значительно более понятным при работе с EEPROM является или
прямой вызов функций записи в него, или просто запуск записи с последующей проверкой
что запись уже закончилась. При этом вопросов с приведением типов обычно не стоит,
поскольку посредством вызова функции я четко указываю о своих намерениях.
Тот код который Вы привели конечно выглядит красиво, мой намного зануднее...
НО, объясните мне как Вы будете пользоваться такими присвоениями в следующей
ситуации:
Есть прога:
- все события(опросы) синхронизированны(системный тик) например с тактом 200-500мкс
- есть одно или несколько прерываний которые получают данные
- есть основной цикл который ведет обработку полученных в прерывании данных
- НУЖНО, не прерывая обработку, писать некоторые изменения соcтояния проги в EEPROM

Где в этой проге можно написать cfg_EE = cfg_RAM ?

Момент номер 2,
когда Вы пишите cfg_EE = cfg_RAM , Вы принудительно заставляете перезаписывать
в EEPROM даже те ячейки которые в данный момент не требуют модификации.
Этим Вы осознанно уменьшаете ресурс EEPROM.
Во всех моих занудных алгоритмах записи в EEPROM, перед тем как
записать байт из какой-то структуры в соответствующее место EEPROM происходит
чтение этого адреса и проверка на то, а нужно ли его вобще перезаписывать.

Как Вы думаете, в среднем, какой вариант общения с EEPROM будет более
быстрым и более надежным(в смысле ресурса EEPROM) ?
defunct
Цитата(singlskv @ Sep 29 2007, 20:21) *
Ну все таки не совсем одно и тоже, я свой пример показал только с точки зрения
потенциально проблемной части в использовании __eeprom, а в вашем примере просто
нарисован баг который из-за преобразования типов не смог поймать компилятор.

В вашем примере баг абсолютно такой же как и в моем.
Ибо нефиг несовместимый тип приводить к PVOID.

Цитата
Хрен знает какие данные оказались не совсем хрен знает какими, а все по тому что
кое кто придумал свой новый тип данных... __eeprom xxx

В AVR три адресных пространства. Насколько это удобно или неудобно не вам судить, и не мне. Они просто есть, IAR дает нам простой инструмент доступа к этим адресным пространствам, если вам такой способ доступа не подходит - пользуйтесь другим, более сложным.


Цитата
для меня например значительно более понятным при работе с EEPROM является или
прямой вызов функций записи в него, или просто запуск записи с последующей проверкой
что запись уже закончилась.

Кому что.. Меня как правило интересует конечный результат, если воспользовавшись фичей X я смогу добиться конечного результата меньшим числом строк кода и не в ущерб наглядности, читабельности программы и скорости испольнения, то обязательно ей воспользуюсь (по крайней мере подумаю об ее использовании). Минусом будет только "Портируемость" внутри семейства и на другие многоадресные семейства МК, а на "протируемость" на одноадресные МК (напр ARM) оно вообще никак не повлияет.

Да и палку вы здесь перегибаете. Что может быть понятнее присваивания?
x = y;
sensor_ua
Цитата
IAR дает нам простой инструмент доступа

Замечу, что чтение из "откуда-попало" куда удобнее (хотя производительность несколько ниже) при использовании указателей с модификатором __generic, реализация которого у IAR есть, а у остальных аналогичного, похоже, даже в проекте нет.
singlskv
Цитата(defunct @ Sep 29 2007, 23:47) *
Да и палку вы здесь перегибаете. Что может быть понятнее присваивания?
x = y;
Хорошо, будем говорить тока за себя,
лично мне очень не нравится ситуация когда
x=y; выполняется несколько сот наносекунд, а
e=k; (где e - eeprom) выполняется несколько миллисекунд.

Ну и остальные отрицательные стороны использования EEPROM как переменных я
уже описал выше.
defunct
Цитата(singlskv @ Sep 29 2007, 23:15) *
e=k; (где e - eeprom) выполняется несколько миллисекунд.
Ну и остальные отрицательные стороны использования EEPROM как переменных я
уже описал выше.

Ну и что?! У eeprom еще и ресурс ограничен, такова уж особенность этой памяти.
100k раз запишете дальше пойдут сбои.
Какое это имеет отношение к удобному механизму обращения к этой памяти?

Не нравится медленный внутренний eeprom используйте RAM или ставте быстрый внешний FRAM, но удобного способа доступа к нему средствами компилятора уже не будет, придется писать драйвер.
singlskv
Цитата(defunct @ Sep 30 2007, 00:20) *
Ну и что?! У eeprom еще и ресурс ограничен, такова уж особенность этой памяти.
100k раз запишете дальше пойдут сбои.
Какое это имеет отношение к удобному механизму обращения к этой памяти?
Похоже Вы невнимательно читаете мои посты,
перечитайте пожалуйста №37, и если Вас не затруднит,
ответьте на 2 поставленных мной вопроса,
продублирую их на всякий случай:

НО, объясните мне как Вы будете пользоваться такими присвоениями в следующей
ситуации:
Есть прога:
- все события(опросы) синхронизированны(системный тик) например с тактом 200-500мкс
- есть одно или несколько прерываний которые получают данные
- есть основной цикл который ведет обработку полученных в прерывании данных
- НУЖНО, не прерывая обработку, писать некоторые изменения соcтояния проги в EEPROM

Где в этой проге можно написать cfg_EE = cfg_RAM ?


.......................
Как Вы думаете, в среднем, какой вариант общения с EEPROM будет более
быстрым и более надежным(в смысле ресурса EEPROM) ?
defunct
Цитата(singlskv @ Sep 29 2007, 23:30) *
[i]НО, объясните мне как Вы будете пользоваться такими присвоениями в следующей
ситуации:
Есть прога:
- все события(опросы) синхронизированны(системный тик) например с тактом 200-500мкс
- есть одно или несколько прерываний которые получают данные
- есть основной цикл который ведет обработку полученных в прерывании данных
- НУЖНО, не прерывая обработку, писать некоторые изменения соcтояния проги в EEPROM

Для этой задачи я поставлю исключительно внешний eeprom либо NVRAM и не буду даже морочиться с внутренним, которого судя по условию задачи просто не хватит для хранения какого либо существенного объема статистики.
Внутренний eeprom лично я использую только для: хранения параметров конфигурации устройства, хранения информации о рестартах + дамп критических структур в случае перезагрузки по WDT.
Цитата
Как Вы думаете, в среднем, какой вариант общения с EEPROM будет более
быстрым и более надежным(в смысле ресурса EEPROM) ?

Я думаю, что вариант общения должен быть обдуманным, т.е. надо минимизировать число записей. При этом инструмент которым непосредственно производится запись/чтение может быть каким угодно, но желательно простым, что нам и дает IAR.
singlskv
Цитата(defunct @ Sep 30 2007, 00:40) *
Для этой задачи я поставлю исключительно внешний eeprom либо NVRAM и не буду даже морочиться с внутренним, которого судя по условию задачи просто не хватит для хранения какого либо существенного объема статистики.
Внутренний eeprom лично я использую только для: хранения параметров конфигурации устройства, хранения информации о рестартах + дамп критических структур в случае перезагрузки по WDT.
А мне вот и для всей остальной статистики хватает smile.gif
Наверное по тому что я не умею пользоваться встроенной EEPROM ? biggrin.gif
Цитата
Я думаю, что вариант общения должен быть обдуманным, т.е. надо минимизировать число записей. При этом инструмент которым непосредственно производится запись/чтение может быть каким угодно, но желательно простым, что нам и дает IAR.
Это вы о чем ? Об этой простоте cfg_EE = cfg_RAM ?
Ну и где здесь минимизация количества записей ?

Свой вариант реализации я уже описал, читаем-проверяем-если нужно пишем, и
это все на уровне байта.
Раскажите мне как Вы планируете минимизировать количество записей при помощи
этой простоты cfg_EE = cfg_RAM ?
sensor_ua
Цитата
Где в этой проге можно написать cfg_EE = cfg_RAM ?

такую операцию нельзя прерывать независимо от компилятора - это АППАРАТНОЕ ограничение. Если это не понимать, то знание особенностей использования диалекта языка и компилятора не помогут. Потому вопрос
Цитата
объясните мне как Вы будете пользоваться такими присвоениями в следующей
ситуации

просто не имеет смысла.
Если используется внешняя память, о чём упомянул defunct, то задача относится опять же не к компиляторам, а есть вопрос архитектуры программы.
singlskv
Цитата(sensor_ua @ Sep 30 2007, 01:05) *
такую операцию нельзя прерывать независимо от компилятора - это АППАРАТНОЕ ограничение.
Не очень понял что Вы хотели этим сказать.
Мои варианты/предположения:
- нельзя прервать потому что нельзя smile.gif
- нельзя прерывать потому что кто-то еще захочет записать в EEPROM (из прерывания например) smile.gif
- нельзя прерывать потому что запись в EEPROM требует остановки всех процессов smile.gif
.....................
.....................
- нельзя пользоваться таким вариантом записи в EEPROM (поддерживаю!)
Цитата
Если это не понимать, то знание особенностей использования диалекта языка и компилятора не помогут.
Вы бы уточнили о каких АППАРАТНЫХ ОГРАНИЧЕНИЯХ идет речь...
Если Вы о необходимости вот этого:
asm("cli");
EECR |= (1<<EEMWE);
EECR |= (1<<EEWE);
asm("sei");
то там речь идет о паре тактов проца... и при грамотном проектировании проги даже эти
cli и sei не понадобятся.
Сергей Борщ
Цитата(singlskv @ Sep 29 2007, 20:21) *
Насколько я знаю, в стандарте С вобще нет такого типа void __eeprom * smile.gif
Мы не обсуждали портируемость. В других компиляторах нет eeprom_write_byte();, а в некоторых процессорах нет eeprom wink.gif
Цитата(singlskv @ Sep 29 2007, 20:21) *
А вот теперь представьте себе:
Код
    MassivHrenZnaetSKakimiDannimy[0].ptr = eeString;
Получаем ошибку компилятора о несоответствии типов. Ту самую, которую в предыдущем примере вы задавили явным приведением к (void *). Ту самую, которую вы получите в WinAVR, если попытаетесь присвоть (void *) переменную типа (void EEMEM *) или prog_void.
Цитата(singlskv @ Sep 29 2007, 21:42) *
Где в этой проге можно написать cfg_EE = cfg_RAM ?
Не поверите - именно там, где надо сохранить данные. Компилятор подставит для каждого байта вызов __eeput8_16, в котором именно там, где это необходимо будет запрет/разрешение прерываний. Поверьте, код будет практически идентичен eeprom_write_byte(), за которую вы агитируете. Для очень редких случаев есть вариант *((uint8_t *)&cfg_EE.Config.ParamA)[2] = byte; Что касается ресурса eeprom, то я не случайно взял конфиг - как наиболее общий случай, когда ресурса хватит даже самому пытливому пользователю. И не пытайтесь меня убедить, что я должен потратить лишнее время чтобы экономить ресурс там, где его и так с запасом - это все равно что агитировать писать на асме (со всеми вытекающими недостатками), чтобы втиснуть програму в 2к памяти при 8к на борту. Если же есть какие-либо специальные требования (ресурс, необходимость отслеживать окончание по прерыванию) - думать головой никто не отменял.

Цитата(SergeiCh @ Sep 29 2007, 10:05) *
Но лучше (надеюсь, грамотные люди со мной согласятся) для конкретной задачи шевеления ногой писать макросы или online функции типа led_busy_on(), led_busy_off() и в коде использовать уже их. led_busy = 1, IMHO, хуже, разве что led_busy = ON smile.gif ...
Почти согласен. Но писать для каждой ноги xxx_on(), xxx_off() - да, конечно так и делал раньше. Но теперь - on(LED); off(FLASH_CS); if(signal(KEY)) - тоже абсолютно портируемо на любой С-компилятор. И сгенеренный код будет идентичен тому, который надо написать вручную для xxx_on(); xxx_off();
singlskv
Цитата(Сергей Борщ @ Sep 30 2007, 01:57) *
Получаем ошибку компилятора о несоответствии типов. Ту самую, которую в предыдущем примере вы задавили явным приведением к (void *). Ту самую, которую вы получите в WinAVR, если попытаетесь присвоть (void *) переменную типа (void EEMEM *) или prog_void.
Я даже и не сомневался что именно Вы укажите на это несоответствие smile.gif,
этот код я даже и не пытался скомпилировать потому что очевидно одно из двух,
если компилятор пропустит такой код, то все очень плохо и пользоваться __eeprom
просто нельзя ни при каких обстоятельствах, а если не пропустит, то это говорит
о том что типы которые придумал IAR(__eeprom xxx), Эээ... ну мягко говоря не
являются таки типами..., по крайней мере в понимании С.
Цитата
Не поверите - именно там, где надо сохранить данные. Компилятор подставит для каждого байта вызов __eeput8_16, в котором именно там где это необходимо будет запрет/разрешение прерываний. Поверьте, код будет практически идентичен eeprom_write_byte(), за которую вы агитируете.
Упс..., это где это я агитировал за использование eeprom_write_byte() ?
Я этим ни разу не пользовался smile.gif У меня свои функции.
Если Вас не затруднит ответьте таки конкретно на 2 моих вопроса из поста №37.



Все равно не понимаю в чем Вы пытаетесь меня убедить.
Цитата(sensor_ua @ Sep 30 2007, 02:21) *
Код
/* Wait for completion of previous write */
while(EECR & (1<<EEWE));
В том что я обязан висеть в этом цикле пока не закончится запись ?
У меня это выглядит примерно так:
Код
//==============================================================
// Автомат записи в EEPROM
//==============================================================
void EepromRun()
{

  if (EECR & (1<<EEWE)) return;                // идет запись ? да, тогда отваливаем (другие дела)

  if (CurrState == EE_FREE)
  {
     ...................................
     ...................................

}

Цитата
Запись заканчивается не сразу после засылки адреса и данных

а после АППАРАТНОЙ записи - для мега16 это 8.5 ms типовое значение. Или Вы хотите сказать, что, буквы EEMEM автоматом вдруг делают неожидающей встроенную функцию
static inline void __attribute__ ((always_inline))
eeprom_write_byte (uint8_t *addr,uint8_t value);
? (Может, она случайноwink.gif и неожидающая, но тогда ею пользоваться низзя) А не пробовали посмотреть, во что раскладывается аналогичная операция у IAR? Дык тоже инлайновый вариант.
Если не используем встроенные функции или модификаторы, а боремся за отсутствие ожиданий при работе с EEPROM, то пример задачи не к месту - в обоих случаях нужно писать СВОЁ.

Я НЕ пользуюсь ни IARовским ни каким другим вариантом доступа к EEPROM.
У меня есть свой хорошо работающий автомат записи.
sensor_ua
Цитата
Я НЕ пользуюсь ни IARовским ни каким другим вариантом доступа к EEPROM.

Обчитался после, что Вы не используете встроенные возможности и удалил пост нафиг.
Если Вы предлагаете для всех случаев применения EEPROM не использовать встроенные функции/модификаторы, то это не повод рассказывать, что они не годятся. Аргументы, ИМХО, сомнительны.
Задачи, конечно, разные бывают. Сам для записи во внешнюю последовательную память целую артиллерию из очередей выстраиваю, но константы, хранимые во __flash никуда не деваются и удобно используютсяwink.gif. Встроенную EEPROM у нас юзают исключительно как описывал defunct, потому как реально для наших логов (архивов) маловато будет - для хранилищ обычно ставим FRAM и DataFlash.
defunct
Цитата(singlskv @ Sep 30 2007, 01:36) *
Упс..., это где это я агитировал за использование eeprom_write_byte() ?
Я этим ни разу не пользовался smile.gif У меня свои функции.

Если речь идет о задаче-драйвере записи eeprom, то что мешает внутри нее использовать уже готовые механизмы компиляторов, e.g.:

Код
void EEPROM_Dispatch(void)
{
    if (EECR & (1<<EEWE))
        return;
    ....
    if (*(__eeprom U8 *)адрес != data to write)
        *(__eeprom U8 *)адрес = data to write;
}


Если вы даже не удосужились посмотреть и разобраться с кодом eeprom_read_byte()/eeprom_write_byte() пакета в котором работаете, и начали сразу городить что-то свое, то спорить с вами о возможностях IAR просто бесполезная трата времени.

Цитата
Я НЕ пользуюсь ни IARовским ни каким другим вариантом доступа к EEPROM.
У меня есть свой хорошо работающий автомат записи.

Порой глупо из-за какого-то принципа не пользоваться уже имеющимися механизмами.
К тому же они нисколько не помешали бы вашему автомату, а наоборот сделали бы его более прозрачным/читаемым.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.