Запуск bootloader-а из программы

Обсуждаем контроллеры компании Atmel.
Ответить
Грызет канифоль
Сообщения: 286
Зарегистрирован: Сб фев 06, 2010 20:39:59

Сообщение 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
Реклама
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Сообщение 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__");
Реклама
Грызет канифоль
Сообщения: 286
Зарегистрирован: Сб фев 06, 2010 20:39:59

Сообщение LEVV2006 »

Что то я уже по разному попробовал.
Вообще не работает.....
Друг Кота
Аватара пользователя
Сообщения: 15599
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

Бутлоадеры существуют для того, чтобы запускаться до начала исполнения программы пользователя.
Да еще и защищаются от случайного самозапуска.
Другое дело, если должен использоваться общий фрагмент загрузчика что в теле бутлоадера, что в прикладной программе - это на случай "горячей перезагрузки" части программного кода.
Однако... на тот случай потребуется и предустановка текущего содержимого критичных РСФ с последующей сменой содержимого таблицы векторов прерываний (или сменой ее расположения) и передачей управления на стартовый адрес бутлоадера.
Есть у меня проектик... но на ассемблере и для MCS51 (там внешнее ОЗУ в качестве памяти программ - вотличии от АВРкового ПЗУ запись содержимого не требует ожидания окончания).
:roll:
Реклама
Эиком - электронные компоненты и радиодетали
Грызет канифоль
Сообщения: 286
Зарегистрирован: Сб фев 06, 2010 20:39:59

Сообщение LEVV2006 »

В принципе..... я тут поизголялся и нашел куда воткнуть кнопку ресет.
При нажатии на ресет МК сбрасывается и загружается бутлоадер.
Ладное. Если что то все же придумаю с программной точки зрения то напишу сюда.
Всем спасибо!
Реклама
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18678
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

на сколько я понимаю, у вас бутлоадер не вызывается потому, что вы адрес точки входа указали в явном виде В БАЙТАХ, в то время как ядро AVR оперирует адресами памяти программ СЛОВАМИ.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Открыл глаза
Сообщения: 42
Зарегистрирован: Вс сен 03, 2017 19:43:57

Сообщение 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
Контактная информация:
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Сообщение NStorm »

[uquote="LEVV2006",url="/forum/viewtopic.php?p=3804159#p3804159"]Что то я уже по разному попробовал.
Вообще не работает.....[/uquote]
Всё работает, если правильно сделать. Адрес правильно указать. Правда вам уже написали тут. Я ж не спроста тот кусок кода привел, где свдиг вправо адреса есть.
Грызет канифоль
Сообщения: 286
Зарегистрирован: Сб фев 06, 2010 20:39:59

Сообщение LEVV2006 »

[uquote="NStorm",url="/forum/viewtopic.php?p=3804515#p3804515"][uquote="LEVV2006",url="/forum/viewtopic.php?p=3804159#p3804159"]Что то я уже по разному попробовал.
Вообще не работает.....[/uquote]
Всё работает, если правильно сделать. Адрес правильно указать.[/uquote]

Я согласен с вами СО ВСЕМИ полностью! Сейчас смотрю ассемблерный код и пытаюсь найти этот адрес....
Грызет канифоль
Сообщения: 286
Зарегистрирован: Сб фев 06, 2010 20:39:59

Сообщение LEVV2006 »

В общем в коде бутлоадера так накручено и наверчено..... что пока победить его не удалось.
Бутлоадер я не сам писал так что разобрался с трудом :)
Пристально рассмотрев дизассемблер обнаружил вот что:

ПО порядку.
1)Фьюз выставлен так что при ресете загружается бутлоадер
2) В коде бутлоадера есть функция которая определяет: грузить бутлоадер или сразу перейти к загрузке основной программы.
Именно этот код отвечает за то, что при подаче питания загружается программа, а при нажатии ресет грузится бутлоадер
3) Эта функция не вызывается из МЕЙН! и в дизассемблере стоит перед входом в функцию мейн! (Как так сделали не знаю...).

Я пробовал по разному переписать функцию проверки, но бутлоадер так и не хочет грузится.
Пробовал в основной программе ставить флаг MCUSR |= (1 << EXTRF); (Говорящий о том что был якобы сброс.)
А потом вызывал бутлоадер ((void (*)(void))0x3000)();
НО пока без результатно.....
Ладно буду думать..... Хитро сделано :)
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Сообщение 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 пуст - значит из основного кода мы пришли, где его уже очистили.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18678
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

LEVV2006 писал(а):вызывал бутлоадер ((void (*)(void))0x3000)();
я вот одного не могу понять: то у вас вход в бутлоадер был по адресу 0х1800, теперь вы по адресу 0х3000 пытаетесь что-то вызвать... а вот тот момент, о котором вам я и NStorm говорили - пословная адресация памяти программ, - я так и не увидел. и это не смотря на явное указание на правильный подход:
NStorm писал(а):Я ж не спроста тот кусок кода привел, где свдиг вправо адреса есть.
сдвиг вправо - это деление на 2, т.е. переход от адреса БАЙТА к адресу СЛОВА, в котором два байта
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Грызет канифоль
Сообщения: 286
Зарегистрирован: Сб фев 06, 2010 20:39:59

Сообщение 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>
И дальше там ещё полно кода....
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18678
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

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

Мой уютный бложик... заходите!
Контактная информация:
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Сообщение NStorm »

LEVV2006, у вас в функции проверка Application_Jump_Check() которая даст далее буту запуститься только, если попали сюда по внешнему сбросу. Вам надо определить адрес функции main() вашего бутлоадера и прыгать к ней. Не пустая адреса в байтах и словах.

Добавлено after 7 minutes 46 seconds:
EDIT: Т.к. это USB бутлоадер на LUFA, который будет использовать прерывания, всё несколько сложнее. Надо еще позаботиться о векторах прерываний через IVSEL.
Вот один из вариантов, как чел сделал: https://www.avrfreaks.net/forum/jumping ... r-software (ближе к концу есть пример кода).
Грызет канифоль
Сообщения: 286
Зарегистрирован: Сб фев 06, 2010 20:39:59

Сообщение 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));
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Сообщение NStorm »

Это секция, предлагаемая avr-gcc по умолчанию для использования под бутлоадер (см. avr/boot.h). Видимо у автора того кода она определена. И проект один. Это навскидку если.
Полагаю, что если проекты разные - то никак конечно. Только вместо секции жестко фиксировано прописать адрес бута, ведь конечно же компоновщик не узнает адрес секции, если её в этом проекте нет.
Ответить

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