USB bootloader для микроконтроллеров AVR

    В статье описывается, как быстро запустить USB bootloader для микроконтроллера ATmega32 на примере загрузчика usbasploader компании Objective Development.

    Технология USB bootloader дает одну-единственную возможность — отсутствие необходимости в специальном программаторе для замены программного обеспечения (firmware) в приборе — достаточно подключения к компьютеру по USB. Больше нет необходимости таскать с собой программатор, так как компьютер и USB есть везде. Если Ваша макетная плата оснащена bootloader, то можно сэкономить деньги на покупке программатора или время на его изготовлении — это бывает немаловажно для начинающих.

    Для AVR понаделано очень много bootloader-ов — см. [1]. Для статьи я выбрал именно usbasploader [2] потому, что он совместим с очень популярным программатором USBasp. Это позволяет перепрошивать firmware как под Linux, так и под Windows с использованием популярных программ (см. [3]) avrdude, eXtreme Burner — AVR, Khazama AVR Programmer и даже из среды программирования BASCOM-AVR (система программирования на бейсике BASCOM-AVR — маленькое чудо, достойное отдельной статьи). Кроме того, usbasploader поставляется со всеми исходниками, отлично задокументирован и легко адаптируется под нужды пользователя (об этом далее).

    Загрузчик usbasploader работает очень просто — при подключении к USB он прикидывается программатором USBasp. Поэтому все программы, его поддерживающие, будут перезаписывать firmware в Вашем устройстве, как будто они используют программатор USBasp. Bootloader расположен в старших адресах flash-памяти программ микроконтроллера, и записывает программу пользователя в младшие адреса (обычно начиная с адреса 0), т. е. при перепрошивке микроконтроллера bootloader не затирается. После окончания записи bootloader передает управление программе пользователя. Теперь подробнее, как это работает с микроконтроллерами ATmega, на примере ATmega32.

    Для ATmega32 usbasploader скомпилирован так, чтобы он размещался во flash с адреса 7000h (напомню, что адресное пространство памяти программ ATmega32 составляет 0000h..7FFFh, и адрес команды кратен двум байтам, т. е. адреса команд лежат в диапазоне 0000h..37FFh). Для программы пользователя остается свободным пространство 0000h..6FFFh (28672 байт). Загрузчик usbasploader использует заложенную в микроконтроллер ATmega32 возможность запуска с адреса, расположенного в старших адресах памяти программ (доступно несколько фиксированных адресов, выбираемых перемычками — фьюзами, см. [4]). Чтобы при включении питания и сбросе управление всегда передавалось на адрес 0x7000, необходимо запрограммировать перемычки (фьюзы, fuse-bits) BOOTSZ0 и BOOTSZ1 в соответствующее состояние (под bootloader должно отводиться 4000h байт, или 2048 слов кода программы), а также запрограммировать перемычку BOOTRST. После этого код при сбросе или включении будет стартовать не с адреса 0, а с адреса 3800h в словах команд AVR, или с адреса 7000h в байтах flash (напомню, что минимальный размер команды AVR — два байта).

    Получив управление после сброса, код usbasploader проверяет условие своей активизации, т. е. сигнал, по которому он должен начать работать как программатор USBasp. Обычно таким сигналом является замыкание какой-нибудь ножки на землю. Для макетной платы в качестве такой ножки я выбрал PB5 микроконтроллера ATmega32. Эта ножка является одновременно и сигналом MOSI, выведенным на коннектор, поэтому перемычкой между контактами 4 и 6 коннектора U1 ISP очень удобно подавать на PB5 сигнал лог. 0. Итак, код usbasploader проверяет уровень на порте PB5, и если там лог. 0 (перемычка между ножками 4 и 6 коннектора U1 ISP установлена), то начинается работа как программатора USBasp. Т. е. при установленной перемычке в момент включения питания bootloader активизируется, и если его подключить к компьютеру, то в компьютере появится USB-устройство USBasp. Если в момент включения питания перемычки нет (при этом на PB5 микроконтроллером читается лог. 1), то usbasploader сразу передает управление в программу пользователя (на адрес 0). Вот такой нехитрый алгоритм запуска.

    В usbasploader есть возможность изменить поведение bootloader, для этого достаточно отредактировать три функции (они очень простые, и находятся в файле bootloaderconfig.h) — bootLoaderInit, bootLoaderCondition, bootLoaderExit. Назначение функций практически очевидно по названиям. Функция bootLoaderInit предназначена для конфигурирования окружения, в котором возможно отслеживание условие активизации bootloader:
    static inline void bootLoaderInit(void) <br>{<br>    DDRB |= (1 << PB0);  //выход для красного светодиода<br>    //на PB5 (MOSI, контакт 4 коннектора U1 ISP) подключаем pull-up и зажигаем светодиод<br>    PORTB |= (1 << PB5)|(1 << PB0);  <br>}

    Код очень прост — он только подключает на ножку PB5 подтягивающий к плюсу внутренний нагрузочный резистор (pull-up) — это позволяет определить наличие перемычки между контактами 4 и 6 коннектора U1 ISP, и зажигает красный светодиод на макетке. Функция bootLoaderCondition предназначена для проверки — есть или нет перемычка между контактами 4 и 6:
    static inline uint8_t bootLoaderCondition() <br>{<br>    if (!(PINB & (1 << PB5))) <br>    {<br>        return 1;<br>    } <br>    else <br>    {<br>        // no boot loader<br>        return 0;<br>    }<br>}
    Если перемычка стоит, то ножка PB5 читается как лог. 0, и функция bootLoaderCondition вернет 1 (что означает — bootloader работает). Если перемычки нет, то функция вернет 0, что означает неактивность для bootloader (управление немедленно передается по адресу 0 — в программу пользователя). Функция bootLoaderExit у меня не делает ничего, только гасит красный светодиод макетки:
    static inline void bootLoaderExit(void) <br>{<br>    PORTB &= ~(1 << PB0);  //гасим светодиод<br>}

    Приведенный код для функций bootLoaderInit, bootLoaderCondition, bootLoaderExit можно рассматривать в качестве примера — их можно и нужно переделать под Ваши нужды, и тогда usbasploader будет работать именно так, как Вы хотите. В заключение опишу процесс по шагам на платформе Windows (предполагается, что у Вас уже установлены AVRStudio и среда WinAVR. Если нет — читайте инструкции, как их установить, по ссылке [6]).

    [Как встроить в Ваш проект usbasploader]

    1. Нужно скачать последнюю версию usbasploader (см. [2]), например USBaspLoader.2009-03-20.zip. Если у Вас макетная плата AVR-USB-MEGA16, то предлагаю скачать вариант по ссылке [5] — там уже все готово, и шаги 2, 3, 4 можно пропустить. Распаковываете в любую удобную папку.

    2. Отредактируйте установки в Makefile. Там нужно поменять:
    а) определение F_CPU — частоту в Гц, на которой работает микроконтроллер. Домустимы частоты 12, 15, 16, 16.5 и 20 МГц.
    б) определение DEVICE под Ваш тип микроконтроллера.
    в) адрес (формат шестнадцатеричный, единицы в байтах) загрузки кода usbasploader BOOTLOADER_ADDRESS.
    г) (необязательно, если Вы будете прошивать чип не из Makefile) проверить и при необходимости скорректровать определения FUSEOPT и LOCKOPT, а также определение AVRDUDE.

    3. Отредактируйте bootloaderconfig.h. Там нужно проверить и при необходимости поменять:
    а) макрос USB_CFG_IOPORTNAME — буква имени порта, к которому подключены сигналы USB D- и D+.
    б) макросы USB_CFG_DMINUS_BIT и USB_CFG_DPLUS_BIT — номера портов, которым подключены сигналы D- и D+. Сигнал D+ обязательно должен быть подключен на ножку прерывания INT0.
    в) код функций bootLoaderInit, bootLoaderExit и макрос bootLoaderCondition.

    4. Перекомпилируйте проект, для этого введите make. В командной строке увидите что-то наподобие:

    image

    После успешной компиляции получите в корневой папке проекта файлы main.bin и main.hex — готовая прошивка для usbasploader. Кстати, в папке hexfiles уже есть несколько скомпилированных версий прошивок для кристаллов ATmega8, ATmega88, ATmega168, на разные частоты кварца.

    5. Необходимо с помощью программатора прошить в чип код usbasploader, правильно установить фьюзы. Смысл этой операции — код usbasploader необходимо положить в верхнюю область памяти (по адресу BOOTLOADER_ADDRESS), и установить фьюзы таким образом, чтбы при сбросе или включении питания начал выполняться код bootloader (я уже об этом писал). Подробности по фьюзам см. по ссылке [4] и в даташите на Ваш микроконтроллер. Для микроконтроллера ATmega32, например, фьюзы должны быть установлены следующим образом:
    LOW FUSE BYTE: 0xCF
    HIGH FUSE BYTE: 0xD8 (можно и 0x98, чтобы разрешить JTAG-отладку)
    LOCKOPT BYTE: 0xEF

    Макетную плату AVR-USB-MEGA16 можно приобрести с уже прошитым usbasploader и фьюзами, поэтому шаги 1, 2, 3, 4, 5 проделывать не нужно.

    6. Необходимо подключить прошитую макетную плату к компьютеру по USB. Если ничего не напутали, то макетка определится в системе как новое устройство и система Windows запросит драйвер. Драйвер можно скачать со странички [2], или взять из архива по ссылке [5]. Для Linux драйвер не нужен.

    7. Нужна одна из программ, работающих с программатором USBasp (см. ссылки [3]). Для пользователей Linux подойдет avrdude, а для пользователей Windows выбор очень широк. Я рекомендую Khazama AVR Programmer с очень простым и удобным интерфейсом.

    image

    image

    [Как работать с загрузчиком usbasploader на примере макетки AVR-USB-MEGA16 и Khazama AVR Programmer]

    1. Поставьте перемычку между ножками 4 и 6 коннектора U1 ISP.
    image

    2. Подключите макетную плату к компьютеру по USB. На макетке загорится красный светодиод, и в системе Windows обнаружится программатор USBasp.

    3. Запустите программу Khazama AVR Programmer. В настройках уберите опцию очистки памяти кристалла (Command -> Program Options -> снимите галку Erase Chip). Выберите из выпадающего списка Ваш чип. Загрузите hex-файл прошивки (через меню File -> Load FLASH file to Buffer). Нажмите большую кнопку Auto Program, запускающую программирование. Программируется кристалл очень быстро, за несколько секунд.
    image
    После окончания программирования красный светодиод погаснет, и начнет выполняться Ваша программа с адреса 0 (которую Вы только что записали).

    4. Снимите перемычку между ножками 4 и 6 коннектора U1 ISP.
    image

    UPD100711: написал статью про другой USB bootloaderBootloadHID. По исходному коду и стилю работы очень похож на USBASPloader. Отличается тем, что требует специальной программы на компьютере, но зато легче встраивается в младшие чипы (начиная с ATmega8), т. к. снижены требования к размеру bootloader-секции.

    [Ссылки]

    1. Загрузчики (bootloader) для микроконтроллеров AVR.
    2. Домашняя страничка usbasploader.
    3. Программы для работы с программатором USBasp — AVRDUDE, BASCOM-AVR, Khazama AVR Programmer, eXtreme Burner- AVR.
    4. Engbedded Atmel AVR® Fuse Calculator — калькулятор перемычек для AVR.
    5. Мой вариант usbasploader, заточенный под макетную плату AVR-USB-MEGA16 с микроконтроллером ATmega32 (проект для AVRStudio с исходниками и скомпилированными вариантами для кварцев 12 МГц, 16 МГц).
    6. Разработка устройства USB — как начать работу с библиотеками AVR USB (V-USB) и libusb.
    7. Бутлоадер USBasp с XOR-шифрованием.
    Поделиться публикацией

    Похожие публикации

    Комментарии 42
    • НЛО прилетело и опубликовало эту надпись здесь
        +1
        К сожалению, Хабр не поддерживает анхоры в статьях (хотел вставить ссылки на якорь рядом с блоком ссылок), поэтому придется постить прямые ссылки. Но тут появляется другое неудобство — будете скакать уже не в футер статьи, а прямиком по ссылкам… Короче, похоже что универсального решения нет.

        Ваш коммент то плюсуют, то минусуют. Пока он колеблется около нуля =).
        +1
        Сам при программировании/разработке пользуюсь программатором, а вот реализовывать обновление прошивки в уже готовом устройстве (например обновление ПО пользователем) вполне удобно с помощью данного загрузчика.
          0
          Я раньше смотрел на бутлоадеры свысока, думал — да нафик они нужны, отъедают место в коде, да еще разбираться надо с ними… Всегда пользовался JTAGICE mkII (программатор плюс отладчик), и думал лучше ничего нет. А как попробовал бутлоадер — понял, что одно другому не мешает, и в конце памяти программ почти всегда есть свободный кусок. Очень удобно — фактически вместе с устройством носишь с собой программатор. Захотел — перешил. Must have однозначно.
            0
                Дело говоришь. Я вот недели три провозился: то один программатор спаяю, то другой — не работает нифига. И схему Громова пробовал, и STK200, и ещё бог знает, что. А у меня была для прототипов плата CraftDuino с выведенными линиями с микросхемы FT232RL. Я подсмотрел у товарища Di Halt'а распиновку для ISP-программатора на этой микросхеме, впаял штырьки и сварганил ISP-шнурок. Успешно прошил ATTiny12, ATTiny2313 и ATMega48.
                А на CraftDuino я прошивку вмиг залил, как только в руках повертел вдоволь — потому что там bootloader. И никакого месяца возни: воткнул в USB, нажал кнопку Upload в IDE, и всё (:
                Жаль, не на все кристаллы можно загрузчик поставить.
              0
              Да, действительно, не на все кристаллы. Минимум на ATmega8. Да и то, чтобы код USB-bootloader влез в секцию 2 килобайта, надо очень постараться — подобрать версию gcc, чтобы код оптимально скомпилился. Лучше всего подходят микроконтроллеры ATmega32 и выше.
                0
                    А если написать на асме? Обычно скомпилированный сишный код отнимает больше флеша, чем ассемблерный. Но сишный код, конечно, более портируемый.
                    Неделю назад я написал кода на асме строк на 200 — светодиодом помигать, моторчик ШИМом через транзистор раскрутить, всё по нажатию кнопки. Прошивка вышла на 174 байта. Сишный код получился в два раза короче (ну да, таблицу прерываний расписывать не надо, но всё же) и понятнее, но прошивка заняла на сей раз 239 байт. Для такой штуки, как загрузчик, я полагаю, излишек побольше будет.
                  0
                  Вы все правильно говорите. Но весь фокус в том, чтобы брать готовенькое и с наименьшими усилиями. Все как обычно — идем по пути наименьшего сопротивления. Кому в здравом уме придет мысль переписывать код, да еще и (подумать страшно!..) — на АССЕМБЛЕРЕ?.. Еффект, который будет получен ради экономии полкилобайта кода (в нашем случае) будет мизерный — ну подумаешь, сможем залить теперь код в ATmega8, когда ATmega32 стоит все равно сущие копейки. А работы придется проделать — мама не горюй, код поддержки USB не шутка даже на C, откройте-ка модуль bootloader\usbdrv\usbdrv.c — понимаете там что-нибудь? Лично я мало что понимаю. Оно Вам надо? Если надо, то тратьте свое драгоценное время.

                  Можно поступить проще — скомпилировать в ассемлер, и вырезать мусорный код, который генерит компилятор (всякие там ненужные PUSH и POP, очистку памяти при старте и т. п.). Т. е. можно заняться низкоуровневой оптимизацией кода C. Но опять-таки, без должного стимула (например денежного) никто и пальцем шевелить не будет — поставят ATmega32 и вся недолга.

                  Похожая тенденция в компьютерном железе — дешевле и экономически выгоднее заставить юзверей проапгрейдиться (взять новый процессор, акселератор, больше памяти и т. п.), чем платить деньги программистам за вылизывание кода драйверов и интерфейсных библиотек.
                    0
                        Согласен, мало кому захочется в этом всём копаться. Лично я себя экономией лишних байт дисциплинирую, чтобы планку не опускать. Конечно же, я не предлагаю экономить везде, где только можно. Мне просто показалось, что было бы неплохо оптимизировать код, для которого приходится подбирать нужную версию компилятора. Как бы там ни было, рано или поздно я напишу свой загрузчик — хотя бы для получения опыта (:
                      0
                      Важна золотая середина — нельзя ни переборщить, не недоборщить. Иначе не выжить в нашем жестоком мире (почти шутка). Идеальный пример — та же самая библиотека V-USB, на которой основан описанный в статье bootloader. Критичные места (которые должны работать максимально быстро и точно) написаны на ассемблере (см. bootloader\usbdrv\usbdrvasm.S), а сложная логика, которая требует модификации и поддержки — на C. Идеальный баланс, отлажено годами, работает как единый механизм. Сравнить разве что можно с автоматом Калашникова — ни грамма лишнего веса, все поставлено на службу её величеству эффективности.
                    0
                    Еще один аспект — поддерживаемость кода. То, что Вы накосячите на ассемблере, через месяц-другой станет не нужно никому, даже Вам. Потому что жизнь идет, все меняется, а подправить в асмовом коде что-то, добавить/изменить функционал будет практически невозможно. Я, конечно, говорю не про мигание светодиодом и не про кручение моторчиком, а про наш конкретный случай (т. е. достаточно объемный код) — bootloader USB.
            +1
              0
              Программирования тут мало-мало. Точнее, его совсем нет. Просто приложение к конкретной задаче. Хотя, может быть, Вы и правы. Только мне блог DIY почему-то больше нравится.
              –3
              «USB здесь, здесь все, никита, стас, гена, турбо и дюша метелкин» (с)
                0
                Еще карма не закончилась для срача в коментах =)?
                  0
                  пока нет))) была бы еще карма для срача в кармах
              • НЛО прилетело и опубликовало эту надпись здесь
                  +1
                  Не покупайте ничего у этих рекламщиков, берите там, где дают нормальную цену.
                • НЛО прилетело и опубликовало эту надпись здесь
                    0
                    На рынке в Москве ATmega32-16AU в розницу стоит 82 рубля. Оптом 75 рублей и дешевле (зависит от партии). Может быть, Михаил надежный поставщик, «помошник» и все такое, но Ваша назойливая реклама говорит об обратном.
                  • НЛО прилетело и опубликовало эту надпись здесь
                      0
                      У меня есть цены только на декабрь 2009 года, других нет. Хотите, озвучу?
                    • НЛО прилетело и опубликовало эту надпись здесь
                        0
                        И что собственно на сегодня, после прошествии 7 месяцев, должно измениться? Цены должны вырасти в полтора — два раза? Не верю.

                        Зашел на efind.ru, поинтересовался. И дальше что? Там есть в разы дороже чем у Вас, но есть и дешевле. Там, где дороже (в том числе и у Вас) я покупать никогда не буду, лучше простимулирую хороших продавцов. Точно так же я не буду покупать у тех, кто бессовестно пичкает меня рекламой.

                        Поймите меня правильно — мне все равно какие у Вас цены, рынок есть рынок, каждый вертится как может. Кому-то Ваши цены могут показаться нормальными (кто не умеет или не хочет искать где дешевле). Дело в Ваших рекламных комментариях — они просто достали, суете их везде и по поводу и без повода.
                      • НЛО прилетело и опубликовало эту надпись здесь
                          0
                          Устал с Вами воевать. Ну как Вам объяснить, чтобы Вы меня поняли? Достала меня Ваша реклама. Русский язык понимаете? Я не хотел бы видеть ТАКИЕ комментарии у себя в статьях и вообще на Хабре. Причем, заметьте, я не против рекламы как таковой. Я против говнорекламы.

                          На Хабре нормальной рекламы очень много. Мало того, весь Хабр состоит на 80% из рекламных статей. Но ТАКАЯ реклама, как Ваша, ИМХО, на страницах Хабра не уместна. Если хотите нормального к себе отношения, пишите что-то действительно полезное и интересное, буду рад почитать, поучиться и покликать по предлагаемым Вами ссылкам.

                          Захотели нахаляву, ничего не делая, получить больше клиентов и посещений своего ресурса? Тогда получите в довесок, то что заработали — минусы в комментариях, рейтинге и в карме. В итоге добьетесь того, что НЛО Вас просто забанит.
                        • НЛО прилетело и опубликовало эту надпись здесь
                            0
                            Никак не успокоитесь? -1.
                          • НЛО прилетело и опубликовало эту надпись здесь
                              0
                              Бесит, бесит, ой как бесит.
                            • НЛО прилетело и опубликовало эту надпись здесь
                                0
                                Скоро рычать начну и порву, как Тузик грелку.
                              • НЛО прилетело и опубликовало эту надпись здесь
                                  0
                                  Да, наверное. Кто первый?
                                • НЛО прилетело и опубликовало эту надпись здесь
                                    0
                                    Подарки я очень люблю, подарки — это хорошо.
                                      0
                                      Что-то Вы надолго замолчали. Голоса за комментарии кончились? Скучно даже как-то…
                                    • НЛО прилетело и опубликовало эту надпись здесь
                                        0
                                        Чего Вы тут аукаете, не в лесу же ведь.
                                          0
                                          В качестве акта доброй воли поднимаю белый флаг и предлагаю заключить пакт о ненападении. Вы обещаете больше на публиковать говнокоментарии у меня в статьях, а я а свою очередь буду закрывать глаза на Ваши злодейства в других местах Хабра и не ставить Вам минусики. За остальных хабралюдей не ручаюсь. Идет?
                                        • НЛО прилетело и опубликовало эту надпись здесь
                                            0
                                            Снова гадюшник из Хабра делаете? Обидно.

                                          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                          Самое читаемое