Страница 1 из 1
Запуск bootloader-а из программы
Добавлено: Чт мар 05, 2020 14:32:12
LEVV2006
Всем привет!
Хочу запускать bootloader на МК по команде с ПК. Это требуется для перепрошивки устройства.
Программа для МК написана, также имеется и bootloader, но не удается его загрузить из программы.
Код в упрощенном виде:
Код: Выделить всё
void (*funcptr)( void ) = 0x1800;
int main(void)
{
funcptr();
}
Проблема в том что я никак не пойму что происходит. Если адрес указать 0х0000 то МК перезагружается (Это правильно и нормально).
А если указать адрес bootloader то вообще ничего не происходит.... Возможно МК даже зависает..... НО если нажать ресет то bootloader загружается....
Я вот думаю.... Скорее всего нужно не только указывать на адрес, но и сбрасывать ещё какие не будь регистры (как при ресете)... Веть bootloader имеется уже свою функцию main и следовательно все должно инициализироваться по новой.
МК: Atmega16u2
Фьюзы:
0xFF LOW
0xD8 HIGH
0xF8 EXTENDED
Адрес загрузчика 0x1800
Re: Запуск bootloader-а из программы
Добавлено: Чт мар 05, 2020 17:29:51
NStorm
Посмотрите как в optiboot это реализовано:
https://github.com/Optiboot/optiboot/bl ... _reset.ino
В самом конце:
Код: Выделить всё
typedef void (*do_reboot_t)(void);
const do_reboot_t do_reboot = (do_reboot_t)((FLASHEND - 511) >> 1);
И в самом буте вот что делается и прокомментировано:
Код: Выделить всё
// After the zero init loop, this is the first code to run.
//
// This code makes the following assumptions:
// No interrupts will execute
// SP points to RAMEND
// r1 contains zero
//
// If not, uncomment the following instructions:
// cli();
asm volatile ("clr __zero_reg__");
Re: Запуск bootloader-а из программы
Добавлено: Пн мар 09, 2020 09:35:23
LEVV2006
Что то я уже по разному попробовал.
Вообще не работает.....
Re: Запуск bootloader-а из программы
Добавлено: Пн мар 09, 2020 13:06:21
BOB51
Бутлоадеры существуют для того, чтобы запускаться до начала исполнения программы пользователя.
Да еще и защищаются от случайного самозапуска.
Другое дело, если должен использоваться общий фрагмент загрузчика что в теле бутлоадера, что в прикладной программе - это на случай "горячей перезагрузки" части программного кода.
Однако... на тот случай потребуется и предустановка текущего содержимого критичных РСФ с последующей сменой содержимого таблицы векторов прерываний (или сменой ее расположения) и передачей управления на стартовый адрес бутлоадера.
Есть у меня проектик... но на ассемблере и для MCS51 (там внешнее ОЗУ в качестве памяти программ - вотличии от АВРкового ПЗУ запись содержимого не требует ожидания окончания).

