demiurg_spb 0 2 марта, 2011 Опубликовано 2 марта, 2011 · Жалоба image-craft тоже не использует по-инерции avr-gcc использует и лично я не испытываю в связи с этим никаких затруднений. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Petka 0 2 марта, 2011 Опубликовано 2 марта, 2011 · Жалоба .... avr-gcc использует и лично я не испытываю в связи с этим никаких затруднений. avr-gcc вообще не распределяет eeprom память. Как понимать "avr-gcc использует"? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 3 марта, 2011 Опубликовано 3 марта, 2011 · Жалоба avr-gcc вообще не распределяет eeprom память. Как понимать "avr-gcc использует"? Хорошо. Под avr-gcc я имел ввиду весь тулчейн, точно так же как и CV, ICC и IAR. Линкер помещает в отдельную секцию данные с атрибутом EEMEM, а потом утилита objcopy выкусывает её в отдельный файл - образ прошивки eeprom памяти. И в результате, по умолчанию, данные в eeprom располагаются начиная с нулевого адреса. Вся эта канитель конфигурится через Makefile и программист может изменить массу параметров, в том числе и стартовый адрес eeprom данных. Поправьте или дополните меня если считаете нужным. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
defunct 0 3 марта, 2011 Опубликовано 3 марта, 2011 · Жалоба Если просто хранить номер записи то младший бит будет меняться с каждым увеличением. Во-первых вы немного ошибаетесь - можно подобрать количество записей так, что изменения в младшем бите будут очень редкими. Например, если записи всего две, то младший бит в sequence ячейках практически никогда меняться не будет, т.к. в 0-ю запись попадут все четные sequence, в 1-ю - все нечетные. Во-вторых - даже если младший бит будет меняться постоянно, ну и что? Мы же пишем всегда в новые n-байт, т.е. ячеек с sequence'ом будет столько же сколько и записей, наработка на отказ - все те же n * 100000, где n - размерность массива записей. Ниже пример реализации алгоритма, правда здесь в качестве хранилища используется флеш (проц SAM7): void js_LoadConfig(void) { U8 *p = (U8 *)(CONFIG_START_FLASH_ADDRESS); U8 last_seq = *p; U8 *pLastConfig = p; U8 buf[sizeof(jsContext.Cfg)]; PJS_CONFIG pCfg = (PJS_CONFIG)buf; int i; for (i = 0; i < CONFIG_MIRROR_PAGE_COUNT; i++) { p += FLASH_PAGE_SIZE_BYTES; if (((U8)(last_seq + 1)) == *p) { last_seq = *p; pLastConfig = p; } else { p = pLastConfig; break; } } // at this point p - points to the address with the most fresh config record memcpy( buf, p, sizeof(buf)); jsContext.LastLocation = (U32)p; jsContext.Cfg.Sequence = *p; // check CRC of the record if ( CRC16( buf, sizeof(buf) != 0 ) { printf("CRC error exp=%2x, cur=%2x, flash_addr=%x, seq=%d\n", hCRC, pCfg->CRC, (U32)p, *p); printf("The configuration has NOT been applied!\n" ); printf("or there is no previously saved configuration.\n"); // store defaults js_StoreConfig(); } else { // CRC is ok, applying new settings memcpy( &jsContext.Cfg, pCfg, sizeof(jsContext.Cfg)); printf("Configuration applied, seq_%x\n", *p); } } void js_StoreConfig(void) { jsContext.Cfg.Sequence += 1; jsContext.LastLocation += FLASH_PAGE_SIZE_BYTES; if (jsContext.LastLocation > CONFIG_LAST_FLASH_CELL_ADDRESS) jsContext.LastLocation = CONFIG_START_FLASH_ADDRESS; jsContext.Cfg.CRC = CRC16( (U8 *)&jsContext.Cfg, sizeof(jsContext.Cfg) - 2); iap_PageWrite( jsContext.LastLocation, (U32 *)&jsContext.Cfg, sizeof(jsContext.Cfg) ); printf("configuration stored, L(%x), Sq(%x), (%d)bytes\n", jsContext.LastLocation, jsContext.Cfg.Sequence, sizeof(jsContext.Cfg)); } CONFIG_MIRROR_PAGE_COUNT --> это число записей в массиве. Sequence постоянно увеличивается, и новый sequence пишется уже в новую запись. При загрузке конфигурации - пробегаемся по массиву, находим самую страшую запись и берем ее. 2 moderator: просьба тэг [ code ] на [ codebox ] не менять, пасиба. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
NullPointer 0 3 марта, 2011 Опубликовано 3 марта, 2011 · Жалоба А всё-таки, EEPROM в AVR страничной организации, или же нет? В документации, правда, в разделе записи в EEPROM с программатора, указан страничный обмен: к примеру, страница - 8 байт, и минимально адресуемый элемент - 1 байт. Ежели оно минимально адресуемо байтом, то какой смысл считать в них биты, ибо стирание\запись всё равно для всех восьми? А если из МК при записи в EEPROM одного байта переписывается вся страница, про принципу read-modify-write, то всё и того хуже... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
defunct 0 3 марта, 2011 Опубликовано 3 марта, 2011 · Жалоба А всё-таки, EEPROM в AVR страничной организации, или же нет? Всегда был байтовой насколько помню. - можно стирать/записать произвольный байт. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zombi 0 3 марта, 2011 Опубликовано 3 марта, 2011 · Жалоба To defunct. Я не могу понять что такое это sequence, где оное хранится и какова его размерность? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
NullPointer 0 3 марта, 2011 Опубликовано 3 марта, 2011 · Жалоба Всегда был байтовой насколько помню. - можно стирать/записать произвольный байт.Тогда нет смысла мудрить с отдельными битами, ибо для всего байта erase\write выполняется. Нет write-only команды. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zombi 0 3 марта, 2011 Опубликовано 3 марта, 2011 · Жалоба Тогда нет смысла мудрить с отдельными битами, ибо для всего байта erase\write выполняется. Нет write-only команды. Осталось только выяснить : приводит ли к исчепанию ресурса стирание(запись значения FFH) в ячейку которая и до того была FFH Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ukpyr 0 3 марта, 2011 Опубликовано 3 марта, 2011 · Жалоба Осталось только выяснить : приводит ли к исчепанию ресурса стирание(запись значения FFH) в ячейку которая и до того была FFHПолезно перед записью каждого байта проверять на равенство записанному. Уменьшается износ и часто сильно ускоряется обновление параметров. В одном проекте не хватало заряда конденсатора для сохранения в EEPROM после пропадания питания (больше 0.5сек), добавил проверку - успевало записать за десятки миллисекунд. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 3 марта, 2011 Опубликовано 3 марта, 2011 · Жалоба Я не могу понять что такое это sequence, где оное хранится и какова его размерность? Хранится в каждой записи. Размерность должна быть такой, чтобы максимальное значение sequence было больше числа возможных записей, тогда всегда можно достоверно определить наиболее свежую. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 140 4 марта, 2011 Опубликовано 4 марта, 2011 · Жалоба Размерность должна быть такой, чтобы максимальное значение sequence было больше числа возможных записей, тогда всегда можно достоверно определить наиболее свежую.Может быть и небольшой размерности, но период записываемых в него значений должен быть некратен количеству копий записей. Тогда по сбою последовательности легко находится место налезания головы буфера на хвост. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
defunct 0 4 марта, 2011 Опубликовано 4 марта, 2011 · Жалоба что такое это sequence, где оное хранится и какова его размерность? Sequence это первый байт структуры Cfg (она вся пишется во флеш, последние ее два байта - CRC16). Структура Cfg - пишется покругу во флеш, при каждой записи sequence увеличивается на 1. При старте девайса - последовательно вычитываются записи начиная с нулевой, там где обнаруживается разница sn[i+1] - sn[ i ] != 1 (т.е. следующий Sequence отличается от текущего не на единицу), и будет i - номер искомой самой свежей записи. Тогда нет смысла мудрить с отдельными битами, ибо для всего байта erase\write выполняется. Нет write-only команды. Я и не предлагал :laughing: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zombi 0 5 марта, 2011 Опубликовано 5 марта, 2011 · Жалоба Хранится в каждой записи. Размерность должна быть такой, чтобы максимальное значение sequence было больше числа возможных записей, тогда всегда можно достоверно определить наиболее свежую. Sequence это первый байт структуры Cfg (она вся пишется во флеш, последние ее два байта - CRC16). Спасибо! Разобрался. Действительно очень красиво все получается. :beer: Осталось только выяснить : приводит ли к исчепанию ресурса стирание(запись значения FFH) в ячейку которая и до того была FFH Полезно перед записью каждого байта проверять на равенство записанному. Уменьшается износ и часто сильно ускоряется обновление параметров. В одном проекте не хватало заряда конденсатора для сохранения в EEPROM после пропадания питания (больше 0.5сек), добавил проверку - успевало записать за десятки миллисекунд. Т.е. получается что время на запись "тогоже самого" тратится по любому, а вот приводит ли это к износу еепром? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
NullPointer 0 5 марта, 2011 Опубликовано 5 марта, 2011 (изменено) · Жалоба Т.е. получается что время на запись "тогоже самого" тратится по любому, а вот приводит ли это к износу еепром?Убивается, ждём-с. Сейчас 1'248'000 циклов выполнено, пока жива... (Хм, в программке вроде бы не наврал нигде.. в один и тот же адрес пишу 0xFF в количестве 992 штук, затем 8 значений с единичкой в разных разрядах, и в обоих случаях читаю и проверяю совпало ли, и циклы считаю.) Код (ATMega128; здесь USB - мост на UART), на проверку, может ошибка где? #include <stdio.h> static char str[100]; #define EEPROM_ADDRESS_TO_DESTROY 4094U uint32_t cycles_; uint16_t cycles_1000_; void show_cycles(uint8_t is_failed) { if(is_failed) { sprintf(str, "\r\nFAILED ON: %ld", cycles_); } else { sprintf(str, "\r\nCURRENT: %ld", cycles_); } for(uint8_t i = 0; i < 100; i++) { if(str[i]) USB_TransmitByte(str[i]); else break; } } void eeprom_write_no_check(uint16_t address, uint8_t data) { while(EECR & _BV(EEWE)); EEAR = address; EEDR = data; ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { EECR |= _BV(EEMWE); EECR |= _BV(EEWE); } } uint8_t eeprom_read_no_check(uint16_t address) { while(EECR & _BV(EEWE)); EEAR = address; EECR |= _BV(EERE); return EEDR; } __attribute__((OS_main)) int main(void) { USB_Initialize(); sei(); for(;;) { eeprom_write_no_check(EEPROM_ADDRESS_TO_DESTROY, 0xFF); ++cycles_; ++cycles_1000_; if(eeprom_read_no_check(EEPROM_ADDRESS_TO_DESTROY) != 0xFF) { show_cycles(TRUE); for(;;); } if(cycles_1000_ == 1000) { cycles_1000_ = 0; show_cycles(FALSE); for(uint8_t data = 1; data; data <<= 1) { eeprom_write_no_check(EEPROM_ADDRESS_TO_DESTROY, data); ++cycles_; ++cycles_1000_; if(eeprom_read_no_check(EEPROM_ADDRESS_TO_DESTROY) != data) { show_cycles(TRUE); for(;;); } } } if(USB_IsDataReceived()) { if(USB_ReceiveByte() == '?') { show_cycles(FALSE); } } } return 0; } Если в коде ошибок нет, то поставлю писать что-нить отличное от 0xFF, проверим далее... Изменено 5 марта, 2011 пользователем SysRq Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться