Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Скрипты линкера ld
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > GNU/OpenSource средства разработки
EugeNNe
Возникла задача подсчитать CRC прошивки загружаемой во флэш AVR и писать в CRC ну скажем в последнюю ячейку памяти. Считать СRC бинарного файла и потом отдельно загружать в память совсем неудобно. Хотелось бы что бы в WinAVR собрал проект и загрузил. Люди подсказали что такое можно сотворить если написать скрипт для линкера. Сейчас с этим разбираюсь. Но может быть кто то подобное уже делал и есть примерчик. Просто время жмёт, а доки на ld немало надо сказать...

P.S. И хотелось бы полагать что CRC надо посчитать и загрузить куда надо.
А вопрос "зачем это надо?" несущественен....
Сергей Борщ
Цитата(BigBolt @ Mar 26 2009, 14:55) *
Возникла задача подсчитать CRC прошивки загружаемой во флэш AVR и писать в CRC ну скажем в последнюю ячейку памяти. Считать СRC бинарного файла и потом отдельно загружать в память совсем неудобно. Хотелось бы что бы в WinAVR собрал проект и загрузил. Люди подсказали что такое можно сотворить если написать скрипт для линкера.
Что-то я не припомню, чтобы ld умел считать CRC. Почему неудобно считать и загружать? ld должен зарезервировать место в прошивке. Srecord умеет считать CRC и вставлять ее в указанное место HEX-файла. Вызов SRecord можно добавить в качестве одной из целей в makefile.
EugeNNe
Цитата(Сергей Борщ @ Mar 26 2009, 18:29) *
Что-то я не припомню, чтобы ld умел считать CRC. Почему неудобно считать и загружать? ld должен зарезервировать место в прошивке. Srecord умеет считать CRC и вставлять ее в указанное место HEX-файла. Вызов SRecord можно добавить в качестве одной из целей в makefile.


Вопрос не в том кто будет CRC считать, а в том что бы автоматизировать процесс. Спасибо за ссылочку, будем изучать.... Мне вообще тоже казалось что вроде как подсчёт CRC не задача линкера...
IgorKossak
Цитата(BigBolt @ Mar 26 2009, 18:58) *
Мне вообще тоже казалось что вроде как подсчёт CRC не задача линкера...

С IARовским линкером спутали.
demiurg_spb
Тоже думал на эту тему. И подумалось что не надо CRC пихать в последнюю ячейку памяти (т.е. в конец адресного пространства ПЗУ), а лучше сразу после программы. Так-как можно сильно снизить надежность устройства в случае большого неиспользованного пространства ПЗУ.
ARV
может, я недопонимаю чего-то... но как подсчет CRC программного кода повышает надежность ПО? вот мои рассуждения.

1. программа, в которой искажен хотя бы 1 бит в коде не может считаться корректной.
2. результат работы некорректной программы не может быть признан достоверным и не должен никак использоваться.

теперь на основе этого проанализируем ситуацию: программа запустилась и посчитала CRC своего собственного кода - CRC совпала с контрольной. можно ли сделать вывод о том, что памяти программ находятся неискаженные данные? Предположим, искажение содержимого памяти произошло именно в участке подсчета CRC, в результате чего алгоритм стал недостоверным...

далее - если CRC не совпала... что делать в этом случае? просто "зависнуть"? ведь надеяться, что даже какое-то мигание светодиодом при работе НЕКОРРЕКТНОЙ программы будет исполнено правильно - нельзя... и чем такое "зависание" будет отличаться от зависания полноценного (из-за нарушения ПЗУ)?

не самообман ли это - самоподсчет CRC?
Сергей Борщ
Цитата(ARV @ Mar 27 2009, 10:45) *
не самообман ли это - самоподсчет CRC?
Нет. Почему вы априори думаете, что будет считаться CRC всей программы? Самое распространенное применение - загрузчики. Загрузчик зашивается один раз и не меняется. Приложение записывается в другую область памяти (а может и в ОЗУ). В процессе обновления приложения может произойти сбой и приложение будет испорчено (или не до конца записано, что то же самое). Загрузчик при этом остается целым и вполне может посчитать CRC приложения и сделать вывод - передавать ему управление или нет.
ARV
а, ну в таком контексте - я согласен. я почему-то считал, что считается CRC всей флеши... спасибо.
Harbour
скрипт-то тут нафиг ненужен - в makefile вставляем генератор CRC после objcopy :

%.bin: %.elf
$(OBJCOPY) -j .data -j .text -j .board -O $(FORMAT) $< $@
@gencrc $@

его задача тупо дописать CRC в конец бинарной паршивки. В проге пишем что-то типа :

....
u32 plen = (u32)((&_etext + (&_edata - &__data_start)) - (unsigned long) AT91C_IFLASH);
u16 *crc = (u16 *)((unsigned long) AT91C_IFLASH + plen);
printf("Bootloader size - %d bytes, crc - 0x%X [ %s ]\r\n", plen, *crc,
(compute_csum((unsigned char *) AT91C_IFLASH, plen) == *crc) ? "valid" : "*** invalid ***");
....

это кусман от арм, но принцип тот же и для AVR. compute_csum - это та-же f() только внутри паршивки
demiurg_spb
Цитата(Harbour @ Mar 27 2009, 14:38) *
это кусман от арм, но принцип тот же и для AVR. compute_csum - это та-же f() только внутри паршивки
Спасибо Вам за мысль. Правильно-ли я Вас понимаю, что загрузчик вызывает функцию верификации CRC из области приложения?
Как быть если хочется поместить в сам загрузчик и эту функцию. Т.е. как bootloader узнает размер уже запрограммированной прошивки для верификации CRC только по реально используемой flash?

