|
ПО для перепрошивки 8051, Дайте мудрый совет |
|
|
|
Sep 23 2009, 10:40
|
Группа: Участник
Сообщений: 6
Регистрация: 26-04-06
Пользователь №: 16 503

|
Встала задача по созданию программного обеспечения для обновления ПО 8051. Особенностью создаваемого устройства является то, что в процессе эксплуатации может потребоваться неоднократное обновление программного обеспечение. В связи с этим хочу спросить две вещи: 1. Можно ли вообще написать модуль ПО перепрошивки на Си? В проекте стоит опция максимальной оптимизации по размеру кода, при которой Кеil по идее может сам находить похожие куски кода и выделять их в подпрограммы. И тогда код, расположенный в ПО перепрошивки, будет вызывать код, который лежит за пределами области памяти программ перепрошивщика, что недопустимо. Остается только ассемблер? 2. Если все же писать на Си, то как жестко разместить программу перепрошивки с заданного адреса? Например 0xF800. И как это сделать в варианте на ассемблере.
|
|
|
|
|
Sep 23 2009, 23:59
|
Знающий
   
Группа: Свой
Сообщений: 540
Регистрация: 16-08-07
Из: Владивосток
Пользователь №: 29 831

|
Цитата(Jevys @ Sep 23 2009, 20:40)  Встала задача по созданию программного обеспечения для обновления ПО 8051. Особенностью создаваемого устройства является то, что в процессе эксплуатации может потребоваться неоднократное обновление программного обеспечение. В связи с этим хочу спросить две вещи: 1. Можно ли вообще написать модуль ПО перепрошивки на Си? В проекте стоит опция максимальной оптимизации по размеру кода, при которой Кеil по идее может сам находить похожие куски кода и выделять их в подпрограммы. И тогда код, расположенный в ПО перепрошивки, будет вызывать код, который лежит за пределами области памяти программ перепрошивщика, что недопустимо. Остается только ассемблер? 2. Если все же писать на Си, то как жестко разместить программу перепрошивки с заданного адреса? Например 0xF800. И как это сделать в варианте на ассемблере. 1. Можно, какая разница на чем писать. 2. В кейле project->options for target->bl51 locate. В asm это делается с помощью например ORG или смотрите далее. Найдите ее описание. Но в общем Вы ничего не написали о том как хотите обновлять прошивку. Если предположить, что Вы хотите по UART присылать новую прошиву и полностью переписывать содержимое внутренней flash-памяти программ, относящейся к основной программе. Следует прочитать "AN-112 UART IN-APPLICATION CODE LOADING EXAMPLES" у silabs. Я делал следующим образом. Создал 2 проекта - основной и bootloader. Основная прога ложится в память начиная, например, с адреса 0x100 (задается установками линкера). Естественно, вектора прерывания находятся по своим местам ниже этой точки. В проекте бутлоадера делаем установки линкера размещать код с выбранного Вами адреса 0xf800. Далее, в оба проекта явно добавляем копии стандартного startup.a51. Далее немного модифицируем эти копии. Для основного проекта: Код PUBLIC ?C_STARTUP
CSEG AT 100h <-измененный адрес! ?C_STARTUP: LJMP STARTUP1
RSEG ?C_C51STARTUP для бутлоадера: Код CSEG AT 0;делаем переход на нужный адрес 0xf800 LJMP 0f800h CSEG AT 0f800h; теперь прога начинается с этой позиции ?C_STARTUP: LJMP STARTUP1 Теперь при старте начинает выполняться бутлоадер. Если для него работы нет, то он передает управление основной программе вызовом application(); имеющей только прототип void (*application)(void)=(void code *)0x0100; Основная программа при выполнении получает новую прошиву, размещает ее во внешней памяти, выставляет какой нибудь флаг. После этого сбрасывает контроллер или переходит на выполнение строки по 0-му адресу, бутлоадер видит флаг и начинается ... Можно и самим бутлоадером получать прошиву. Зависит от Ваших требований. Описывайте подробнее желаемое. Можно и основную прогу начинать по 0-му адресу, а из нее вызывать бутлоадер. Но в моем варианте критическим является переписывание только 0-го сектора. Даже если в процессе перезаписи произошел сбой, пропадание питания или еще что-нибудь, бутлоадер начнет сначала. Для обоих проектов создаем HEX-файлы и объеденяем их в один, не забывая удалить в одном из них строку окончания файла. Получившийся файл загружаем в камень при первой прошивке. Ну и еще можно добавить в бутлоадер функции по расшифровке полученного перед записью во флэш и тогда можно прошивки передавать через третьих лиц
|
|
|
|
|
Sep 24 2009, 06:04
|
Группа: Участник
Сообщений: 6
Регистрация: 26-04-06
Пользователь №: 16 503

