Arduino Bootloader - PullRequest
       14

Arduino Bootloader

26 голосов
/ 06 сентября 2010

Может кто-нибудь объяснить, как работает загрузчик Arduino ?Я не ищу ответа высокого уровня, я прочитал код и понял его суть.

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

Что мне неясно, так это строка 270:

void (*app_start)(void) = 0x0000; 

... которую я распознаю как объявление и инициализация в NULL указателя функции.Последующие вызовы app_start выполняются в тех местах, где загрузчик предназначен для делегирования выполнения загруженного пользователем кода.

Конечно, каким-то образом app_start нужно получить значение, отличное от NULL, в какой-то момент, чтобы все это собралось вместе.Я не вижу этого в коде загрузчика ... он магически связан с программой, которая загружается загрузчиком?Я предполагаю, что основной загрузчик является точкой входа в программное обеспечение после сброса чипа.

Завернуто примерно в 70 строк сборки, должно быть секретное кольцо декодера, которое сообщает главной программе, где действительно находится app_start?Или, может быть, в Arduino IDE используются неявные знания?Все, что я знаю, это то, что если кто-то не изменит app_start так, чтобы он указывал на что-либо, отличное от 0, код загрузчика просто навсегда закрутился бы в себе ... так в чем же подвох?1019 *

Я заинтересован в попытке портировать загрузчик на Tiny AVR, который не имеет отдельного пространства памяти для кода загрузчика.Поскольку для меня становится очевидным, что код загрузчика опирается на определенные настройки предохранителей и поддержку микросхем, я думаю, что мне действительно интересно знать, что нужно для портирования загрузчика на чип, который не имеет этих предохранителей и оборудованияподдержка (но все еще имеет возможность самостоятельного программирования)?

Ответы [ 2 ]

40 голосов
/ 07 сентября 2010

On NULL

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

ATmegaBootloaders

Обычно при сбросе программный счетчик AVR (ПК) инициализируется равным 0, поэтому микроконтроллер начинает выполнять код по адресу 0.

Однако, если предохранитель перезагрузки перезагрузки ("BOOTRST"), счетчик программы вместо этого инициализируется по адресу блока в верхнем конце памяти (где это зависит от того, как установлены предохранители, см. таблица данных (PDF, 7 МБ)) для уточнения).Код, который начинается там, может делать все что угодно - если вы действительно хотите, вы можете поместить свою собственную программу туда, если вы используете ICSP (загрузчики обычно не могут перезаписать себя).

Часто это специальная программа - загрузчик - он может считывать данные из внешнего источника (часто через UART, I 2 C, CAN и т. Д.) Для перезаписи программыкод (хранится во внутренней или внешней памяти, в зависимости от микро).Загрузчик обычно ищет «специальное событие», которое может быть буквально любым, но для разработки удобнее всего что-то на шине данных, из которой он будет извлекать новый код.(Для производства это может быть специальный логический уровень на выводе, поскольку его можно проверить почти мгновенно.) Если загрузчик видит специальное событие, он может войти в режим загрузки, где он перепрошивает память программы, в противном случае он передает управление.выключен к пользовательскому коду.

Кроме того, смысл плавкого предохранителя и верхнего блока памяти загрузчика состоит в том, чтобы разрешить использование загрузчика с без модификаций исходного программного обеспечения (до тех пор, покаон не распространяется на весь адрес загрузчика).Вместо того, чтобы просто мигать только оригинальным HEX и нужными плавкими предохранителями, можно прошить оригинальный HEX, загрузчик и модифицированные предохранители, а также presto, добавленный загрузчик.протокол от STK500 , он пытается связаться через UART, и если он не получает ответа в отведенное время:

uint32_t count = 0;
while(!(UCSRA & _BV(RXC))) { // loops until a byte received
    count++;
    if (count > MAX_TIME_COUNT) // 4 seconds or whatever
        app_start();
}

или если он слишком много ошибок, получаянеожиданный ответ:

if (++error_count == MAX_ERROR_COUNT)
    app_start();

Передает управление обратно основной программе, расположенной в 0. В источнике Arduino, показанном выше, это делается путем вызова app_start();, определенного как void (*app_start)(void) = 0x0000;.

Поскольку он связан как вызов функции C, перед тем, как ПК переключится на 0, он поместит текущее значение ПК в стек, который также содержит другие переменные, используемые в загрузчике (например, count и error_count сверху).Это украдет оперативную память из вашей программы?Что ж, после того, как ПК установлен в 0, выполняемые операции явно «нарушают» то, что должна делать правильная функция C (которая в конечном итоге вернется).Среди других шагов инициализации, он сбрасывает указатель стека (эффективно уничтожая стек вызовов и все локальные переменные), восстанавливая ОЗУ.Глобальные / статические переменные инициализируются равными 0, адрес которых может свободно перекрываться с тем, что использовался загрузчиком, потому что загрузчик и пользовательские программы были скомпилированы независимо.

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

ATtiny Bootloaders

На ATtinys, как вы упомянули, нет ничего особенного в плавких предохранителях или памяти загрузчика, поэтому ваш код всегда будет начинаться с адреса 0. Возможно, вы сможете поместить свой загрузчик на несколько более высоких страниц памяти и указать вектор RESETпри этом каждый раз, когда вы получаете новый шестнадцатеричный файл для прошивки, возьмите команду с адресом 0: 1, замените его адресом загрузчика, затем сохраните замененный адрес в другом месте, чтобы вызвать его для нормального выполнения.(Если это RJMP относительный скачок»), значение, очевидно, необходимо пересчитать)

1 голос
/ 24 октября 2013

Редактировать

Я заинтересован в попытке портировать загрузчик на Tiny AVR, который не имеет отдельного пространства памяти для кода загрузчика.Поскольку для меня становится очевидным, что код загрузчика опирается на определенные настройки предохранителей и поддержку микросхем, я думаю, что мне действительно интересно знать, что нужно для портирования загрузчика на чип, который не имеет этих предохранителей и оборудованияподдержка (но все еще имеет возможность самопрограммирования)?

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

1) uart tx

2) uart rx

3) программирование с самостоятельной флеш-памятью

, которое можно изучить отдельно, а затем объединить в загрузчик.Вам понадобится часть, которую вы можете использовать для записи флэш-памяти spi или что-то еще, так что, если ваш загрузчик не работает или какая-то деталь, поставленная с вами, испортилась, вы все равно можете продолжить разработку.

Независимо от того, портируете ли вы или катаетесь самостоятельно, вам все равно нужно понимать эти три основные вещи, относящиеся к этой части.

...