Re: Запуск bootloader-а из программы
Добавлено: Пн мар 09, 2020 18:08:51
LEVV2006
В принципе..... я тут поизголялся и нашел куда воткнуть кнопку ресет.
При нажатии на ресет МК сбрасывается и загружается бутлоадер.
Ладное. Если что то все же придумаю с программной точки зрения то напишу сюда.
Всем спасибо!
Re: Запуск bootloader-а из программы
Добавлено: Пн мар 09, 2020 18:24:27
ARV
на сколько я понимаю, у вас бутлоадер не вызывается потому, что вы адрес точки входа указали в явном виде В БАЙТАХ, в то время как ядро AVR оперирует адресами памяти программ СЛОВАМИ.
Re: Запуск bootloader-а из программы
Добавлено: Пн мар 09, 2020 20:52:43
technik-1017
В одном из проектов для mega168 я сделал так (сам проект на Си (IAR), загрузчик на ассемблере, но это не принципиально)
asm("jmp $3F14"); // переход на boot-загрузчик
Адрес начала области загрузчика по datasheet 0x1F80 (умножаем на 2 получаем 3F00)
Смещение ещё на 0x14 это вырезается условие перехода на загрузчик или основной код программы (main()) по джамперу. Данное смещение зависит от вашей реализации загрузчика (необходимый адрес смещения можно посмотреть в hex загрузчика).
кусок из загрузчика
Код: Выделить всё
.CSEG
.org 0x0000
main:
jmp main
.org BEGIN_ADR_BOOT
boot:
;===== Точка входа при установленном BOOTRST =================
;===== инициализация портов ввода/вывода =====================
ldi temp,(1<<KEY) ; включаем подтягивающий резистор
out PORTD,temp ; -//-
nop
nop
nop
nop
nop
;===== условие входа в режим программирования ================
sbis PIND,KEY ; если кнопка нажата, то переход на выполнения программы загрузчика
jmp main ; иначе переход на выполнение основной программы по адресу 0x0000
;===== Точка входа из области программы ====
cli
так вот команда cli и находится по адресу 0x3F14
Re: Запуск bootloader-а из программы
Добавлено: Пн мар 09, 2020 22:12:23
NStorm
[uquote="LEVV2006",url="/forum/viewtopic.php?p=3804159#p3804159"]Что то я уже по разному попробовал.
Вообще не работает.....[/uquote]
Всё работает, если правильно сделать. Адрес правильно указать. Правда вам уже написали тут. Я ж не спроста тот кусок кода привел, где свдиг вправо адреса есть.
Re: Запуск bootloader-а из программы
Добавлено: Пн мар 09, 2020 22:44:38
LEVV2006
[uquote="NStorm",url="/forum/viewtopic.php?p=3804515#p3804515"][uquote="LEVV2006",url="/forum/viewtopic.php?p=3804159#p3804159"]Что то я уже по разному попробовал.
Вообще не работает.....[/uquote]
Всё работает, если правильно сделать. Адрес правильно указать.[/uquote]
Я согласен с вами СО ВСЕМИ полностью! Сейчас смотрю ассемблерный код и пытаюсь найти этот адрес....
Re: Запуск bootloader-а из программы
Добавлено: Вт мар 10, 2020 20:02:41
LEVV2006
В общем в коде бутлоадера так накручено и наверчено..... что пока победить его не удалось.
Бутлоадер я не сам писал так что разобрался с трудом

Пристально рассмотрев дизассемблер обнаружил вот что:
ПО порядку.
1)Фьюз выставлен так что при ресете загружается бутлоадер
2) В коде бутлоадера есть функция которая определяет: грузить бутлоадер или сразу перейти к загрузке основной программы.
Именно этот код отвечает за то, что при подаче питания загружается программа, а при нажатии ресет грузится бутлоадер
3) Эта функция не вызывается из МЕЙН! и в дизассемблере стоит перед входом в функцию мейн! (Как так сделали не знаю...).
Я пробовал по разному переписать функцию проверки, но бутлоадер так и не хочет грузится.
Пробовал в основной программе ставить флаг MCUSR |= (1 << EXTRF); (Говорящий о том что был якобы сброс.)
А потом вызывал бутлоадер ((void (*)(void))0x3000)();
НО пока без результатно.....
Ладно буду думать..... Хитро сделано

