Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Вызов функций из bootloader
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
sevstels
В приложении необходимо переписывать таблицы констант расположенные в FLASH. Для этого требуется вызывать подпрограмму расположенную в boot-секторе. Но не всё так просто как кажется! Boot-sector полностью занял bootloader и при загрузке или обновлении приложения через бут, этот кусочек кода bootloader ом отбрасывается, тк секция защищена от записи сама в себя. И получается невозможным реализовать запись приложения во FLASH тк отсутствует нужная подпрограмма.

Остаётся попробовать пользоваться функциями записи самого bootloader. Попробовал, не работает.
Как делал:

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. Пытаюсь записать страницу памяти.

Затем всё зависает. Вероятно не происходит возврата из вызванной функции.
Посмотреть отладчиком что происходит не получается.

Вопрос такой. Если boot-сектор залочен от чтения и записи, выполняются ли из него вызовы из приложения?
Что делаю не так?
Непомнящий Евгений
Цитата(sevstels @ Feb 16 2017, 08:20) *
Вопрос такой. Если boot-сектор залочен от чтения и записи, выполняются ли из него вызовы из приложения?
Что делаю не так?


Memory programming / Lock bits
Код
1 1 1 No restrictions for SPM or (E)LPM accessing the Boot
Loader section.
2 1 0 SPM is not allowed to write to the Boot Loader section.
3 0 0
SPM is not allowed to write to the Boot Loader section,
and (E)LPM executing from the Application section is not
allowed to read from the Boot Loader section. If interrupt
vectors are placed in the Application section, interrupts
are disabled while executing from the Boot Loader section.
4 0 1
(E)LPM executing from the Application section is not
allowed to read from the Boot Loader section. If interrupt
vectors are placed in the Application section, interrupts
are disabled while executing from the Boot Loader section.
Memory Lock Bits Protection Type


Можно предложить обходной путь - выделяется область памяти в ОЗУ под команду загрузчику. Туда пишется команда, ее аргументы и crc, затем процессор перезагружается (скажем по вотчдогу). Загрузчик при старте проверяет, есть ли в этой области команда и выполняет ее
sevstels
>> выделяется область памяти в ОЗУ под команду загрузчику
Перезагружаться нельзя, тк будет разорвана связь с PC и процесс обновления "упадёт". А сам же фирменный Atmel CAN bootloader к сожалению крив до безобразия, тк писать страницы выше 64к он не способен ввиду того, что ему забыли прикрутить long адресацию. Через CAN протокол поддерживается передача только 2х байтного адреса и попытка это исправить вызывает переполнение boot section и загручик не влазит в память. Как ни крути - а переписать FLASH константы самим бутом - не получится. Только из приложения.
Непомнящий Евгений
Цитата(sevstels @ Feb 16 2017, 09:21) *
>> выделяется область памяти в ОЗУ под команду загрузчику
Перезагружаться нельзя, тк будет разорвана связь с PC и процесс обновления "упадёт". А сам же фирменный Atmel CAN bootloader к сожалению крив до безобразия, тк писать страницы выше 64к он не способен ввиду того, что ему забыли прикрутить long адресацию. Как ни крути - а переписать FLASH константы самим бутом - не получится. Только из приложения.


тогда выберите другой режим защиты, который разрешает обращаться к загрузчику из приложения
sevstels
Попробовал снять все биты защиты.
Результат аналогичен - зависает.

Смущает предупреждение компилятора: Warning[Pe1053]: conversion from integer to smaller pointer
Похоже указатель void 2х байтный, а надо 3х байтный те __farflash.
Но IAR указатель __farflash отказывается принять... как правильно написать не соображу.
aiwa
Цитата(sevstels @ Feb 16 2017, 07:20) *
2. Создаю в основной программе указатель:
void (*flash_page_write)(unsigned short) = (void (*)(unsigned short))0x1F72E;


Проверьте адресацию в map-файле. Вполне вероятно, что она байтовая и тогда Вы вызываете функцию по случайному адресу вместо (0x1F72E>>1);


Цитата(sevstels @ Feb 16 2017, 08:35) *
Но IAR указатель __farflash отказывается принять... как правильно написать не соображу.

__far
sevstels
__far не принимается (размер памяти программ 128к, AT90CAN128)
Error[Pa043]: the keyword "__far" is not available with the current settings

Вот такой вариант собирается но не работает:
void (__nearfunc *flash_page_write)(unsigned short) = ( void (__nearfunc *)(unsigned short))0x1F72E;
Трудность всё та-же: Warning[Pe1053]: conversion from integer to smaller pointer
Посмотрел вызов в дизассемблере отладчика. Он 2х байтный, всместо 0x1F72E адрес 0xF72E;

Непомнящий Евгений
Цитата(sevstels @ Feb 16 2017, 11:03) *
Посмотрел вызов в дизассемблере отладчика. Он 2х байтный, всместо 0x1F72E адрес 0xF72E;


Так может надо записать в указатель 0x1F72E / 2 ? Давно не имел дела с потрохами avr, уже не помню точно...
aiwa
Вам нужно такой оператор.
void (*flash_page_write)(unsigned short) = (void (*)(unsigned short))0xFB97; // (0x1F72E>>1);

Флеш адресуется пословно, но в мепе указан побайтовый, который в 2-раза больший.
sevstels
>> в мепе указан побайтовый
Таки Бинго, работает!

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;
aiwa спасибо Вам за подсказку.
pavel-pervomaysk
Любая подпрограмма из закрытой области BOOT вызывается без проблем, так и наоборот из обрасти BOOT можно выполнить любую операцию (если она не завязана на прерывания и перенастройку периферии). Векторы прерываний надо переключать, после перехода из BOOT -> MAIN и наоборот.
Это ведь для нас код как бы скрыт, для проца данные всегда в читабельном виде. Просто встроенный в процессор загрузчик в зависимости от состояния локбитов выдает нам одно либо другое.

Немного из моей практики.
К примеру есть у Вас протокол, по которому Вы обновляете ПО, это будет UART, CAN, или свой какой-то 1-wire, о котором никто никогда и не догадается.
Для обновления прошивки не обязательно дергать ресетами, зажимать кнопки, итд.
В MAIN пишем обработчик "секретной" посылки, (он же обязан быть и в секции BOOT)!
Перешли в бут и работаем с бутом.
Аналогично схожей командой и вышли от туда.

Кстати, сам не пользуюсь загрузчиками от ATMEL, пишу свои.
Стояла задача работать с областями Flash, EEprom, External i2c.
Лень было каждую 24схх в программаторе писать.
Д_М
А как будет выглядеть вызов функции с параметрами?
void MyFunc(unsigned int MyPar)
{
}
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2024 Invision Power Services, Inc.