|
Обновление ПО представляю так: От компьютера по стандартному протоколу передачи данных через UART подается определенная команда, после которой происходит переход в программу перепрошивки, которая уже далее принимает по своему специальному протоколу пакеты с данными, содержащими код программы, и по мере поступления происывает их в память программ. Аварийный выход в программу перепрошивки только при включении питания при определенном нажатии кнопок (есть еще и такие).
А вообще спасибо за столь объемный ответ. Действительно, стало понятнее. Но надо будет еще самому подумать и все проверить.
|
|
|
|
|
Oct 5 2009, 22:04
|
Участник

Группа: Участник
Сообщений: 36
Регистрация: 1-05-06
Из: Одесса
Пользователь №: 16 644

|
Цитата(barabek @ Sep 24 2009, 02:59)  Можно и самим бутлоадером получать прошиву. не можно, а даже нужно! Следует исходить из того, что основная часть прошивки может испортиться как угодно. Поэтому для живучести надо стартовать в бутлоадер (для силабсов - в последний сектор), там посчитать контрольную сумму и проверить спецножку контроллера. Если сумма испорчена или ножка зажата в ноль - аварийно ждать прошивку и шить. При нормальной сумме и свободной ноге - переходить на основную программу, оттуда тоже должна быть возможность перейти на перепрошивку - это штатный способ обновления FW. Еще важный трюк: по адресу 0x0200 следует расположить еще один ljmp на бутлоадер. Для того, чтобы сброс контроллера при стертом первом секторе вывел на аварийную загрузку прошивки. А стереться первый сектор может как штатно (при неоконченной его перешивке), так и случайно по сбою.
|
|
|
|
|
Oct 21 2009, 16:33
|
Группа: Участник
Сообщений: 12
Регистрация: 8-10-09
Из: СПб
Пользователь №: 52 817

|
Доброго времени суток!!!
Столкнулся с такой-же задачей - программно прошивать CC1010. У контроллера CC1010 есть функция перепрошивки себя любимого, но, в отличае от Атмелов, у него нет "аппаратного" bootloader'а. Поделюсь своими мыслями по повод решения данной задачи и с удовольствием вышлушаю Вашу критику. Загрузчин думаю разместить с 0-го адреса, тогда при загрузки сразу будет запускаться bootloader. После загрузки он в течении некоторого времени "слушает" UART. Если по UART'у пришла команда перехода в режим программирования, то по тому-же UART'у кусками принемаем прошивку и шьем ее во флеш начиная с определенного адреса. Т.к. прошивается флеш по страницам в 128 байт, то адрес начала основной программы будет определяться так: адрес начала следующей, после конца bootloader'а, страницы (если bootloader заканчивается на середине третьей страницы, то основная программа начинается с четвертой). Если по UART'у команда перехода в режим программирования не пришла, пришла не та команда или уже все прошили, то прыгаем на адрес начала основной программы программы. Если действительно можно приказать Кейлу, чтобы он собирал hex начиная с определенного адреса так, чтобы вся программа, включая таблицу векторов прерывания, была тупо смещена, то проблем не должно быть.
Что скажите Господа? Кейл правда умеет такое делать? Заранее спасибо.
|
|
|
|
|
Oct 22 2009, 09:55
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(Goodvin @ Oct 21 2009, 19:33)  Если действительно можно приказать Кейлу, чтобы он собирал hex начиная с определенного адреса так, чтобы вся программа, включая таблицу векторов прерывания, была тупо смещена, то проблем не должно быть. Кейл правда умеет такое делать? Чисто теоритически - такое проделать, имхо, возможно: переопределить начало всех сегментов, размещаемых в памяти программ командами линкера... Сам я делал иначе. Делал так: Загрузчик располагал в конце памяти программ. Загрузчик работает исключительно по готовности (не использует прерывания). Тогда в таблице векторов на загрузчик указывает только команда по вектору 0. При записи в память программ прикладной программы загрузчик контролирует запись в этот (нулевой) вектор и сохраняет его неизменным, но "выкусывает" из загружаемай программы адрес перехода из команды по нулевому адресу и сохраняет его в выделенном месте памяти программ. Это "выкусывание" и сохранение адреса используется для последующего запуска прикладной программы. Приимущества: прикладную программу не нужно "корёжить". Единственное ограничение - прикладная программа должна использовать хоть один вектор прерывания, тогда по нулевому адресу Keil поместит команду JMP, из которой бутлоадер "выкусит" адрес старта прикладной программы.
|
|
|
|
|
Oct 22 2009, 20:44
|
Группа: Участник
Сообщений: 12
Регистрация: 8-10-09
Из: СПб
Пользователь №: 52 817