Re: Запуск bootloader-а из программы
Добавлено: Вт мар 10, 2020 20:10:31
NStorm
2) В коде бутлоадера есть функция которая определяет: грузить бутлоадер или сразу перейти к загрузке основной программы.
Именно этот код отвечает за то, что при подаче питания загружается программа, а при нажатии ресет грузится бутлоадер
3) Эта функция не вызывается из МЕЙН! и в дизассемблере стоит перед входом в функцию мейн! (Как так сделали не знаю...).
Почти также сделано в optiboot, ссылку на который я вам давал. Бутлоадер в любом случае надо собирать с отдельными секциями для линковщика, чтобы поместить его в конец прошивки. Также как правило применяются флаги, чтобы не использовать стандартную процедуру инита через -nostartfiles. Короче всё это есть в коде optiboot:
Код: Выделить всё
void pre_main(void) __attribute__ ((naked)) __attribute__ ((section (".init8")));
int main(void) __attribute__ ((OS_main)) __attribute__ ((section (".init9"))) __attribute__((used));
pre_main() идет до секции main(). Секции .initN предопределены в avr-gcc:
https://www.microchip.com/webdoc/AVRLib ... _init.html
Только там в main проверка выглядит так:
Код: Выделить всё
...
ch = MCUSR;
#endif
// Skip all logic and run bootloader if MCUSR is cleared (application request)
if (ch != 0) {
...
Т.е. если MCUSR пуст - значит из основного кода мы пришли, где его уже очистили.
Re: Запуск bootloader-а из программы
Добавлено: Вт мар 10, 2020 20:21:04
ARV
LEVV2006 писал(а):вызывал бутлоадер ((void (*)(void))0x3000)();
я вот одного не могу понять: то у вас вход в бутлоадер был по адресу
0х1800, теперь вы по адресу
0х3000 пытаетесь что-то вызвать... а вот тот момент, о котором вам я и
NStorm говорили - пословная адресация памяти программ, - я так и не увидел. и это не смотря на явное указание на правильный подход:
NStorm писал(а):Я ж не спроста тот кусок кода привел, где свдиг вправо адреса есть.
сдвиг вправо - это деление на 2, т.е. переход от адреса БАЙТА к адресу СЛОВА, в котором два байта
Re: Запуск bootloader-а из программы
Добавлено: Ср мар 11, 2020 15:28:46
LEVV2006
Давайте я выложу частично код программы. Чтобы понятней было...
Код бутлоадера (Бутлоадер от lufa так как чип Atmega16u2 c USB на борту).
Спойлер
Код: Выделить всё
/** Special startup routine to check if the bootloader was started via a watchdog reset, and if the magic application
* start key has been loaded into \ref MagicBootKey. If the bootloader started via the watchdog and the key is valid,
* this will force the user application to start via a software jump.
*/
void Application_Jump_Check(void)
{
bool JumpToApplication = false;
/* Check if the device's BOOTRST fuse is set */
if (boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS) & FUSE_BOOTRST)
{
/* If the reset source was not an external reset or the key is correct, clear it and jump to the application */
if (!(MCUSR & (1 << EXTRF)) || (MagicBootKey == MAGIC_BOOT_KEY))
JumpToApplication = true;
/* Clear reset source */
MCUSR &= ~(1 << EXTRF);
}
else
{
/* If the reset source was the bootloader and the key is correct, clear it and jump to the application;
* this can happen in the HWBE fuse is set, and the HBE pin is low during the watchdog reset */
if ((MCUSR & (1 << WDRF)) && (MagicBootKey == MAGIC_BOOT_KEY))
JumpToApplication = true;
/* Clear reset source */
MCUSR &= ~(1 << WDRF);
}
/* Don't run the user application if the reset vector is blank (no app loaded) */
bool ApplicationValid = (pgm_read_word_near(0) != 0xFFFF);
/* If a request has been made to jump to the user application, honor it */ //
if (JumpToApplication && ApplicationValid)
{
/* Turn off the watchdog */
MCUSR &= ~(1 << WDRF);
wdt_disable();
/* Clear the boot key and jump to the user application */
MagicBootKey = 0;
// cppcheck-suppress constStatement
((void (*)(void))0x0000)();
}
}
/** Main program entry point. This routine configures the hardware required by the bootloader, then continuously
* runs the bootloader processing routine until instructed to soft-exit, or hard-reset via the watchdog to start
* the loaded application code.
*/
int main(void)
{
/* Setup hardware required for the bootloader */
SetupHardware();
..........
Дизассемблер
Спойлер
Код: Выделить всё
Disassembly of section .text:
00003000 <__vectors>:
3000: 39 c0 rjmp .+114 ; 0x3074 <__ctors_end>
3002: 00 00 nop
3004: 9b c0 rjmp .+310 ; 0x313c <__bad_interrupt>
3006: 00 00 nop
3008: 99 c0 rjmp .+306 ; 0x313c <__bad_interrupt>
300a: 00 00 nop
300c: 97 c0 rjmp .+302 ; 0x313c <__bad_interrupt>
300e: 00 00 nop
3010: 95 c0 rjmp .+298 ; 0x313c <__bad_interrupt>
3012: 00 00 nop
3014: 93 c0 rjmp .+294 ; 0x313c <__bad_interrupt>
3016: 00 00 nop
3018: 91 c0 rjmp .+290 ; 0x313c <__bad_interrupt>
301a: 00 00 nop
301c: 8f c0 rjmp .+286 ; 0x313c <__bad_interrupt>
301e: 00 00 nop
3020: 8d c0 rjmp .+282 ; 0x313c <__bad_interrupt>
3022: 00 00 nop
3024: 8b c0 rjmp .+278 ; 0x313c <__bad_interrupt>
3026: 00 00 nop
3028: 89 c0 rjmp .+274 ; 0x313c <__bad_interrupt>
302a: 00 00 nop
302c: ec c4 rjmp .+2520 ; 0x3a06 <__vector_11>
302e: 00 00 nop
3030: 85 c0 rjmp .+266 ; 0x313c <__bad_interrupt>
3032: 00 00 nop
3034: 83 c0 rjmp .+262 ; 0x313c <__bad_interrupt>
3036: 00 00 nop
3038: 81 c0 rjmp .+258 ; 0x313c <__bad_interrupt>
303a: 00 00 nop
303c: 7f c0 rjmp .+254 ; 0x313c <__bad_interrupt>
303e: 00 00 nop
3040: 7d c0 rjmp .+250 ; 0x313c <__bad_interrupt>
3042: 00 00 nop
3044: 7b c0 rjmp .+246 ; 0x313c <__bad_interrupt>
3046: 00 00 nop
3048: 79 c0 rjmp .+242 ; 0x313c <__bad_interrupt>
304a: 00 00 nop
304c: 77 c0 rjmp .+238 ; 0x313c <__bad_interrupt>
304e: 00 00 nop
3050: 75 c0 rjmp .+234 ; 0x313c <__bad_interrupt>
3052: 00 00 nop
3054: 73 c0 rjmp .+230 ; 0x313c <__bad_interrupt>
3056: 00 00 nop
3058: 71 c0 rjmp .+226 ; 0x313c <__bad_interrupt>
305a: 00 00 nop
305c: 6f c0 rjmp .+222 ; 0x313c <__bad_interrupt>
305e: 00 00 nop
3060: 6d c0 rjmp .+218 ; 0x313c <__bad_interrupt>
3062: 00 00 nop
3064: 6b c0 rjmp .+214 ; 0x313c <__bad_interrupt>
3066: 00 00 nop
3068: 69 c0 rjmp .+210 ; 0x313c <__bad_interrupt>
306a: 00 00 nop
306c: 67 c0 rjmp .+206 ; 0x313c <__bad_interrupt>
306e: 00 00 nop
3070: 65 c0 rjmp .+202 ; 0x313c <__bad_interrupt>
...
00003074 <__ctors_end>:
3074: 11 24 eor r1, r1
3076: 1f be out 0x3f, r1 ; 63
3078: cf ef ldi r28, 0xFF ; 255
307a: d2 e0 ldi r29, 0x02 ; 2
307c: de bf out 0x3e, r29 ; 62
307e: cd bf out 0x3d, r28 ; 61
00003080 <Application_Jump_Check>:
/* Re-enable JTAG debugging */
JTAG_ENABLE();
#else
/* Check if the device's BOOTRST fuse is set */
if (boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS) & FUSE_BOOTRST)
3080: e3 e0 ldi r30, 0x03 ; 3
3082: f0 e0 ldi r31, 0x00 ; 0
3084: 89 e0 ldi r24, 0x09 ; 9
3086: 80 93 57 00 sts 0x0057, r24 ; 0x800057 <__EEPROM_REGION_LENGTH__+0x7f0057>
308a: 84 91 lpm r24, Z
308c: 8e 7f andi r24, 0xFE ; 254
308e: 91 f0 breq .+36 ; 0x30b4 <Application_Jump_Check+0x34>
{
/* If the reset source was not an external reset or the key is correct, clear it and jump to the application */
if (!(MCUSR & (1 << EXTRF)) || (MagicBootKey == MAGIC_BOOT_KEY))
3090: 04 b6 in r0, 0x34 ; 52
3092: 01 fe sbrs r0, 1
3094: 0a c0 rjmp .+20 ; 0x30aa <Application_Jump_Check+0x2a>
3096: 81 e0 ldi r24, 0x01 ; 1
3098: 20 91 94 01 lds r18, 0x0194 ; 0x800194 <__bss_end>
309c: 30 91 95 01 lds r19, 0x0195 ; 0x800195 <__bss_end+0x1>
30a0: 22 34 cpi r18, 0x42 ; 66
30a2: 3c 4d sbci r19, 0xDC ; 220
30a4: 19 f0 breq .+6 ; 0x30ac <Application_Jump_Check+0x2c>
30a6: 80 e0 ldi r24, 0x00 ; 0
30a8: 01 c0 rjmp .+2 ; 0x30ac <Application_Jump_Check+0x2c>
JumpToApplication = true;
30aa: 81 e0 ldi r24, 0x01 ; 1
/* Clear reset source */
MCUSR &= ~(1 << EXTRF);
30ac: 94 b7 in r25, 0x34 ; 52
30ae: 9d 7f andi r25, 0xFD ; 253
30b0: 94 bf out 0x34, r25 ; 52
30b2: 11 c0 rjmp .+34 ; 0x30d6 <Application_Jump_Check+0x56>
}
else
{
/* If the reset source was the bootloader and the key is correct, clear it and jump to the application;
* this can happen in the HWBE fuse is set, and the HBE pin is low during the watchdog reset */
if ((MCUSR & (1 << WDRF)) && (MagicBootKey == MAGIC_BOOT_KEY))
30b4: 04 b6 in r0, 0x34 ; 52
30b6: 03 fe sbrs r0, 3
30b8: 0a c0 rjmp .+20 ; 0x30ce <Application_Jump_Check+0x4e>
30ba: 81 e0 ldi r24, 0x01 ; 1
30bc: 20 91 94 01 lds r18, 0x0194 ; 0x800194 <__bss_end>
30c0: 30 91 95 01 lds r19, 0x0195 ; 0x800195 <__bss_end+0x1>
30c4: 22 34 cpi r18, 0x42 ; 66
30c6: 3c 4d sbci r19, 0xDC ; 220
30c8: 19 f0 breq .+6 ; 0x30d0 <Application_Jump_Check+0x50>
30ca: 80 e0 ldi r24, 0x00 ; 0
30cc: 01 c0 rjmp .+2 ; 0x30d0 <Application_Jump_Check+0x50>
* start key has been loaded into \ref MagicBootKey. If the bootloader started via the watchdog and the key is valid,
* this will force the user application to start via a software jump.
*/
void Application_Jump_Check(void)
{
bool JumpToApplication = false;
30ce: 80 e0 ldi r24, 0x00 ; 0
* this can happen in the HWBE fuse is set, and the HBE pin is low during the watchdog reset */
if ((MCUSR & (1 << WDRF)) && (MagicBootKey == MAGIC_BOOT_KEY))
JumpToApplication = true;
/* Clear reset source */
MCUSR &= ~(1 << WDRF);
30d0: 94 b7 in r25, 0x34 ; 52
30d2: 97 7f andi r25, 0xF7 ; 247
30d4: 94 bf out 0x34, r25 ; 52
}
#endif
/* Don't run the user application if the reset vector is blank (no app loaded) */
bool ApplicationValid = (pgm_read_word_near(0) != 0xFFFF);
30d6: 20 e0 ldi r18, 0x00 ; 0
30d8: 30 e0 ldi r19, 0x00 ; 0
30da: f9 01 movw r30, r18
30dc: 45 91 lpm r20, Z+
30de: 54 91 lpm r21, Z
/* If a request has been made to jump to the user application, honor it */ //
if (JumpToApplication && ApplicationValid)
30e0: 88 23 and r24, r24
30e2: b9 f0 breq .+46 ; 0x3112 <__do_copy_data>
30e4: 4f 3f cpi r20, 0xFF ; 255
30e6: 5f 4f sbci r21, 0xFF ; 255
30e8: a1 f0 breq .+40 ; 0x3112 <__do_copy_data>
{
/* Turn off the watchdog */
MCUSR &= ~(1 << WDRF);
30ea: 84 b7 in r24, 0x34 ; 52
30ec: 87 7f andi r24, 0xF7 ; 247
30ee: 84 bf out 0x34, r24 ; 52
);
}
else
{
uint8_t register temp_reg;
__asm__ __volatile__ (
30f0: 0f b6 in r0, 0x3f ; 63
30f2: f8 94 cli
30f4: a8 95 wdr
30f6: 80 91 60 00 lds r24, 0x0060 ; 0x800060 <__DATA_REGION_ORIGIN__>
30fa: 88 61 ori r24, 0x18 ; 24
30fc: 80 93 60 00 sts 0x0060, r24 ; 0x800060 <__DATA_REGION_ORIGIN__>
3100: 10 92 60 00 sts 0x0060, r1 ; 0x800060 <__DATA_REGION_ORIGIN__>
3104: 0f be out 0x3f, r0 ; 63
wdt_disable();
/* Clear the boot key and jump to the user application */
MagicBootKey = 0;
3106: 10 92 95 01 sts 0x0195, r1 ; 0x800195 <__bss_end+0x1>
310a: 10 92 94 01 sts 0x0194, r1 ; 0x800194 <__bss_end>
// cppcheck-suppress constStatement
((void (*)(void))0x0000)();
310e: f9 01 movw r30, r18
3110: 09 95 icall
00003112 <__do_copy_data>:
3112: 11 e0 ldi r17, 0x01 ; 1
3114: a0 e0 ldi r26, 0x00 ; 0
3116: b1 e0 ldi r27, 0x01 ; 1
3118: ea eb ldi r30, 0xBA ; 186
311a: fd e3 ldi r31, 0x3D ; 61
311c: 02 c0 rjmp .+4 ; 0x3122 <__do_copy_data+0x10>
311e: 05 90 lpm r0, Z+
3120: 0d 92 st X+, r0
3122: a6 38 cpi r26, 0x86 ; 134
3124: b1 07 cpc r27, r17
3126: d9 f7 brne .-10 ; 0x311e <__do_copy_data+0xc>
00003128 <__do_clear_bss>:
3128: 21 e0 ldi r18, 0x01 ; 1
312a: a6 e8 ldi r26, 0x86 ; 134
312c: b1 e0 ldi r27, 0x01 ; 1
312e: 01 c0 rjmp .+2 ; 0x3132 <.do_clear_bss_start>
00003130 <.do_clear_bss_loop>:
3130: 1d 92 st X+, r1
00003132 <.do_clear_bss_start>:
3132: a4 39 cpi r26, 0x94 ; 148
3134: b2 07 cpc r27, r18
3136: e1 f7 brne .-8 ; 0x3130 <.do_clear_bss_loop>
3138: 82 d0 rcall .+260 ; 0x323e <main>
313a: 3d c6 rjmp .+3194 ; 0x3db6 <_exit>
0000313c <__bad_interrupt>:
313c: 61 cf rjmp .-318 ; 0x3000 <__vectors>
И дальше там ещё полно кода....
Re: Запуск bootloader-а из программы
Добавлено: Ср мар 11, 2020 15:33:52
ARV
и чо?
Re: Запуск bootloader-а из программы
Добавлено: Ср мар 11, 2020 15:54:57
NStorm
LEVV2006, у вас в функции проверка Application_Jump_Check() которая даст далее буту запуститься только, если попали сюда по внешнему сбросу. Вам надо определить адрес функции main() вашего бутлоадера и прыгать к ней. Не пустая адреса в байтах и словах.
Добавлено after 7 minutes 46 seconds:
EDIT: Т.к. это USB бутлоадер на LUFA, который будет использовать прерывания, всё несколько сложнее. Надо еще позаботиться о векторах прерываний через IVSEL.
Вот один из вариантов, как чел сделал:
https://www.avrfreaks.net/forum/jumping ... r-software (ближе к концу есть пример кода).
Re: Запуск bootloader-а из программы
Добавлено: Ср мар 11, 2020 16:32:10
LEVV2006
Посмотрел код из того примера.
Спойлер
Код: Выделить всё
void Boot_StartBootloader(void);
void Boot_BootloaderCheck(void) ATTR_INIT_SECTION(3);
/* Magic key for activating bootloader */
volatile uint32_t Boot_MagicKey ATTR_NO_INIT;
/* Address of bootloader is defined by linker */
extern void bootloader_start(void) __attribute__ ((section (".bootloader"), noreturn));
/* Reboot and run bootloader */
void Boot_StartBootloader(void)
{
/* Disable all interrupts */
__asm__ __volatile__ ("cli" ::)
/* Set the bootloader key to the magic value and enable the watchdog to
force a timeout to reset the AVR. Upon reset, the AVR will execute
Boot_BootloaderCheck() before main() and if the magic key is set then
will call the bootloader.
NOTE: BOOTRST fuse should not be programmed */
Boot_MagicKey = MAGIC_BOOT_KEY;
/* Re-enable watchdog and wait for it to reset us */
wdt_enable(WDTO_500MS);
for(;;);
}
/* Check if bootloader should be run */
void Boot_BootloaderCheck(void)
{
// If the reset source was the watchdog and the key is correct, clear it and jump to the bootloader
if ((MCUSR & (1<<WDRF)) && (Boot_MagicKey == MAGIC_BOOT_KEY))
{
/* Move interrupt vectors to start of bootloader flash section
IVSEL=0 vectors at start of Flash, IVSEL=1 vectors at start of bootloader flash section (as set by BOOTSZ fuses) */
uint8_t Mcucr = MCUCR;
MCUCR = Mcucr | (1 << IVCE);
MCUCR = Mcucr | (1 << IVSEL);
/* Clear boot key to force next reset into application code */
Boot_MagicKey = 0;
/* Jump to bootloader */
bootloader_start();
}
}
Как я понял этот код встраивается в основную программу.
Функцией void Boot_StartBootloader(void) мы устанавливаем Boot_MagicKey и сбрасываем контроллер через watchdog.
Контроллер опять стартует с программы, НО сначала идет функция void Boot_BootloaderCheck(void) которая уже перенаправляет нас на бутлоадер.
А уже в самом бутлоадер получается нужно удалить функцию Application_Jump_Check() так как она уже не нужна.
У меня вопрос.
1) Как компоновщик определит адрес бутлоадера? Если бутлоадер в отдельном проекте от основной программы? Или где указывается эта настройка
extern void bootloader_start(void) __attribute__ ((section (".bootloader"), noreturn));
Re: Запуск bootloader-а из программы
Добавлено: Ср мар 11, 2020 16:53:54
NStorm
Это секция, предлагаемая avr-gcc по умолчанию для использования под бутлоадер (см. avr/boot.h). Видимо у автора того кода она определена. И проект один. Это навскидку если.
Полагаю, что если проекты разные - то никак конечно. Только вместо секции жестко фиксировано прописать адрес бута, ведь конечно же компоновщик не узнает адрес секции, если её в этом проекте нет.