а вот с этого места по-подробнее, пожалуйстаavreal писал(а):Нет, ну конечно можно завести generic-указатели, для AVR 3-байтовые
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
а вот с этого места по-подробнее, пожалуйстаavreal писал(а):Нет, ну конечно можно завести generic-указатели, для AVR 3-байтовые
вот так всегда...avreal писал(а):Не-а![]()
спасение утопающих - дело рук самих утопающихO-LED писал(а):я конечно понимаю что вы бегите далеко впереди меня, но всеже, как мне подружить флешь, еепром и указатель на них?
Код: Выделить всё
flash unsigned int yzor1 []
flash unsigned int yzor2 []
flash unsigned int yzor3 []
flash unsigned int yzor4 []
eeprom unsigned int yzor5 []
????? unsigned int *yzor;Код: Выделить всё
while (1)
{
ля-ля-ля
switch (yzor_nomer)
{
case 0: yzor=yzor1; break;
case 1: yzor=yzor2; break;
case 2: yzor=yzor3; break;
case 3: yzor=yzor4; break;
case 4: yzor=yzor5; break;
};
};Код: Выделить всё
flash unsigned int yzor2 []
flash unsigned int yzor3 []
flash unsigned int yzor4 []
eeprom unsigned int yzor5 []
flash unsigned int *f_yzor;
eeprom unsigned int *ee_yzor;
while (1)
{
ля-ля-ля
switch (yzor_nomer)
{
case 0: f_yzor=yzor1; break;
case 1: f_yzor=yzor2; break;
case 2: f_yzor=yzor3; break;
case 3: f_yzor=yzor4; break;
case 4: ee_yzor=yzor5; break;
};
if (yzor_nomer <=3)
{
использхуем указатель f_yzor
}
else
{
использхуем указатель ee_yzor
}
};Код: Выделить всё
flash unsigned int yzor1 []
flash unsigned int yzor2 []
flash unsigned int yzor3 []
flash unsigned int yzor4 []
eeprom unsigned int yzor5 []
union {
flash unsigned int *f;
eeprom unsigned int *e;
} yzor;
unsigned char isEeprom;
Код: Выделить всё
while (1)
{
ля-ля-ля
switch (yzor_nomer)
{
case 0: yzor.f=yzor1; isEeprom=0; break;
case 1: yzor.f=yzor2; isEeprom=0; break;
case 2: yzor.f=yzor3; isEeprom=0; break;
case 3: yzor.f=yzor4; isEeprom=0; break;
case 4: yzor.e=yzor5; isEeprom=1; break;
};
};
Код: Выделить всё
a = (isEeprom?*yzor.e:*yzor.f);
Куда в avr-gcc до таких сложных вещей? Куда важнее было бы сделать нормальную работу оптимизатора на 16-битных числах(которыми в GCC являются все константы, даже если они помещяются в 8 бит) и поддержку обращения к данным во flash без ассемблерных вставок(которые в AVR LibC находятся в pgmspace.h).avreal писал(а):И не уверен, что будет в ближайшее время, вроде-бы в рассылке этот вопрос как-то поднимался и там и сдох.
а в чем проблема с 16-битными числами? если я не ошибаюсь, по стандарту все числа считаются типа int, чтобы они были другого типа. надо объявлять это. так в чем вы видите проблему: в соблюдении стандарта?Murav писал(а):Куда в avr-gcc до таких сложных вещей? Куда важнее было бы сделать нормальную работу оптимизатора на 16-битных числах(которыми в GCC являются все константы, даже если они помещяются в 8 бит) и поддержку обращения к данным во flash без ассемблерных вставок(которые в AVR LibC находятся в pgmspace.h).
Главное, что запись типа (a+1)<<2, где a и b имеют тип char вполне может быть преобразована компилятором в сдвиг 16-битного числа, который выполняется в цикле. И естественно скорости это совершенно не добавляет.ARV писал(а):а в чем проблема с 16-битными числами? если я не ошибаюсь, по стандарту все числа считаются типа int, чтобы они были другого типа. надо объявлять это. так в чем вы видите проблему: в соблюдении стандарта?
Я регулярно наблюдаю как оптимизатор сначала преобразует переменную к нужному типу и затем производит операцию не только с нужными регистрами, но и с несколькими, которые он незадолго до этого заполнил нулями.ARV писал(а):а оптимизатор, по-моему, отлично справляется со всеми поставленными задачами... опять же: какие претензии?
Хоть компилятор по стандарту и не обязан поддерживать другие типы памяти, но тем не менее поддерживать их нужно. Причём делать такую поддержку крайне желательно на уровне компилятора(а не костылями типа ассемблерных вставок), поскольку в этом случае во-первых оптимизатор может произвести оптимизацию(например, avr-gcc не может использовать инструкцию LPM Rd, Z+) и во-вторых уменьшается число мест где можно сделать ошибку(тот же avr-gcc при обращении к указателю со спецификатором PROGMEM как к обычной памяти даже варнинг не выдаст).ARV писал(а):и, наконец, последнее: только что тут было рассказано (с уклоном в историю) о том, что Си не имеет и не должен иметь никакого понятия о РАЗНЫХ типах памяти и потому НЕ ОБЯЗАН реализовывать на уровне языка доступ к этим разным памятям... и если какой-то компилятор умеет работать с ячейкой eeprom, как с обычной переменной (без функций) - то это скорее недостаток, чем достоинство!
Если для указания того, что переменная находится в другом типе памяти требуется только её спецификатор, то программу легко сделать переносимой с помощью обычных #define'ов. А вот если при каждом обращении нужно вызывать функцию, то для переноса кода потребуется переделывать весь код.ARV писал(а):это делает программу непереносимой
Язык высокого уровня и должен скрывать от программиста тонкости реализации. Естественно при этом программисту нельзя забывать, что указав другой тип памяти он может значительно снизить быстродействие и он должен это учитывать. А для возможности доступа по прерываниям можно и дополнительно дать возможность чтения и записи вручную и никаких проблем с таким доступом я не вижу.ARV писал(а):но главное, полностью скрывает от программиста контроль за скоростью исполнения. не только скорость, но и просто процесс записи, например, 32-битной переменной long в EEPROM происходит неизвестно как: то ли с использованием прерывания по окончанию записи, то ли нет, то ли с запретом прерываний (атомарно), то ли нет...
Но им иногда приходится делать конструкции типа pgm_read_word(((PROGMEM struct1 *)pgm_read_word(dataaddr+a))->fld1) .ARV писал(а):кстати, по вышеупомянутым причинам avr-gcc-программисты даже не подозревают о наличии каких-то проблем с указателями и т.п. при доступе к разным видам памяти!
Код: Выделить всё
eeprom x;
x=1;
PORTA=x;
x=2;
PORTA=x;
x=3;
PORTA=x;выведется и не собъется. однако, если такое делать в цикле, вот тут-то и запрятался пушной зверек: число записей в EEPROM ограничено жалкими 100 тысячами, и при определенном стечении обстоятельств уже спустя час работы вашей программы ячейки EEPROM перестанут правильно записываться или читаться.O-LED писал(а): и в порт А выведится последовательно 1,2,3 и ничего не потеряется и не собьется?
Код: Выделить всё
eeprom unsigned int yzor[64];
unsigned int led[64]
// этот цикл запускается крайне редко!!!
for (x=0;x<64;x++)
{
yzor[x]=led[x]
}Код: Выделить всё
eeprom int x;
x=0xFFFF;
x=0x0000;Код: Выделить всё
a = 12;
a=12;Нормально. Перед обращением к EEPROM вставляется ожидание пока он освободится.O-LED писал(а):а нормально ли запишется в еепром в таком виде, если после записи одного элемента не ждать окончания записи, а сразу приступать к записи второго элемента.
Здесь важно то, что константы, которые в случае программы для компьютера будут храниться в обычной памяти, в МК окажутся в flash. То есть требуется переделывать способ доступа к константам. А случае констант во flash никаких проблем при переносе нет вообще, достаточно для всех этих констант заменить спецификатор const на flash const, а в случае необходимости доступа к flash функциями придётся переделывать весь код.ARV писал(а):для портирования кода с обращением к памяти через функцию достаточно переделать эту функцию, а вот когда доступ скрыт внутри компилятора - тут-то и приходится весь код коверкать...
А вот на a = *ptr он не обратит никакого внимания и вставит чтение из SRAM. А записывать в константные переменные и так никто пытаться не будет.ARV писал(а):GCC выдаст error на *ptr = 123;, если указатель будет описан, как положено const PROGMEM int *ptr;могли бы, конечно, const упрятать внутрь PROGMEM, но не упрятали... мотивация пока мне не ясна (да и не интересует, если честно).
Так программист должен знать что делает спецификатор eeprom, если он его использует.ARV писал(а):тут доказывал, что такое "незаметное" обращение к EEPROM - хорошо, а вот принесет человек свою программу куда-то специалисту Си и спросит: почему через час все перестает работать? специалист будет смотреть и думать: а и вправду, почему?! все по-стандарту внешне, где собака порылась? а было бы обращение к EEPROM в виде функции - он (специалист) тут же спросил бы - а что эта функция eeprom_write() делает? не в ПЗУ ли какое-то пишет? а не дает ли ПЗУ отказов при частой записи? и решение проблемы будет найдено быстро...