Самопрограмирование через Bootloader

Обсуждаем контроллеры компании Atmel.
Ответить
foregit
Первый раз сказал Мяу!
Сообщения: 39
Зарегистрирован: Вт фев 04, 2014 20:23:41

Самопрограмирование через Bootloader

Сообщение foregit »

Доброго времени суток.
Есть такая задача - дистанционно перешивать девайс. Девайс сделан на атмеге и из внешних интерфейсов имеет только езернет через мост на визнете. Идея состоит в том ,что в основной программе мы получаем прошивку и шьем ее в определенную часть флеша. Потом даем сброс контроллеру, он перегружается в boot, видит какой нибудь флаг перепрошивки (например определенную последовательность байт по определенному адресу) и переливает полученную дистанционно новую прошивку по нулевому уже адресу. Естественно для таких целей запас флеша на контроллере берется в 2 раза больший максимально возможной прошивки (с учетом бутлоадера).
Вопросы -
1. Были ли уже где нибудь решения похожих задач чтоб не изобретать велосипед?
2. Если нет и рыть самому -подскажите следующее - прописано что шить сам себя проц может только функциями, расположенными в секции загрузчика. Но в моему случае необходимо шить и из загрузчика и из основной программы. Так как это две разные собственно прошивки - как я могу обратиться из основной программы к функции записи флеша, скомпилированной для загрузчика? Или как решить такого плана задачу по другому?
Аватара пользователя
Ivanoff-iv
Друг Кота
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

Re: Самопрограмирование через Bootloader

Сообщение Ivanoff-iv »

если шить напрямую нельзя - попробуй другую память (eeprom или ОЗУ, возможно внешнее) или загрузчик учить по ЛАНу работать.
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
foregit
Первый раз сказал Мяу!
Сообщения: 39
Зарегистрирован: Вт фев 04, 2014 20:23:41

Re: Самопрограмирование через Bootloader

Сообщение foregit »

Отвечал в личку, перекину и сюда:

Аппнотов начитался вдоволь, и в принципе вся инфа почуть-чуть уже начала складываться на нужные полочки в голове, но перед тем как взяться за карандаш и нарисовать первый эскиз колеса к будущему велосипеду и задал вопрос тут - возможно уже кто-то на просторах уже задавался такими вопросами.

Все встреченные мною интернетовские буты умеют общаться по встроенным в проц протоколам - 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
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Самопрограмирование через Bootloader

Сообщение ARV »

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

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

Мой уютный бложик... заходите!
foregit
Первый раз сказал Мяу!
Сообщения: 39
Зарегистрирован: Вт фев 04, 2014 20:23:41

Re: Самопрограмирование через Bootloader

Сообщение foregit »

Согласен идея хорошая, хотя и бут , в отличие от основной прошивы (надеюсь) менять не придется. Тем более не реально его поменять дистанционно , только программатором на столе. Адреса будут константой после отладки и заливки бута.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Самопрограмирование через Bootloader

Сообщение ARV »

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

Мой уютный бложик... заходите!
foregit
Первый раз сказал Мяу!
Сообщения: 39
Зарегистрирован: Вт фев 04, 2014 20:23:41

Re: Самопрограмирование через Bootloader

Сообщение foregit »

Спасибо за подсказку
Аватара пользователя
Мурик
Друг Кота
Сообщения: 3383
Зарегистрирован: Пн окт 11, 2010 19:00:08

Re: Самопрограмирование через Bootloader

Сообщение Мурик »

foregit писал(а):Идея состоит в том ,что в основной программе мы получаем прошивку и шьем ее в определенную часть флеша.
Внешнего флеша? Потому что насколько помню, только из загрузчика можно прошивать флеш, а из основной программы не получится.
То что вы хотите поддерживается в МК других производителей, но не в мегах.
foregit
Первый раз сказал Мяу!
Сообщения: 39
Зарегистрирован: Вт фев 04, 2014 20:23:41

Re: Самопрограмирование через Bootloader

Сообщение foregit »