|
Доброго времени суток!!!
Вчера попробовал сместить адреса в Кейле. Делается это, как описывает уважаемый barabek: project->options for target->bl51 locate снимаем галачку "Use Memory Layuot..." в поле "Code Range" изменяем первый адрес на тот, который нужно. В моем случае, для CC1010, адрес можно менять на число байт, кратное 128, это следует из страничной организации памяти программ этого контроллера (256 страниц по 128 байт в каждой). Hex генерируется что надо, но таблица векторов прерывания все равно идет с нулегого адреса, что не удивительно:
БЫЛО:
:020000020000FC :100000000211E1000000000000000002114E4B2F21 :100010000E58000041FC9C0280604844810AFFC0E9 :10002000000000020FB2EF4E70038D9922AF058FD2 :10003000C12200000000000000000002108000004B :10004000000000020EDEBB010689828A83E0225096 :1000500002E722BBFE02E32289828A83E49322BB69 :10006000010CE58229F582E5833AF583E02250060A :10007000E92582F8E622BBFE06E92582F8E222E5C0 :100080008229F582E5833AF583E49322BB01068950 :10009000828A83F0225002F722BBFE01F322F8BBD2 :1000A000010DE58229F582E5833AF583E8F02250D7 :1000B00006E92582C8F622BBFE05E92582C8F222A0
СТАЛО:
:020000020000FC :1000000002121B0000000000000000021188000026 :1000100000000000000000000000000000000000E0 :10002000000000020FEC00000000000000000000D3 :1000300000000000000000000000000210BA0000F4 :10004000000000020F180000000000000000000087 :1000500000000000000000000000000000000000A0 :100060000000000000000000000000000000000090 :100070000000000000000000000000000000000080 :10008000BB010689828A83E0225002E722BBFE027E :10009000E32289828A83E49322BB010CE58229F55D :1000A00082E5833AF583E0225006E92582F8E622CC :1000B000BBFE06E92582F8E222E58229F582E58386
Правда в hex'нике изначальном в начале, где вектора прерывания, еще что-то есть, но я не знаю что это (например адрес 0x000E)
Щас думаю как в сложившейся ситуации разместить bootloader и как что будет работать.
Уважаемый Палыч, не понял фразу "загрузчик работает исключительно по готовности" это как, нельзя ли описать по подробнее? И еще, как вы принемаете прошивку, если bootloader работает не по прерываниям? Думаю, что в моем случае не получится реализовать Ваше решение из-за страничной организации памяти.
|
|
|
|
|
Oct 23 2009, 16:16
|
Группа: Участник
Сообщений: 12
Регистрация: 8-10-09
Из: СПб
Пользователь №: 52 817

