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

 
 
4 страниц V  < 1 2 3 4 >  
Reply to this topicStart new topic
> Энергонезависимая Память AVR
demiurg_spb
сообщение Mar 2 2011, 12:06
Сообщение #16


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



image-craft тоже не использует по-инерции
avr-gcc использует и лично я не испытываю в связи с этим никаких затруднений.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
Petka
сообщение Mar 2 2011, 17:44
Сообщение #17


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

Группа: Свой
Сообщений: 1 453
Регистрация: 23-08-05
Пользователь №: 7 886



Цитата(demiurg_spb @ Mar 2 2011, 15:06) *
....
avr-gcc использует и лично я не испытываю в связи с этим никаких затруднений.

avr-gcc вообще не распределяет eeprom память. Как понимать "avr-gcc использует"?
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Mar 3 2011, 10:06
Сообщение #18


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(Petka @ Mar 2 2011, 20:44) *
avr-gcc вообще не распределяет eeprom память. Как понимать "avr-gcc использует"?

Хорошо. Под avr-gcc я имел ввиду весь тулчейн, точно так же как и CV, ICC и IAR.

Линкер помещает в отдельную секцию данные с атрибутом EEMEM,
а потом утилита objcopy выкусывает её в отдельный файл - образ прошивки eeprom памяти.
И в результате, по умолчанию, данные в eeprom располагаются начиная с нулевого адреса.

Вся эта канитель конфигурится через Makefile и программист может изменить массу параметров,
в том числе и стартовый адрес eeprom данных.

Поправьте или дополните меня если считаете нужным.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
defunct
сообщение Mar 3 2011, 16:20
Сообщение #19


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(zombi @ Mar 1 2011, 17:01) *
Если просто хранить номер записи то младший бит будет меняться с каждым увеличением.

Во-первых вы немного ошибаетесь - можно подобрать количество записей так, что изменения в младшем бите будут очень редкими.
Например, если записи всего две, то младший бит в 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 ] не менять, пасиба.
Go to the top of the page
 
+Quote Post
SysRq
сообщение Mar 3 2011, 16:43
Сообщение #20


Чайник, 1 литр
****

Группа: Свой
Сообщений: 655
Регистрация: 17-05-06
Из: Moscow
Пользователь №: 17 168



А всё-таки, EEPROM в AVR страничной организации, или же нет?
В документации, правда, в разделе записи в EEPROM с программатора, указан страничный обмен: к примеру, страница - 8 байт, и минимально адресуемый элемент - 1 байт.
Ежели оно минимально адресуемо байтом, то какой смысл считать в них биты, ибо стирание\запись всё равно для всех восьми? А если из МК при записи в EEPROM одного байта переписывается вся страница, про принципу read-modify-write, то всё и того хуже...
Go to the top of the page
 
+Quote Post
defunct
сообщение Mar 3 2011, 16:47
Сообщение #21


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(SysRq @ Mar 3 2011, 18:43) *
А всё-таки, EEPROM в AVR страничной организации, или же нет?

Всегда был байтовой насколько помню. - можно стирать/записать произвольный байт.
Go to the top of the page
 
+Quote Post
zombi
сообщение Mar 3 2011, 16:58
Сообщение #22


Гуру
******

Группа: Свой
Сообщений: 2 076
Регистрация: 10-09-08
Пользователь №: 40 106



To defunct.
Я не могу понять что такое это sequence, где оное хранится и какова его размерность?
Go to the top of the page
 
+Quote Post
SysRq
сообщение Mar 3 2011, 17:00
Сообщение #23


Чайник, 1 литр
****

Группа: Свой
Сообщений: 655
Регистрация: 17-05-06
Из: Moscow
Пользователь №: 17 168



Цитата(defunct @ Mar 3 2011, 19:47) *
Всегда был байтовой насколько помню. - можно стирать/записать произвольный байт.
Тогда нет смысла мудрить с отдельными битами, ибо для всего байта erase\write выполняется. Нет write-only команды.
Go to the top of the page
 
+Quote Post
zombi
сообщение Mar 3 2011, 17:13
Сообщение #24


Гуру
******

Группа: Свой
Сообщений: 2 076
Регистрация: 10-09-08
Пользователь №: 40 106



Цитата(SysRq @ Mar 3 2011, 20:00) *
Тогда нет смысла мудрить с отдельными битами, ибо для всего байта erase\write выполняется. Нет write-only команды.

Осталось только выяснить : приводит ли к исчепанию ресурса стирание(запись значения FFH) в ячейку которая и до того была FFH
Go to the top of the page
 
+Quote Post
ukpyr
сообщение Mar 3 2011, 22:06
Сообщение #25


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

Группа: Участник
Сообщений: 1 264
Регистрация: 17-06-08
Из: бандустан
Пользователь №: 38 347



Цитата
Осталось только выяснить : приводит ли к исчепанию ресурса стирание(запись значения FFH) в ячейку которая и до того была FFH
Полезно перед записью каждого байта проверять на равенство записанному. Уменьшается износ и часто сильно ускоряется обновление параметров. В одном проекте не хватало заряда конденсатора для сохранения в EEPROM после пропадания питания (больше 0.5сек), добавил проверку - успевало записать за десятки миллисекунд.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Mar 3 2011, 22:21
Сообщение #26


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(zombi @ Mar 3 2011, 19:58) *
Я не могу понять что такое это sequence, где оное хранится и какова его размерность?

Хранится в каждой записи. Размерность должна быть такой, чтобы максимальное значение sequence было больше числа возможных записей, тогда всегда можно достоверно определить наиболее свежую.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Mar 4 2011, 11:00
Сообщение #27


Гуру
******

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



QUOTE (aaarrr @ Mar 4 2011, 00:21) *
Размерность должна быть такой, чтобы максимальное значение sequence было больше числа возможных записей, тогда всегда можно достоверно определить наиболее свежую.
Может быть и небольшой размерности, но период записываемых в него значений должен быть некратен количеству копий записей. Тогда по сбою последовательности легко находится место налезания головы буфера на хвост.


--------------------
На любой вопрос даю любой ответ
"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
defunct
сообщение Mar 4 2011, 15:02
Сообщение #28


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(zombi @ Mar 3 2011, 18:58) *
что такое это sequence, где оное хранится и какова его размерность?

Sequence это первый байт структуры Cfg (она вся пишется во флеш, последние ее два байта - CRC16).
Структура Cfg - пишется покругу во флеш, при каждой записи sequence увеличивается на 1. При старте девайса - последовательно вычитываются записи начиная с нулевой, там где обнаруживается разница
Код
sn[i+1] - sn[ i ] != 1
(т.е. следующий Sequence отличается от текущего не на единицу), и будет i - номер искомой самой свежей записи.

Цитата(SysRq @ Mar 3 2011, 19:00) *
Тогда нет смысла мудрить с отдельными битами, ибо для всего байта erase\write выполняется. Нет write-only команды.

Я и не предлагал laughing.gif
Go to the top of the page
 
+Quote Post
zombi
сообщение Mar 5 2011, 11:34
Сообщение #29


Гуру
******

Группа: Свой
Сообщений: 2 076
Регистрация: 10-09-08
Пользователь №: 40 106



Цитата(aaarrr @ Mar 4 2011, 01:21) *
Хранится в каждой записи. Размерность должна быть такой, чтобы максимальное значение sequence было больше числа возможных записей, тогда всегда можно достоверно определить наиболее свежую.

Цитата(defunct @ Mar 4 2011, 18:02) *
Sequence это первый байт структуры Cfg (она вся пишется во флеш, последние ее два байта - CRC16).

Спасибо! Разобрался. Действительно очень красиво все получается.
beer.gif

Цитата(ukpyr @ Mar 4 2011, 01:06) *
Цитата(zombi @ Mar 3 2011, 20:13) *

Осталось только выяснить : приводит ли к исчепанию ресурса стирание(запись значения FFH) в ячейку которая и до того была FFH

Полезно перед записью каждого байта проверять на равенство записанному. Уменьшается износ и часто сильно ускоряется обновление параметров. В одном проекте не хватало заряда конденсатора для сохранения в EEPROM после пропадания питания (больше 0.5сек), добавил проверку - успевало записать за десятки миллисекунд.

Т.е. получается что время на запись "тогоже самого" тратится по любому, а вот приводит ли это к износу еепром?
Go to the top of the page
 
+Quote Post
SysRq
сообщение Mar 5 2011, 12:29
Сообщение #30


Чайник, 1 литр
****

Группа: Свой
Сообщений: 655
Регистрация: 17-05-06
Из: Moscow
Пользователь №: 17 168



Цитата(zombi @ Mar 5 2011, 14:34) *
Т.е. получается что время на запись "тогоже самого" тратится по любому, а вот приводит ли это к износу еепром?
Убивается, ждём-с. Сейчас 1'248'000 циклов выполнено, пока жива...

(Хм, в программке вроде бы не наврал нигде.. в один и тот же адрес пишу 0xFF в количестве 992 штук, затем 8 значений с единичкой в разных разрядах, и в обоих случаях читаю и проверяю совпало ли, и циклы считаю.)

Код (ATMega128; здесь USB - мост на UART), на проверку, может ошибка где?
CODE
#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, проверим далее...

Сообщение отредактировал SysRq - Mar 5 2011, 15:03
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 20th July 2025 - 12:31
Рейтинг@Mail.ru


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