Обсуждаем контроллеры компании Atmel.
Ответить

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

Чт июл 20, 2017 07:39:18

Доброго времени суток.
Есть такая задача - дистанционно перешивать девайс. Девайс сделан на атмеге и из внешних интерфейсов имеет только езернет через мост на визнете. Идея состоит в том ,что в основной программе мы получаем прошивку и шьем ее в определенную часть флеша. Потом даем сброс контроллеру, он перегружается в boot, видит какой нибудь флаг перепрошивки (например определенную последовательность байт по определенному адресу) и переливает полученную дистанционно новую прошивку по нулевому уже адресу. Естественно для таких целей запас флеша на контроллере берется в 2 раза больший максимально возможной прошивки (с учетом бутлоадера).
Вопросы -
1. Были ли уже где нибудь решения похожих задач чтоб не изобретать велосипед?
2. Если нет и рыть самому -подскажите следующее - прописано что шить сам себя проц может только функциями, расположенными в секции загрузчика. Но в моему случае необходимо шить и из загрузчика и из основной программы. Так как это две разные собственно прошивки - как я могу обратиться из основной программы к функции записи флеша, скомпилированной для загрузчика? Или как решить такого плана задачу по другому?

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

Чт июл 20, 2017 08:42:31

если шить напрямую нельзя - попробуй другую память (eeprom или ОЗУ, возможно внешнее) или загрузчик учить по ЛАНу работать.

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

Чт июл 20, 2017 10:38:58

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

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

Все встреченные мною интернетовские буты умеют общаться по встроенным в проц протоколам - 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;


Надо попробовать...

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

Чт июл 20, 2017 10:43:00

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

анализировать map-файл всякий раз после пересборки бута не потребуется.

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

Чт июл 20, 2017 11:59:04

Согласен идея хорошая, хотя и бут , в отличие от основной прошивы (надеюсь) менять не придется. Тем более не реально его поменять дистанционно , только программатором на столе. Адреса будут константой после отладки и заливки бута.

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

Чт июл 20, 2017 12:19:13

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

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

Чт июл 20, 2017 13:06:08

Спасибо за подсказку

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

Чт июл 20, 2017 15:48:18

foregit писал(а):Идея состоит в том ,что в основной программе мы получаем прошивку и шьем ее в определенную часть флеша.
Внешнего флеша? Потому что насколько помню, только из загрузчика можно прошивать флеш, а из основной программы не получится.
То что вы хотите поддерживается в МК других производителей, но не в мегах.

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

Чт июл 20, 2017 19:18:34

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

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

Чт июл 20, 2017 21:00:14

Я как то задумывался над проблемой нехватки места в бутлоадере, но времени как то стало крайне мало и я забросил, но была у меня мысля(если я неправ уважаемые знатоки, поправьте ход моих мыслей): контроллер мега шьётся постранично, т.е. я сам решаю какие страницы я хочу переписать и где, в этом вроде ограничений нет кроме одного нельзя прошить ботлодыря поскольку в этот момент он "работает". С другой стороны, если нет команды на обновление прошивки бут перенаправляет контроллер на выполнение основной программы. Смысл заключается в чём: к примеру берём контроллер мега16, допустим основная прошивка будет укладываться с лихой в первые 8 Кбайт а вот размер бута ну не как не укладывается в 1 Кбайт , то почему бы функции бута не разместить после 8 Кбайт основной программы. При старте бута сразу перенаправить на данную функцию, а при прошивке переписывать только те страницы в которых находятся в первых 8Кбайтах? :roll:

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

Чт июл 20, 2017 22:08:42

Ну по логике, как я понимаю, никто не мешает так делать. Если из основной области программы ты не будешь писать самое себя.
И это уже можно называть не бутлодырем, а просто каким нибудь "стартапом", который будет выполнять например какие то функции до основной программы, а не просто работать перепрошивальщиком.
А можно сделать 2 разные прошивки для одного и того же контроллера и переключаться между ними по какому то флагу в том же еепроме.
Полет фантазии никто не ограничивает.

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

Пт июл 21, 2017 20:41:00

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

А подскажите пожалуйста тогда как в авр-студии правильно это проделать?
То есть имея наши функции
uint16_t writeFlashPage(uint16_t waddr, pagebuf_t size),
uint16_t readFlashPage(uint16_t waddr, pagebuf_t size)
- какой конструкцией взять их адрес и записать/забрать в переменную в ОЗУ по определенному адресу?

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

Сб июл 22, 2017 10:07:41

Есть такая директива ORG с помощью которой можно привязать переменные в том числе и функции к определённому месту в памяти
Код:
void func(int par) org 0x200 {
// Function will start at address 0x200
  asm nop;
}

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

Сб июл 22, 2017 19:07:21

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); // вызвали вторую
имя функции - это указатель на ее адрес.

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

Вс июл 23, 2017 09:02:24

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

Делал для LPC2368/2378 на основе NXP-шного примера из аппнота по этой теме - не только езернет, но и примитивный ip с ARP,ICMP,DHCP,UDP уместился в 0x2000 байт. Принимает данные по UDP, шьёт вызовами встроенных IAP функций. При старте проверяет на наличие программы в первом блоке флеша за своим хвостом - и, либо передаёт управление этой программе, либо ждёт команд от внешней загружающей программы. Шьёт от последнего блока к первому - понятно почему. ;)

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

Вт авг 15, 2017 07:24:02

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


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