|
Доброго времени суток!!! А может быть в памяти программ 2 таблицы векторов прерываний (одна bootloader'a вторая прикладной программы)? Так, что бы пока bootloader работает, выполнялись его обработчики прерываний, а когда выполняется прикладная программа, то исполняются ее обработчики. 2Редактор А нельзя ли поподробнее о STARTUP'е, а то я не догоню что-то.
|
|
|
|
|
Oct 24 2009, 00:27
|
Знающий
   
Группа: Свой
Сообщений: 540
Регистрация: 16-08-07
Из: Владивосток
Пользователь №: 29 831

|
Цитата(Goodvin @ Oct 24 2009, 03:16)  Доброго времени суток!!! А может быть в памяти программ 2 таблицы векторов прерываний (одна bootloader'a вторая прикладной программы)? Так, что бы пока bootloader работает, выполнялись его обработчики прерываний, а когда выполняется прикладная программа, то исполняются ее обработчики. 2Редактор А нельзя ли поподробнее о STARTUP'е, а то я не догоню что-то.  Было бы хорошо иметь несколько таблиц, но чудес не бывает. В своей программе Вы можете прописать обработчики прерываний по любым адресам ( при большом желании ) . Однако в железе при приходе прерывания переход будет осуществлен на строго определенный НЕИЗМЕНЯЕМЫЙ адрес, прописаный в документации. Не пытайтесь никак это изменить, не получится. А по второму вопросу. В каждый проект на С добавляется файл startup.a51, который исполняется после сброса контроллера до перехода на Вашу функцию main. Поиском найдете у себя на компе. При желании можете его менять под свои нужды. Как? Найдите недавно был пост типа "не могу записать в xdata". Извините, пишу с телефона и мне нужно бежать :-). Потом если что ...
|
|
|
|
|
Oct 26 2009, 15:24
|
Группа: Участник
Сообщений: 12
Регистрация: 8-10-09
Из: СПб
Пользователь №: 52 817

|
Доброго времени суток!!!
Думаю поступить так: bootloader расположить в начальных адресах. В стартапе bootloader'а переопределить все вектора прерывания (кроме тех, что используются в bootloader'е) на адреса, где во флеше будет таблица прерываний прикладной программы. Тогда по прерыванию контроллер идет по адресу прописаному в документации, а там ему говорят иди по новому адресу. Придя по новому адресу он обрабатывает прерывание. Но получается, что если я в bootloader'е буду использовать прерывания по UART'у и таймеру, то в прикладной программе их юзать уже на получится?
Еще вариант расположить bootloader в последних адресах. Тогда прикладная программа при прерываниях не будет скакать по адресам, но там другие загвоздки есть.
Я правильно уловил логику "колдования" со стартапом?
Уважаемый barabek, не могли бы Вы написать о стартапе или дать ссылку.
|
|
|
|
|
Oct 26 2009, 16:20
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(Goodvin @ Oct 26 2009, 18:24)  Но получается, что если я в bootloader'е буду использовать прерывания по UART'у и таймеру, то в прикладной программе их юзать уже на получится? Ну, почему же - не получится... Просто переход по прерыванию в прикладной программе получится длиннее: нужна будет переменная - флаг работы прикладной программы. При прерываниях по UART и таймеру придётся её проверять и переходить на переопределённый вектор или выполнять некие действия для бутлоадера. Цитата(Goodvin @ Oct 26 2009, 18:24)  Еще вариант расположить bootloader в последних адресах. Тогда прикладная программа при прерываниях не будет скакать по адресам, но там другие загвоздки есть. Это какие загвоздки? Работа бутлоадера по-готовности устройств? Проверять циклически несколько флагов в регистрах - это разве так сложно? Цитата(Goodvin @ Oct 26 2009, 18:24)  ... не могли бы Вы написать о стартапе или дать ссылку. Что Вы хотите узнать о стартапе? Посмотрите на стартап сами - файлы для разных МК лежат в Keil/C51/Lib
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|