Нет, идея вот в чем - допустим я знаю что у меня прошивка будет не более 20кб. Я беру камень с заведомо большим флешем - допустим Atmega644 с 64к на борту.
Моя родная прошива сидит в нижних 20к. Когда я хочу обновить - я передаю ей через езернет новую прошивку. Обработка эзернета итак уже есть в основной прошивке. Камень ее получает и шьет в следующие 20к просто как поток данных, вызывая процедуры записи в флеш, находящиеся уже в составе предварительно зашитого бутлоадера.
Потом выставляю флаг что имеем новую прошиву и ресечусь. Естественно фьюзы выставлены так , что при старте сразу запускается бут, если нет флага - просто передает управление основной программе. при наличии флага просто запускается копирование прошивки с верхних 20к в положенные нижние и по окончании опять ресет.
Собственно так поступают абсолютное все бутлоадеры, разница только в том , как я писал выше, что прошивку они получают онлайн через какой нибудь интерфейс и сразу шьют.
В моем случае прошивка УЖЕ имеется на борту в виде данных - надо ее только перекинуть на положенные адреса.
Весь сыр бор тут и был - как обратиться к этим процедурам чтения/записи флеша, которые находятся в секции загрузчика. Выше был предложен вариант решения. Даже два.
Ну и вопрос - может кто то это уже реализовывал, не думаю я что это супер революционная идея.
Аватара пользователя
alex_
Опытный кот
Сообщения: 781
Зарегистрирован: Сб июн 01, 2013 22:24:21
Откуда: ПФО

Re: Самопрограмирование через Bootloader

Сообщение alex_ »

Я как то задумывался над проблемой нехватки места в бутлоадере, но времени как то стало крайне мало и я забросил, но была у меня мысля(если я неправ уважаемые знатоки, поправьте ход моих мыслей): контроллер мега шьётся постранично, т.е. я сам решаю какие страницы я хочу переписать и где, в этом вроде ограничений нет кроме одного нельзя прошить ботлодыря поскольку в этот момент он "работает". С другой стороны, если нет команды на обновление прошивки бут перенаправляет контроллер на выполнение основной программы. Смысл заключается в чём: к примеру берём контроллер мега16, допустим основная прошивка будет укладываться с лихой в первые 8 Кбайт а вот размер бута ну не как не укладывается в 1 Кбайт , то почему бы функции бута не разместить после 8 Кбайт основной программы. При старте бута сразу перенаправить на данную функцию, а при прошивке переписывать только те страницы в которых находятся в первых 8Кбайтах? :roll:
foregit
Первый раз сказал Мяу!
Сообщения: 39
Зарегистрирован: Вт фев 04, 2014 20:23:41

Re: Самопрограмирование через Bootloader

Сообщение foregit »

Ну по логике, как я понимаю, никто не мешает так делать. Если из основной области программы ты не будешь писать самое себя.
И это уже можно называть не бутлодырем, а просто каким нибудь "стартапом", который будет выполнять например какие то функции до основной программы, а не просто работать перепрошивальщиком.
А можно сделать 2 разные прошивки для одного и того же контроллера и переключаться между ними по какому то флагу в том же еепроме.
Полет фантазии никто не ограничивает.
foregit
Первый раз сказал Мяу!
Сообщения: 39
Зарегистрирован: Вт фев 04, 2014 20:23:41

Re: Самопрограмирование через Bootloader

Сообщение foregit »

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

А подскажите пожалуйста тогда как в авр-студии правильно это проделать?
То есть имея наши функции
uint16_t writeFlashPage(uint16_t waddr, pagebuf_t size),
uint16_t readFlashPage(uint16_t waddr, pagebuf_t size)
- какой конструкцией взять их адрес и записать/забрать в переменную в ОЗУ по определенному адресу?
Аватара пользователя
alex_
Опытный кот
Сообщения: 781
Зарегистрирован: Сб июн 01, 2013 22:24:21
Откуда: ПФО

Re: Самопрограмирование через Bootloader

Сообщение alex_ »

Есть такая директива ORG с помощью которой можно привязать переменные в том числе и функции к определённому месту в памяти

Код: Выделить всё

void func(int par) org 0x200 {
// Function will start at address 0x200
  asm nop;
}
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Самопрограмирование через Bootloader

Сообщение ARV »

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
Потрогал лапой паяльник
Сообщения: 353
Зарегистрирован: Вс янв 19, 2014 22:41:55

Re: Самопрограмирование через Bootloader

Сообщение Siarzhuk »

Засунуть обработку внешнего эзернета в бут нереально по размеру.

Делал для LPC2368/2378 на основе NXP-шного примера из аппнота по этой теме - не только езернет, но и примитивный ip с ARP,ICMP,DHCP,UDP уместился в 0x2000 байт. Принимает данные по UDP, шьёт вызовами встроенных IAP функций. При старте проверяет на наличие программы в первом блоке флеша за своим хвостом - и, либо передаёт управление этой программе, либо ждёт команд от внешней загружающей программы. Шьёт от последнего блока к первому - понятно почему. ;)
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)
foregit
Первый раз сказал Мяу!
Сообщения: 39
Зарегистрирован: Вт фев 04, 2014 20:23:41

Re: Самопрограмирование через Bootloader

Сообщение foregit »

Чтоб подытожить тему, опишу как в итоге реализовал на 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);
...


Вроде работает ;)
Спасибо всем за помощь.
Ответить

Вернуться в «AVR»