Форум РадиоКот https://radiokot.ru/forum/ |
|
Самопрограмирование через Bootloader https://radiokot.ru/forum/viewtopic.php?f=57&t=146929 |
Страница 1 из 1 |
Автор: | foregit [ Чт июл 20, 2017 07:39:18 ] |
Заголовок сообщения: | Самопрограмирование через Bootloader |
Доброго времени суток. Есть такая задача - дистанционно перешивать девайс. Девайс сделан на атмеге и из внешних интерфейсов имеет только езернет через мост на визнете. Идея состоит в том ,что в основной программе мы получаем прошивку и шьем ее в определенную часть флеша. Потом даем сброс контроллеру, он перегружается в boot, видит какой нибудь флаг перепрошивки (например определенную последовательность байт по определенному адресу) и переливает полученную дистанционно новую прошивку по нулевому уже адресу. Естественно для таких целей запас флеша на контроллере берется в 2 раза больший максимально возможной прошивки (с учетом бутлоадера). Вопросы - 1. Были ли уже где нибудь решения похожих задач чтоб не изобретать велосипед? 2. Если нет и рыть самому -подскажите следующее - прописано что шить сам себя проц может только функциями, расположенными в секции загрузчика. Но в моему случае необходимо шить и из загрузчика и из основной программы. Так как это две разные собственно прошивки - как я могу обратиться из основной программы к функции записи флеша, скомпилированной для загрузчика? Или как решить такого плана задачу по другому? |
Автор: | Ivanoff-iv [ Чт июл 20, 2017 08:42:31 ] |
Заголовок сообщения: | Re: Самопрограмирование через Bootloader |
если шить напрямую нельзя - попробуй другую память (eeprom или ОЗУ, возможно внешнее) или загрузчик учить по ЛАНу работать. |
Автор: | foregit [ Чт июл 20, 2017 10:38:58 ] |
Заголовок сообщения: | Re: Самопрограмирование через Bootloader |
Отвечал в личку, перекину и сюда: Аппнотов начитался вдоволь, и в принципе вся инфа почуть-чуть уже начала складываться на нужные полочки в голове, но перед тем как взяться за карандаш и нарисовать первый эскиз колеса к будущему велосипеду и задал вопрос тут - возможно уже кто-то на просторах уже задавался такими вопросами. Все встреченные мною интернетовские буты умеют общаться по встроенным в проц протоколам - uart, spi, в более сложных usb и при этом бут получает прошиву в онлайн. Засунуть обработку внешнего эзернета в бут нереально по размеру. Потому возник такой вариант. Когда прошива получается в основном теле, а потом бут ее переливает куда надо. Понятно что буду писать свой бут. Пока для себя не уяснил как из основного тела обратиться к заранее прописанным в буте процедурам записи во флеш, ибо они по требованиям атмеловцев обязаны быть там. Update: Правда за это время наткнулся на вариант (закину сюда может еще кого заинтересует): Цитата: 1. Смотрю адрес нужной функции в IAR map файле: flash_page_write CODE 0001F72E 2. Создаю в основной программе указатель: void (*flash_page_write)(unsigned short) = (void (*)(unsigned short))0x1F72E; При этом IAR выдаёт предупреждение. Warning[Pe1053]: conversion from integer to smaller pointer 3. Записываю в кристалл boot, затем с его помощью загружаю и запускаю приложение. 4. Пытаюсь записать страницу памяти. Затем всё зависает. Вероятно не происходит возврата из вызванной функции. ...... Проверьте адресацию в map-файле. Вполне вероятно, что она байтовая и тогда Вы вызываете функцию по случайному адресу вместо (0x1F72E>>1); ...... Вам нужно такой оператор. void (*flash_page_write)(unsigned short) = (void (*)(unsigned short))0xFB97; // (0x1F72E>>1); Флеш адресуется пословно, но в мепе указан побайтовый, который в 2-раза больший. ...... >> в мепе указан побайтовый Таки Бинго, работает! void (*flash_wr_block)(unsigned char*, long, unsigned short) = (void (*)(unsigned char*, long, unsigned short))(0x1F004>>1); Позвал из bootloader более высокоуровневую: flash_wr_block(pMem, fl_address, 256); Нормально пишет по всему CODE area; Надо попробовать... |
Автор: | ARV [ Чт июл 20, 2017 10:43:00 ] |
Заголовок сообщения: | Re: Самопрограмирование через Bootloader |
можно обойтись без map-файла. т.к. по сбросу обычно получает управление бут, который затем переводит стрелки на основную программу, достаточно в обоих программах (бута и главной) прописать по фиксированному адресу в ОЗУ указатель на таблицу интерфейсных функций, и на этом все. бут начинает работу с того, что пишет в эти ячейки адрес таблицы с адресами своих интерфейсных функций, а главая программа, когда получает управление, пользуется этим адресом. анализировать map-файл всякий раз после пересборки бута не потребуется. |
Автор: | foregit [ Чт июл 20, 2017 11:59:04 ] |
Заголовок сообщения: | Re: Самопрограмирование через Bootloader |
Согласен идея хорошая, хотя и бут , в отличие от основной прошивы (надеюсь) менять не придется. Тем более не реально его поменять дистанционно , только программатором на столе. Адреса будут константой после отладки и заливки бута. |
Автор: | ARV [ Чт июл 20, 2017 12:19:13 ] |
Заголовок сообщения: | Re: Самопрограмирование через Bootloader |
Я имел ввиду процесс разработки бута - намучаетесь всякий раз перепроверять точки входа, пока до ума доведете. только об этом беспокоюсь ![]() |
Автор: | foregit [ Чт июл 20, 2017 13:06:08 ] |
Заголовок сообщения: | Re: Самопрограмирование через Bootloader |
Спасибо за подсказку |
Автор: | Мурик [ Чт июл 20, 2017 15:48:18 ] |
Заголовок сообщения: | Re: Самопрограмирование через Bootloader |
foregit писал(а): Идея состоит в том ,что в основной программе мы получаем прошивку и шьем ее в определенную часть флеша. Внешнего флеша? Потому что насколько помню, только из загрузчика можно прошивать флеш, а из основной программы не получится.То что вы хотите поддерживается в МК других производителей, но не в мегах. |
Автор: | foregit [ Чт июл 20, 2017 19:18:34 ] |
Заголовок сообщения: | Re: Самопрограмирование через Bootloader |
Нет, идея вот в чем - допустим я знаю что у меня прошивка будет не более 20кб. Я беру камень с заведомо большим флешем - допустим Atmega644 с 64к на борту. Моя родная прошива сидит в нижних 20к. Когда я хочу обновить - я передаю ей через езернет новую прошивку. Обработка эзернета итак уже есть в основной прошивке. Камень ее получает и шьет в следующие 20к просто как поток данных, вызывая процедуры записи в флеш, находящиеся уже в составе предварительно зашитого бутлоадера. Потом выставляю флаг что имеем новую прошиву и ресечусь. Естественно фьюзы выставлены так , что при старте сразу запускается бут, если нет флага - просто передает управление основной программе. при наличии флага просто запускается копирование прошивки с верхних 20к в положенные нижние и по окончании опять ресет. Собственно так поступают абсолютное все бутлоадеры, разница только в том , как я писал выше, что прошивку они получают онлайн через какой нибудь интерфейс и сразу шьют. В моем случае прошивка УЖЕ имеется на борту в виде данных - надо ее только перекинуть на положенные адреса. Весь сыр бор тут и был - как обратиться к этим процедурам чтения/записи флеша, которые находятся в секции загрузчика. Выше был предложен вариант решения. Даже два. Ну и вопрос - может кто то это уже реализовывал, не думаю я что это супер революционная идея. |
Автор: | alex_ [ Чт июл 20, 2017 21:00:14 ] |
Заголовок сообщения: | Re: Самопрограмирование через Bootloader |
Я как то задумывался над проблемой нехватки места в бутлоадере, но времени как то стало крайне мало и я забросил, но была у меня мысля(если я неправ уважаемые знатоки, поправьте ход моих мыслей): контроллер мега шьётся постранично, т.е. я сам решаю какие страницы я хочу переписать и где, в этом вроде ограничений нет кроме одного нельзя прошить ботлодыря поскольку в этот момент он "работает". С другой стороны, если нет команды на обновление прошивки бут перенаправляет контроллер на выполнение основной программы. Смысл заключается в чём: к примеру берём контроллер мега16, допустим основная прошивка будет укладываться с лихой в первые 8 Кбайт а вот размер бута ну не как не укладывается в 1 Кбайт , то почему бы функции бута не разместить после 8 Кбайт основной программы. При старте бута сразу перенаправить на данную функцию, а при прошивке переписывать только те страницы в которых находятся в первых 8Кбайтах? ![]() |
Автор: | foregit [ Чт июл 20, 2017 22:08:42 ] |
Заголовок сообщения: | Re: Самопрограмирование через Bootloader |
Ну по логике, как я понимаю, никто не мешает так делать. Если из основной области программы ты не будешь писать самое себя. И это уже можно называть не бутлодырем, а просто каким нибудь "стартапом", который будет выполнять например какие то функции до основной программы, а не просто работать перепрошивальщиком. А можно сделать 2 разные прошивки для одного и того же контроллера и переключаться между ними по какому то флагу в том же еепроме. Полет фантазии никто не ограничивает. |
Автор: | foregit [ Пт июл 21, 2017 20:41:00 ] |
Заголовок сообщения: | Re: Самопрограмирование через Bootloader |
можно обойтись без map-файла. т.к. по сбросу обычно получает управление бут, который затем переводит стрелки на основную программу, достаточно в обоих программах (бута и главной) прописать по фиксированному адресу в ОЗУ указатель на таблицу интерфейсных функций, и на этом все. бут начинает работу с того, что пишет в эти ячейки адрес таблицы с адресами своих интерфейсных функций, а главая программа, когда получает управление, пользуется этим адресом. А подскажите пожалуйста тогда как в авр-студии правильно это проделать? То есть имея наши функции uint16_t writeFlashPage(uint16_t waddr, pagebuf_t size), uint16_t readFlashPage(uint16_t waddr, pagebuf_t size) - какой конструкцией взять их адрес и записать/забрать в переменную в ОЗУ по определенному адресу? |
Автор: | alex_ [ Сб июл 22, 2017 10:07:41 ] |
Заголовок сообщения: | Re: Самопрограмирование через Bootloader |
Есть такая директива ORG с помощью которой можно привязать переменные в том числе и функции к определённому месту в памяти Код: void func(int par) org 0x200 {
// Function will start at address 0x200 asm nop; } |
Автор: | ARV [ Сб июл 22, 2017 19:07:21 ] |
Заголовок сообщения: | Re: Самопрограмирование через Bootloader |
foregit писал(а): А подскажите пожалуйста тогда как в авр-студии правильно это проделать? То есть имея наши функции uint16_t writeFlashPage(uint16_t waddr, pagebuf_t size), uint16_t readFlashPage(uint16_t waddr, pagebuf_t size) - какой конструкцией взять их адрес и записать/забрать в переменную в ОЗУ по определенному адресу? Код: typedef uint16_t (*function)(uint16_t, pagebuf_t); // объявили тип "указатель на функцию" имя функции - это указатель на ее адрес.
static const __flash function interface[2] = {writeFlashPage, readFlashPage}; // массив с адресами наших функций во flash uint16_t result = interface[0](0, 64); // вызвали первую функцию result = interface[1](0, 64); // вызвали вторую |
Автор: | Siarzhuk [ Вс июл 23, 2017 09:02:24 ] |
Заголовок сообщения: | Re: Самопрограмирование через Bootloader |
Засунуть обработку внешнего эзернета в бут нереально по размеру. Делал для LPC2368/2378 на основе NXP-шного примера из аппнота по этой теме - не только езернет, но и примитивный ip с ARP,ICMP,DHCP,UDP уместился в 0x2000 байт. Принимает данные по UDP, шьёт вызовами встроенных IAP функций. При старте проверяет на наличие программы в первом блоке флеша за своим хвостом - и, либо передаёт управление этой программе, либо ждёт команд от внешней загружающей программы. Шьёт от последнего блока к первому - понятно почему. ![]() |
Автор: | foregit [ Вт авг 15, 2017 07:24:02 ] |
Заголовок сообщения: | Re: Самопрограмирование через Bootloader |
Чтоб подытожить тему, опишу как в итоге реализовал на Atmel Studio: Bootloader: Код: uint16_t writeFlashPage(uint16_t waddr, uint8_t *pBuff, pagebuf_t size) { .... } uint16_t readFlashPage(uint16_t waddr, uint8_t *pBuff, pagebuf_t size) { ... } typedef uint16_t (*flashfunc_t)(uint16_t, uint8_t*, pagebuf_t); // объявили тип "указатель на функцию" //Сохраним адреса функций работы с флеш памятью по фиксированному адресу //секция flashfunc описана в настройках линкера (-Wl,--section-start=.flashfunc=0xFFF0) const flashfunc_t flashfunc[2] __attribute__ ((section (".flashfunc"))) = {writeFlashPage, readFlashPage}; // массив с адресами наших функций во flash Main: Код: typedef uint16_t (*flashfunc_t)(uint16_t, uint8_t*, uint16_t); // объявили тип "указатель на функцию" flashfunc_t flashwr, flashrd; void InitFlashFunc (void) { uint16_t* fwr = (uint16_t*)0xfff0; uint16_t* frd = (uint16_t*)0xfff2; flashwr = (flashfunc_t)pgm_read_word(fwr); flashrd = (flashfunc_t)pgm_read_word(frd); } ... flashwr(pagenum*0x100, pagebuf, 256); ... Вроде работает ![]() Спасибо всем за помощь. |
Страница 1 из 1 | Часовой пояс: UTC + 3 часа |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |