Цитата
Как советует zltigo, храните в заранее оговоренном месте в начале программы (например, сразу после векторов) адрес, по которому расположена контрольная сумма.
Не, контрольную сумму (КС) храню в EEPROM, а адрес КС в EEPROM -- простая константа.
Цитата
объявляете в скрипте линкера, в самом конце раздела SECTIONS фиктивный кусочек выходной секции .text (чтобы он разместился после уже заполненной .text и инициализирующих значений .data), объявляете в нем символ и присваиваете ему значение текущего адреса
Попробовал, не подходит. В этом случае _app_end у меня всегда равно уже существующей _etext.
Цитата
а в программе объявляете фиктивную внешнюю переменную с таким именем и берете ее адрес.
А как правильно объявить? Какого она должна быть типа? У меня в итоге получилось, но как-то "через одно место" это работает, но работает правильно.
Цитата
(injen-d @ Apr 8 2008, 21:46) ЗЫ: на асме это делалось элементарно... Можно пример?
_Pasha Вам ответил, это банальная метка в конце программы.
Цитата
А чем плохо CRC всего набортного флеша (либо до boot - секции) ?
Пока хватает простого побайтового суммирования по модулю 256 или 65536, по вкусу.
И зачем контролировать неиспользуемые байты? При порче хоть одного из них, программа начнет бить ложную тревогу, оставаясь при этом полностью работоспособной. А вдруг это (порча) случится
"на самом интересном"
Как я уже сказал, _app_end у меня всегда равно уже существующей _etext, а _edata = (0x100 + количество инициализируемых переменных (при выравнивании, еще +1))
девайс - ATmega645;
По hex-файлу убедился, что _etext меньше адреса последнего записываемого во флеш байта как раз на количество инициализируемых переменных(ес-но "байтовость" переменных тоже учел),
таким образом объявляем в скрипте линкера в самом конце:
Код
......
_size_prog = _etext +(_edata -0x100);
}
далее используем в функции подсчета.
Привожу свою функцию, может кому будет интересно. В железе пока не проверял, за его отсутствием, но данный алгоритм (реализованный на асме) успешно работает в других готовых девайсах.
Как надо объявлять в функции переменную _size_prog, на сколько я убедился - без разницы, но есть важная особенность: переменная _size_prog не содержит ничего, а вот ее адрес и есть адрес последнего байта, записываемого во флеш.
При попытке использовать _size_prog как есть, компилятор генерит код, пытающийся загрузить значение из ОЗУ с адреса последнего используемого байта во флеш!
Код
//===================================================================
//Функция считает побайтовою сумму flash-памяти с 0 по последний используемый байт;
//Контрольная сумма (КС) хранится в EEPROM;
//Если в EEPROM имеется достоверная КС (байт в EEPROM по адресу f_ee_summ равен 0xAE), то сравнение,
//если нет (первое включение МК после программирования), то запись в EEPROM подсчитанной суммы и
//значения 0xAE по адресу f_ee_summ, затем рекурсивный вызов самой себя;
//Возвращаемое значение: 0 - норма, 0x12 - код ошибки "Ошибка контрольной суммы памяти программ";
#define ee_summ 0x40 //адрес расположения в EEPROM контрольной суммы
#define f_ee_summ 0x30 //адрес в EEPROM флага наличия посчитанной контрольной суммы
extern const uint8_t _size_prog; //переменная _size_prog должна быть определена в скрипте линкера,
//в конце SECTIONS, следующим образом: _size_prog =_etext +(_edata-0x100); uint8_t summ_flash(void)
{
uint16_t summ = 0;
uint16_t adr = 0;
uint8_t f_err;
do
{
summ += (uint16_t)pgm_read_byte(adr); //побайтовое суммирование; сумма 16-битовая
adr++;
} while (adr < (const uint16_t)(&_size_prog)+1); //пока адрес меньше, чем (последний байт во Flash)+1
if (eeprom_read_byte((uint8_t*)f_ee_summ)==0xAE) //если имеется посчитанная сумма
{
if (eeprom_read_word((uint16_t*)ee_summ) != summ) //если контрольная сумма не совпала-
f_err = 0x12; // - вернуть код ошибки,
else f_err = 0; // иначе - 0;
}
else //если посчитанной суммы нет (первое включение МК после программирования)
{
eeprom_write_word((uint16_t*)ee_summ, summ); //запись подсчитанной суммы
eeprom_write_byte((uint8_t*)f_ee_summ, 0xAE); //запись флага наличия достоверной суммы
while(EECR & (1<<EEWE)); //ждать окончания записи в EEPROM
f_err = summ_flash();
}
return f_err;
}