AVR, как прыгнуть на bootloader из программы?
- Coolish
- Опытный кот
- Сообщения: 785
- Зарегистрирован: Сб фев 27, 2010 21:45:37
- Откуда: Ростов-на-Дону
- Контактная информация:
AVR, как прыгнуть на bootloader из программы?
Здравствуйте.
В своих проектах на ATMEGA8,16,32 я использую bootloader avrprog_boot_v0_85. Он запускается по старту контроллера благодаря фьюзу BOOTRST.
Возник вопрос.
1) Каким образом можно корректно запустить загрузчик из основной программы, чтобы это не привело к переполнениям стека или ещё чего похуже?
2) Есть ли наиболее универсальный способ, какой-либо программный RESET, который перезапустит контроллер и запустит загрузчик, независимо от его размера и размера flash-памяти?
Цель - возможность запуска загрузчика при общении контроллера и компьютера без выполнения аппаратного сброса
Основная программа скомпилирована на CodeVision.
После выполнения загрузчика должна опять запуститься основная программа (естественно, с начала).
В своих проектах на ATMEGA8,16,32 я использую bootloader avrprog_boot_v0_85. Он запускается по старту контроллера благодаря фьюзу BOOTRST.
Возник вопрос.
1) Каким образом можно корректно запустить загрузчик из основной программы, чтобы это не привело к переполнениям стека или ещё чего похуже?
2) Есть ли наиболее универсальный способ, какой-либо программный RESET, который перезапустит контроллер и запустит загрузчик, независимо от его размера и размера flash-памяти?
Цель - возможность запуска загрузчика при общении контроллера и компьютера без выполнения аппаратного сброса
Основная программа скомпилирована на CodeVision.
После выполнения загрузчика должна опять запуститься основная программа (естественно, с начала).
Сделать хотел грозу, а получил КоЗу
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: AVR, как прыгнуть на bootloader из программы?
про программно-аппаратный сброс уже было говорено не один раз: единственный способ настоящего сброса - это установить WDT и зациклиться, пока он не сработает. только после срабатывания WDT не забудьте его отключить, а то снова сработает через 15 мс.
ну и, разумеется, ежели вам хватит и не совсем аппаратного сброса, т.е. достаточно просто перейти на адрес загрузчика - сделайте это простым переходом на конкретный адрес... разве это трудно?
ну и, разумеется, ежели вам хватит и не совсем аппаратного сброса, т.е. достаточно просто перейти на адрес загрузчика - сделайте это простым переходом на конкретный адрес... разве это трудно?
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- alex2103
- Прорезались зубы
- Сообщения: 219
- Зарегистрирован: Вт сен 18, 2007 16:41:16
- Откуда: Украина, г. Запорожье
- Контактная информация:
Re: AVR, как прыгнуть на bootloader из программы?
Я просто по команде от ПК перехожу на адрес загрузчика...
А вот подскажите как можно использовать функции, которые лежать в области загрузчика, из основной программы?
Хочу сделать обновление прошивки по радиоканалу, протокол будет лежать в загрузчике...так почему же эти функции еще и в основной программе дублировать?
Как такое реализовать на CVAVR?
А вот подскажите как можно использовать функции, которые лежать в области загрузчика, из основной программы?
Хочу сделать обновление прошивки по радиоканалу, протокол будет лежать в загрузчике...так почему же эти функции еще и в основной программе дублировать?
Как такое реализовать на CVAVR?
Re: AVR, как прыгнуть на bootloader из программы?
Для этого нужно знать адреса функций. Если эти адреса известны, то вызываете функцию по этим адресам. Например, по адресу 1234h лежит функция, возвращающая char и имеющая один парамерт типа intalex2103 писал(а):А вот подскажите как можно использовать функции, которые лежать в области загрузчика, из основной программы?
Код: Выделить всё
typedef char (* pFunc_t)(int);
pFunc_t Func= (pFunc_t)0x1234;вызывается функция с параметром равным пяти так
Код: Выделить всё
char Ch;
Ch=Func(5);или даже так
Код: Выделить всё
Ch=((pFunc_t)0x1234)(5);Re: AVR, как прыгнуть на bootloader из программы?
а как узнать адрес функции?
в CVAVR и ICCAVR?
в CVAVR и ICCAVR?
Re: AVR, как прыгнуть на bootloader из программы?
Самое простое - посмотреть в map-файлеzebrox писал(а):а как узнать адрес функции?
- alex2103
- Прорезались зубы
- Сообщения: 219
- Зарегистрирован: Вт сен 18, 2007 16:41:16
- Откуда: Украина, г. Запорожье
- Контактная информация:
Re: AVR, как прыгнуть на bootloader из программы?
Все таки как узнать адреса функций в cvavr? Вроде бы все перерыл и нигде не нашел...
Смысла хранить 2 копии одних и тех же функций не вижу... Хотелось бы разобраться с этим вопросом.
Смысла хранить 2 копии одних и тех же функций не вижу... Хотелось бы разобраться с этим вопросом.
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: AVR, как прыгнуть на bootloader из программы?
разобраться с этим вопросом не сложно, если разобраться с тем, как CVAVR работает. лично я про это не знаю. а вот компиляторы традиционного вида, которые с нормальным компоновщиком и т.п. - с теми вполне легко.
во-первых, можно по map-файлу определить адреса функций и поступить, как было сказано ранее.
во-вторых, можно сделать таблицу входов в функции по принципу таблицы векторов - т.е. адрес ее начала и так уже известен, и содержимое так же известно.
в-третьих, можно поступить по принципу 21-го прерывания MS DOS (возможно, есть еще люди, кто в курсе, что это такое). а именно: в функции загрузчика проверять содержимое какого-то регистра или определенной ячейки ОЗУ, в котором будет номер конкретной функции вашего протокола. загрузчик, получив управление, проверяет содержимое этой ячейки и вызывает нужную функцию. ну а из обычной программы вы сначала записываете в эту ячейку номер функции, а потом делаете переход на загрузчик - адрес его начала вам известен. в этом методе есть плюс - не надо беспокоиться о расположении и адресах функций, но есть и минус - надо обеспечить а)гарантию отсутствия мусора в "переключательной" ячейке (например, при получении управления загрузчиком при подаче питания), и б) все "протокольные" функции должны иметь одинаковые параметры (лучше вообще их не иметь - только через глобальные переменные по абсолютным адресам работать) и одинаковый возвращаемый результат (так же лучше void).
в общем, выбирайте сами
во-первых, можно по map-файлу определить адреса функций и поступить, как было сказано ранее.
во-вторых, можно сделать таблицу входов в функции по принципу таблицы векторов - т.е. адрес ее начала и так уже известен, и содержимое так же известно.
в-третьих, можно поступить по принципу 21-го прерывания MS DOS (возможно, есть еще люди, кто в курсе, что это такое). а именно: в функции загрузчика проверять содержимое какого-то регистра или определенной ячейки ОЗУ, в котором будет номер конкретной функции вашего протокола. загрузчик, получив управление, проверяет содержимое этой ячейки и вызывает нужную функцию. ну а из обычной программы вы сначала записываете в эту ячейку номер функции, а потом делаете переход на загрузчик - адрес его начала вам известен. в этом методе есть плюс - не надо беспокоиться о расположении и адресах функций, но есть и минус - надо обеспечить а)гарантию отсутствия мусора в "переключательной" ячейке (например, при получении управления загрузчиком при подаче питания), и б) все "протокольные" функции должны иметь одинаковые параметры (лучше вообще их не иметь - только через глобальные переменные по абсолютным адресам работать) и одинаковый возвращаемый результат (так же лучше void).
в общем, выбирайте сами
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- alex2103
- Прорезались зубы
- Сообщения: 219
- Зарегистрирован: Вт сен 18, 2007 16:41:16
- Откуда: Украина, г. Запорожье
- Контактная информация:
Re: AVR, как прыгнуть на bootloader из программы?
в map-файле есть только переменные...функций нет.
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: AVR, как прыгнуть на bootloader из программы?
alex2103 писал(а):в map-файле есть только переменные...функций нет.
я вам писал:
раз CVAVR не делает нормальный map-файл, этот вариант не подойдет - а остальные два вполнеа вот компиляторы традиционного вида, которые с нормальным компоновщиком и т.п. - с теми вполне легко.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Re: AVR, как прыгнуть на bootloader из программы?
Все-таки мое предпочтение ассемблера языкам высокого уровня при работе с микроконтроллерами нашло вот такое яркое подтверждение : элементарнейший вопрос об адресации, который у "АСМ-щика" даже вообще не возникает, вызывает такую дискуссию, и пока не решен. Совет - посмотрите в Студии полученный код - я даже предлагать не буду : для этого же надо знать коды команд МК, а не высоко парящие PRINTF IF ELSE.
Я с CVAVR не работал, потому не знаю, как он справляется с бутлодырем, потому что тот должен ведь размещаться не где попало, а в определенной области флеши.
Я с CVAVR не работал, потому не знаю, как он справляется с бутлодырем, потому что тот должен ведь размещаться не где попало, а в определенной области флеши.
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: AVR, как прыгнуть на bootloader из программы?
если асм-щик занимается тем, что глядя в дизассемблированный код определяет адреса для переходов, - грош ему цена в базарный день. это не метод. я многократно встречал асм-щиков, которые и таблицу векторов делают через пень-колоду...Jack_A писал(а):элементарнейший вопрос об адресации, который у "АСМ-щика" даже вообще не возникает, вызывает такую дискуссию, и пока не решен. Совет - посмотрите в Студии полученный код - я даже предлагать не буду
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Re: AVR, как прыгнуть на bootloader из программы?
alex2103 писал(а):Все таки как узнать адреса функций в cvavr? Вроде бы все перерыл и нигде не нашел...![]()
...
Имя функции - и есть её адрес.
Для чего этот адрес нужен? Что делать с ним дальше хотите?
Пример:
Код: Выделить всё
void fun( void )
{
//...
}
void main( void )
{
//указатель на функцию
void( * fun_pointer )( void ) = fun;
//так к функции можно обратиться через указатель
fun_pointer();
//а это адрес функции до 64 кБ
unsigned int fun_adr = ( unsigned int )fun * 2;
//и чё с ним делать???
...
}
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: AVR, как прыгнуть на bootloader из программы?
вы не внимательно прочли тему: внутри своей программы адреса всех функций известны, как вы справедливо изволили заметить, но bootloader - это отдельно разработанная программа, прошитая по фиксированному адресу, и основная об этой программе не знает ничего, кроме адреса начала boot-секции. в этом и есть проблема: дать одной программе сведения о функциях другой, чтобы они стали взаимодействоать.asteroid7 писал(а):Имя функции - и есть её адрес.
Для чего этот адрес нужен? Что делать с ним дальше хотите?
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Re: AVR, как прыгнуть на bootloader из программы?
asteroid7 писал(а):Имя функции - и есть её адрес.
Только внутри одной программы. А бутлоадер с основной прошивкой хоть и записываются в один контроллер, но компилятся отдельно.
asteroid7 писал(а):Для чего этот адрес нужен? Что делать с ним дальше хотите?
Вызвать функцию по этому адресу.
Вообще самый правильный способ - в прошивке бутлоадера по фиксированному адресу(например последних 64 байтах) создаётся структура в которой указывается сигнатура, чтобы знать что структура никуда не делась, и указатели на функции. Если интерфейс планируется менять между версиями, то можно использовать пару ID-указатель и искать по ID, а не по смещению, чтобы была совместимость новых прошивок со старыми бутлоадерами.
То есть в общем для бутлоадера и основной программы h-файле задаётся структура:
Код: Выделить всё
typedef int *func1_t(int param1);
typedef void *func2_t();
#define BOOTLOADERFUCTADDR 0x1FC0
#define BOOTLOADERFUCTSIGN 0x12345678
typedef struct {
unsigned long sign;
func1_t func1;
func2_t func2;
} BootloaderFunctionsStruct;
В бутлоадере задаётся сама структура:
Код: Выделить всё
int func1(int param1)
{
}
void func2()
{
}
__attribute__((__progmem__)) __attribute__((section (".functbl")) BootloaderFunctionsStruct bootfuncs = { //с атрибутами возможно ошибся - нужно смотреть документацию и эксперементировать
BOOTLOADERFUCTSIGN,
func1,
func2
}
А в настройках задаём новую секцию .functbl, начинающуюся с адреса 0x1FC0.
И в основной программе просто задаём переменную, которая ссылается на этот адрес:
Код: Выделить всё
BootloaderFunctionsStruct *bootfuncs = (BootloaderFunctionsStruct *)BOOTLOADERFUCTADDR;
void somefunc()
{
****
if (bootfuncs->sign!=BOOTLOADERFUCTSIGN) сообщаем об ошибке и выходим;
a = bootfuncs->func1(123);
}
Этот код я привёл для WinAVR, но на других компиляторах это тоже будет работать. Только атрибуты структуры в бутлоадере придётся указывать другие.
Последний раз редактировалось Murav Ср июл 21, 2010 22:41:01, всего редактировалось 1 раз.
Re: AVR, как прыгнуть на bootloader из программы?
Вообще задавать адреса на основе данных map-файла нежелательно - при любой перекомпиляции они сползут и их придётся задавать заново.
Re: AVR, как прыгнуть на bootloader из программы?
ARV писал(а):если асм-щик занимается тем, что глядя в дизассемблированный код определяет адреса для переходов, - грош ему цена в базарный день. это не метод. я многократно встречал асм-щиков, которые и таблицу векторов делают через пень-колоду...
Ну, если он умеет только это - то может быть. А криво сделать таблицу векторов - это надо очень постараться, скопипастить из даташита кусок кода - это могут даже лошади.
Впрочем, во времена моей AVR-ной молодости изредка случалось
Кстати для Murav: если пис`ать на АСМе, то никто никуда не слезает : есть такая директива .org - и код будет стоять в нужном месте, как вкопанный.
Re: AVR, как прыгнуть на bootloader из программы?
Jack_A писал(а):Кстати для Murav: если пис`ать на АСМе, то никто никуда не слезает : есть такая директива .org - и код будет стоять в нужном месте, как вкопанный.
Здесь предлагалось найти адрес функции в map-файле, а не задавать его .org . Вариант с .org для функций аналогичен варианту с таблицей адресов, только таблица адресов удобнее: адрес у неё один(а не по одному для функции), размер маленький, так что её можно запихнуть в конец памяти, где она мешатся не будет, не будет возникать дырок между экспортируемыми функциями и т.д.
Re: AVR, как прыгнуть на bootloader из программы?
Перечитал. Увы, так и не нашёл, про раздельную компиляцию, что это линковщику/сборщику нужен неизвестный внешний/extern адрес функции.ARV писал(а):вы не внимательно прочли тему:
ARV писал(а):... но bootloader - это отдельно разработанная программа, прошитая по фиксированному адресу, ...
Не обязательно. Можно одним целым компилить. Что бутлоадеру необходимо то в отдельную boot-секцию.Murav писал(а):...
А бутлоадер с основной прошивкой хоть и записываются в один контроллер, но компилятся отдельно. ...
И всё равно, проблема мне не понятна. Даже, если раздельно компилить, то что мешает сделать точку входа совпадающую с адресом начала boot-секции?
Для перехода удобнее использовать fuse бит - стартовать с boot-секции при ресете.
Как ни крути, при любом решении адрес "бутлоадера" указывается и известен явно, даже при клонировании векторов прерываний.
Или я опять чего то не догоняю ) или здесь имеет место быть попытка компиляции без функции main()...
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: AVR, как прыгнуть на bootloader из программы?
я об этом и говорилasteroid7 писал(а): Даже, если раздельно компилить, то что мешает сделать точку входа совпадающую с адресом начала boot-секции?
вывод о том, что загрузчик и основная программа друг о друге не знают, я сделал из такого простого факта: предположим, мы собрали программу вместе с загрузчиком - это, так сказать, исходная версия прошивки. все пучком, адреса всех функций известны и нет проблем. но потом мы скармливаем загрузчику обновление - оно ведь уже не содержит самого кода загрузчика, он ведь не перезаписывается! и в этом случае приходится исходить из принципа, что в коде обновления об адресах функций загрузчика компилятору ничего не известно...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!