Может на загрузчик возложить обязанность первоначального расчёта CRC сразу после обновления.
Ведь в этот момент известен размер прошивки.
Если boot контролирует правильность записи каждой отдельной страницы и протокол обмена тоже гарантирует целостность, то на мой взгляд можно...
После окончания обновления записать в последнюю ячейку размер прошивки и рядышком CRC (посчитанное и по байтикам размера прошивки).
Harbour
Да, правильно. Так ее туды и помещают wink.gif узнает размер он с помощью выше указанной строчки :

...
u32 plen = (u32)((&_etext + (&_edata - &__data_start)) - (unsigned long) AT91C_IFLASH);
...

plen - это и есть размер бинарной прошивки внутри контроллера, сразу за ней следует CRC, которую мы уже дописали из makefile. Можно и на загрузчик возложить - но гембеля много - обычно CRC так просто не запишешь - нужно запоминать/стирать страницу - а если питание в это время пропало ? или выносить CRC в отдельную страницу. И потом непонятно - если CRC не совпадает - это что испортились данные или просто загрузчик ее еще не обновил ?

Мой же принцип очень прост и надежен :

- CRC загрузчика я точно знаю после генерации бинарной прошвики
- исполняемый файл содержит заранее вычисленную на хосте и верную CRC прошивки, добавляется она в конец прошивки, много места не содержит и легко вычисляется, как на хосте (по размеру исходного bin файла) так и в MCU (по метке конца данных)
- менятся она не должна - если это произошло до нарушена целостность данных во флеше и нужно принимать меры

Другое дело, что в проекте bootloader работает только в начальный момент, его задача проверить себя, проверить приложение и запустить его. вот CRC самого приложения можно уже вместе с набором параметров класть в отдельную страницу флеша и обновлять после того как юзер залил новую версию приложения через этот самый bootloader.
demiurg_spb
Цитата(Harbour @ Mar 28 2009, 11:06) *
Мой же принцип очень прост и надежен :

- CRC загрузчика я точно знаю после генерации бинарной прошвики
- исполняемый файл содержит заранее вычисленную на хосте и верную CRC прошивки, добавляется она в конец прошивки, много места не содержит и легко вычисляется, как на хосте (по размеру исходного bin файла) так и в MCU (по метке конца данных)
Можете про метку конца данных подробнее. Уж больно всё это интересноsmile.gif Спасибо за пояснения!
Harbour
Конец данных, обычно это и есть последнее что записывается в прошивку, вот классический пример :

...........
.data : AT (_etext)
{
__data_start = . ;
*(.data)
*(.data.*)
SORT(CONSTRUCTORS)
. = ALIGN(4);
*(.fastrun) /* "RAM-Functions" */ /* added by mthomas */

} > DATA

. = ALIGN(4);

_edata = . ;
PROVIDE (edata = .);
..........................................

Если нет своих или каких либо специальных секций, то содержимое прошивки представляет собой две секции : .text и .data, длины которых известны на этапе линковки и могут быть доступны для вычисления изнутри программы непосредственно по меткам линкера. Это как-бы азы работы с ld - описано по многу раз, как в инете, так и тут на форуме.
В данном случае разбивают проект на crypto bootloader и приложение (app), выделяем 1 страницу флеш для хранения app crc и ее параметров (serial number, version и т.д.), размещаем их в памяти последовательно (bootloader + param page + app):

- шьем бутлодер
- шьем с помощью бутлодера app (в этом месте бутлодер уже знает длину app)
- бутлодер вычисляет app crc и вместе с переданными параметрами записывает все это дело в param page
- при старте бутлодер проверяет себя, проверяет приложение, и если все пучком - стартует его
- если нет - переходит в режим ожидания/программирования с соответствующей индикацией/сообщением
boldgambler
а где бы можно посмотреть примеры скрипта линкера для AVR ?
а то для арма почти в каждом проекте и скрипт и startup, а для AVR ни того ни другого не могу встретить в каком нить тестом проекте для gcc.
правда в отличии от арма тут прошивка и так компилится, но видно он откуда-то библиотечные startup и ld по умолчанию берет.
где бы почитать как его составлять этот скрипт?
Сергей Борщ
Цитата(boldgambler @ Dec 17 2009, 16:06) *
а где бы можно посмотреть примеры скрипта линкера для AVR ?
В WinAVR - C:\WinAVR\avr\lib\ldscripts. В линуксе - аналогичная папка, в которую становятся binutils-avr.

Цитата(boldgambler @ Dec 17 2009, 16:06) *
а то для арма почти в каждом проекте и скрипт и startup, а для AVR ни того ни другого не могу встретить в каком нить тестом проекте для gcc.
правда в отличии от арма тут прошивка и так компилится, но видно он откуда-то библиотечные startup и ld по умолчанию берет.
ARMы слишком разные, и слишком разные конфигурации карт памяти возможны в системах с внешними ОЗУ/ПЗУ. У AVR все внутри, поэтому базовые скрипты вшиты в линкер.
Цитата(boldgambler @ Dec 17 2009, 16:06) *
где бы почитать как его составлять этот скрипт?
В документации на binutils
boldgambler
спасибо. буду смотреть.
а когда имеет смысл писать свой скрипт? только если создаешь какие то секции где хочешь например меню расположить? ну или например разделить системные и пользовательские данные в памяти?
Сергей Борщ
Цитата(boldgambler @ Dec 17 2009, 17:01) *
а когда имеет смысл писать свой скрипт?
Когда вас не устраивает раскладка памяти, предоставляемая стандартным скриптом.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.