Загрузчик USB DFU компании Atmel |
![]() |
Добавил(а) microsin | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Перевод документации USB DFU Bootloader Datasheet [1], посвященной бутлоадеру (загрузчику) USB DFU, который прошит во все чипы AVR с аппаратной поддержкой USB. Рассмотрены следующие возможности и особенности загрузчика: • Протокол обмена [3] работает поверх физического подключения через USB. 8-битные микроконтроллеры mega AVR с аппаратной поддержкой интерфейса USB поставляются с завода сконфигурированными загрузчиком USB (USB bootloader), который размещен в памяти программ FLASH, в пределах специальной секции загрузки (flash boot section) микроконтроллера. Это касается микроконтроллеров моделей AT90USB128x, AT90USB64x, AT90USB162, AT90USB82, ATmega32U4, ATmega16U4. USB-загрузчик позволяет выполнить программирование чипа прямо в той системе, где он работает (In-System Programming), через USB от хоста (компьютера PC). Эта процедура происходит без извлечения чипа из системы, где он работает, и при этом не используется никакой дополнительный интерфейс для программирования (типа ISP или JTAG), и не нужен внешний программатор. В этом документе описывается функционал USB bootloader и затрагивается описание его протокола [3] - рассмотрены вопросы эффективного выполнение операций над памятью чипа (FLASH и EEPROM). [2. Рабочее окружение загрузчика] Бутлоадер размещен в секции загрузки (boot section) которая расположена во встроенной в чип памяти FLASH (память программ). Бутлоадер обрабатывает обмен данными через протокол USB и выполняет операции чтения/записи памяти чипа (Flash/EEPROM). Секция памяти бутлоадера "Bootloader Flash Section" находится в старших адресах памяти FLASH, начиная с заранее известного адреса. Этот адрес может быть выбран из нескольких вариантов фьюзами микроконтроллера, и он влияет на размер секции бутлоадера. Размер секции выбирается так, чтобы код бутлоадера целиком поместился в неё (см. таблицу 2-1). Все необходимые для этого настройки фьюзов и программирование секции загрузки заранее сделаны на заводе Atmel, так что загрузчик поставляется готовым к работе прямо "из коробки". Таблица 2-1. Параметры USB Bootloader.
Примечание к таблице: словом называются 2 байта, которые составляют минимальный размер одной инструкции AVR. Адрес в словах всегда в 2 раза меньше байтового адреса, это иногда создает некоторую путаницу. Рис. 2-1. Физическое окружение, в котором работает загрузчик USB. [3. Запуск загрузчика (Bootloader Activation)] Как указано в даташите на чип серии AT90USB, bootloader может быть активизирован через выполнение одного из следующих условий: • Regular application execution. Прямой запуск из программы пользователя: передача управления (выполнение инструкции jump или call) из секции приложения (Application Section). Это может быть инициировано через команду, принятую по USB, USART или SPI, которая была декодирована приложением пользователя. • Boot Reset Fuse. Фьюз Boot Reset (BOOTRST) может быть запрограммирован так, что вектор сброса (Reset) будет указывать на секцию загрузчика (Boot Flash section), так что загрузчик запустится после сброса или включения питания. Как только загрузчик получил и записал в память приложение пользователя, командой бутлоадера "start application" можно запустить на выполнение загруженную программу пользователя. Имейте в виду, что значение самих фьюзов не может быть изменено самим MCU AVR (командами ассемблера). Это означает, что как только запрограммирован Boot Reset Fuse, вектор сброса всегда будет указывать на начало секции загрузки (адрес Bootloader Reset), и фьюз не может быть изменен другим способом, кроме как через последовательное или параллельное программирование (с помощью специальных программаторов типа JTAGICE mkII или AVRISP mkII). В заводской конфигурации по умолчанию фьюз BOOTRST не активен. • External Hardware conditions. Внешнее аппаратное условие для запуска загрузчика. Отдельный фьюз Hardware Boot Enable (HWBE) может быть запрограммирован, чтобы отслеживать специальное аппаратное условие запуска загрузчика после сброса чипа. Это условие анализируется по лог. уровню ножки порта GPIO, которая имеет дополнительную функцию HWB. Если после сброса на этой ножке лог. 0, то происходит принудительный переход на секцию загрузчика. Различные условия запуска загрузчика суммарно отображены на рис. 3-1. Рис. 3-1. Процесс запуска загрузчика (Boot Process). Пояснения к рисунку: HWB - специальный вывод порта микроконтроллера, который может использоваться для управления загрузкой (работа ножки HWB должна быть разрешена отдельным фьюзом). jmp BOOT - программный переход по адресу начала бутлоадера (либо вызов подпрограмм API для манипуляций с содержимым FLASH). [4. Протокол] 4.1 Что такое Device Firmware Upgrade Device Firmware Upgrade (DFU, обновление программного обеспечения микроконтроллера) - механизм, реализованный для модификаций программного обеспечения (firmware) встраиваемых систем (embedded, т. е. электронные устройства, где применен микроконтроллер). В любом устройстве USB может использоваться такая возможность, если оно отвечает требованиям, описанным в этом документе. Очевидно, что непрактично для устройства одновременно поддерживать и операции DFU, и нормальное рабочее функционирование, так как в общем случае операции загрузчика DFU могут замедлить реакцию основной программы, и работа устройства USB может стать ненадежной. Например, принтер не будет работать как положено, если вовлечено обновление firmware. Кроме того, устройство должно поддерживать функционирование определенного, заранее заданного класса USB (HID, CDC, Audio), что несовместимо с функционированием устройства DFU, так как оно реализовано в виде отдельного класса USB со своим специальным драйвером. Поэтому устройства, поддерживающие DFU, сделаны так, что они не могут сами войти в режим обновления firmware, для этого необходимо специальное внешнее вмешательство человека или хоста с операционной системой. 4.2 Специфичные запросы протокола DFU В дополнение к стандартным запросам USB, используются дополнительно 7 DFU запросов, специфичных для класса DFU (class-specific requests). Эти запросы применяются для поддержки операций обновления, см. таблицу 4-1. Таблица 4-1. DFU Class-specific Requests.
4.3 Набор дескрипторов DFU Устройство экспортирует для хоста USB набор дескрипторов, который содержит: • Дескриптор устройства DFU (DFU device descriptor). 4.3.1 DFU Device Descriptor Дескриптор устройства USB DFU, этот дескриптор имеется только в наборе дескрипторов режима DFU. Код класса DFU поставляется в поле bDeviceClass этого дескриптора. Таблица 4-2. DFU Mode Device Descriptor.
4.3.2 DFU Configuration Descriptor Дескриптор конфигурации DFU, этот дескриптор идентичен стандартному дескриптору конфигурации, описанному в спецификации USB DFU версии 1.0, за исключением того, что поле bNumInterfaces должно содержать значение 01h. 4.3.2.1 DFU Interface Descriptor Дескриптор интерфейса DFU, этот дескриптор доступен только когда устройство работает в режиме DFU. Таким образом, значение поля bInterfaceNumber всегда равно 0. Таблица 4-3. DFU Mode Interface Descriptor
Примечание (1): альтернативные установки могут использоваться в приложении для доступа к дополнительным сегментам памяти. В этом случае предлагается, чтобы каждая альтернативная установка использовала строковый дескриптор, чтобы указать целевой сегмент памяти, например "EEPROM". Детали, касающиеся использования альтернативных установок для других возможных применений, выходят за рамки этого документа. Однако их использование специально ничем не ограничено, поскольку авторы ожидают, что творчески настроенные пользователи разработают варианты использования альтернативных настроек для своих целей. 4.4 Описание команд Протокол, реализованный в бутлоадере AT90USB, позволяет: • Начать процедуру обмена данными. Обзор протокола приведен в Приложении A, см. также [3]. 4.5 Состояние устройства (Device Status) 4.5.1 Get Status Команда запроса состояния устройства. Хост применяет запрос DFU_GETSTATUS для установки синхронизации с устройством. Состояние дает информацию о результате выполнения предыдущего запроса: в_процессе_выполнения/OK/Ошибка/... и т. д.
Устройство отвечает на запрос пакетом полезной нагрузки, который содержит следующие данные: Таблица 4-4. Ответ на команду DFU_GETSTATUS.
Таблица 4-5. Значения поля bStatus.
Таблица 4-6. Значения поля bState.
Прим. переводчика: bStatus содержит код, который сигнализирует о каком-то событии или ошибке, произошедшей с устройством. bState характеризует текущее рабочее состояние устройства, его режим. Для bStatus в этом переводе я решил оставить термин "bStatus", а для bState термин "состояние". 4.5.2 Clear Status Очистка статуса устройства. Каждый раз, когда устройство детектирует ошибку и сообщает о ней хосту по запросу DFU_GETSTATUS, устройство входит в состояние dfuERROR. После сообщения о любой ошибке устройство не может выйти из состояния dfuERROR, пока не получит запрос DFU_CLRSTATUS. Как только устройство получит запрос DFU_CLRSTATUS, оно установит свой статус в OK, и перейдет в состояние dfuIDLE. Как только устройство попало в состояние dfuIDLE, оно может перейти в другие возможные рабочие состояния.
4.5.3 Device State Рабочее состояние устройства. Оно говорит о том, в каком текущем режиме находилось устройство до передачи ответа на запрос. Значения состояния, указанные в поле bState, идентичны тем, что содержатся в ответе на запрос DFU_GETSTATUS.
4.5.4 DFU_ABORT request Запрос на прерывание операции. Запрос DFU_ABORT принуждает устройство выйти из любого другого состояния, отличающегося от DFU_IDLE, после этого устройство переходит в состояние DFU_IDLE. При поступлении запроса DFU_ABORT устройство устанавливает свой статус на OK. Для получения дополнительной информации см. соответствующую сводку изменения состояния.
4.6 Программирование данных FLASH или EEPROM Образ firmware загружаются через передачи control-write, инициированные запросом DFU_DNLOAD, специфичным для класса DFU. Хост отправляет к устройству некоторое количество байт в интервале между bMaxPacketSize0 и wTransferSize в передаче control-write. После каждого загруженного блока хост запрашивает статус устройства запросом DFU_GETSTATUS. Как описано в спецификации USB DFU, "Образы программ (firmware) для специфичных устройств (микроконтроллеров) являются, по определению, зависимыми от вендора. Таким образом требуется, чтобы целевые адреса, размеры записей и любая другая информация, относящаяся к поддержке обновления, была инкапсулирована в файл образа firmware (прим. переводчика: всем этим требованиям удовлетворяет формат файла Intel HEX, который использует для загрузки утилита FLIP). Это зона ответственности как производителя чипа (в данном случае Atmel), так и разработчика firmware - нужно убедиться, что его устройства (в данном случае бутлоадер DFU и утилита FLIP) могут обработать эти инкапсулированные встроенные данные (т. е. если перевести на русский язык, нужно удостовериться, что после обработки образа firmware программа пользователя попадет в те адреса программной памяти, которые нужно, и программа не будет испорчена). За исключением расширения файла DFU (например *.HEX или *.a90) содержимое файла для самого хоста не имеет никакого значения." Как передается образ firmware в протоколе DFU: • 32 байта: команда Таблица 4-7. Суффикс файла DFU.
4.6.1 Запрос от хоста USB
4.6.1.1 Write Command (команда записи)
Команда записи имеет длину 6 байт. Чтобы удовлетворить спецификации USB касательно передач управляющего типа (Control type transfer, передача должна уложиться в пакет 32 байта), команда записи дополняется 26 (32 - 6 = 26) ничего не значащими байтами. Таким образом, общая длина команды получается 32 байта, это размер конечной точки по умолчанию (Default Control Endpoint, конечная точка с номером 0). 4.6.1.2 Firmware Теперь могут быть переданы в устройство данные firmware. Чтобы соответствовать размеру страницы FLASH (128 байт), X ничего не значащих байт добавляются перед первым байтом для программирования. Число X вычисляется для выравнивания начала firmware на начало страницы FLASH. X = start_address [32]. Например, если стартовый адрес 00AFh (175d), X = 175 [32] = 15 (15 это остаток от деления числа 175 на 32). 4.6.1.3 DFU Suffix (суффикс DFU) DFU suffix - это 16 байт, добавленных после последнего байта программы. Суффикс зарезервирован для возможного использования в будущем. Рис. 4-1. Пример запроса DFU_DNLOAD нулевой длины для загрузки firmware. Хост отправляет запрос DFU_DNLOAD с пакетов нулевой длины (Zero Length Packet, ZLP), чтобы обозначить завершение передачи файла образа firmware. Это последний пакет с полезной нагрузкой для операции передачи данных прошивки. 4.6.1.4 Ответы от бутлоадера После каждого запроса программирования хост может отравить запрос на состояние и статус устройства путем отправки сообщения DFU_GETSTATUS. Если статус устройства содержит ошибку, то хост должен отправить устройству запрос DFU_CLRSTATUS. 4.7 Чтение данных FLASH или EEPROM Процедура, описанная ниже, позволяет пользователю прочитать данные памяти FLASH или EEPROM. Команда проверки на чистоту также может быть выполнена с помощью этой процедуры. Вся операция выполняется за 2 шага: • Запрос DFU_DNLOAD с командой чтения (6 байт). 4.7.1 Первый запрос от хоста Хост отправляет запрос DFU Download с командой Display в поле данных.
4.7.2 Второй запрос от хоста Хост отправляет запрос DFU Upload. 4.7.3 Ответы от устройства Устройство отправляет к хосту данные firmware с указанного начального адреса до указанного конечного адреса. 4.7.4 Ответы от устройства на команду Blank Check Хост отправляет запрос GET_STATUS к устройству. Как только внутренний тест на чистоту завершится, устройство отправляет свой статус. • Если статус устройства "OK", то память устройства чистая, и устройство будет ожидать нового запроса от хоста. 4.8 Чтение конфигурационной информации (Configuration Information) или информации производителя (Manufacturer Information) Алгоритм процесса, позволяющий пользователю читать конфигурационную информацию и информацию производителя, описан далее. 4.8.1 Запросы от хоста Для начала операции программирования хост отправляет запрос DFU_DNLOAD с командой Read (чтение) в поле данных (2 байта).
4.8.2 Ответы от бутлоадера Устройство имеет 2 возможные ответа на запрос DFU_GETSTATUS: • Если чип защищен от доступа из памяти программ, хосту будет возвращен статус "err_VENDOR". 4.9 Очистка (Erasing) памяти FLASH Ниже описан процесс, позволяющий пользователю очистить память FLASH. При этом по команде Full Chip erase вся область памяти программ (Application Section), которая не относится к секции загрузки, будет приведена в чистое состояние (изначальное состояние памяти FLASH, когда каждый байт равен 0xFF). Код загрузчика, находящийся в секции загрузки, остается нетронутым. 4.9.1 Запрос от хоста Для начала операции очистки хост отправляет запрос DFU_DNLOAD с командой Write (запись) в поле данных (2 байта).
4.9.2 Ответы от бутлоадера Устройство имеет 2 возможные ответа на запрос DFU_GETSTATUS: • Если чип защищен от доступа из памяти программ, хосту будет возвращен статус "err_WRITE". 4.10 Запуск на выполнение приложения пользователя Ниже описана процедура, позволяющая пользователю запустить на выполнение программу firmware, находящуюся в Application section, напрямую из бутлоадера. Это делается при приеме специальной команды. Возможны два варианта опций: • Запуск программы пользователя с внутренним аппаратным сбросом, который генерирует сторожевой таймер (watchdog). Когда устройство принимает эту команду, то watchdog остается разрешенным, и бутлоадер входит бесконечный цикл ожидания, который приводит к сбросу сторожевым таймером устройства. Чтобы запустить приложение пользователя, хост отправляет запрос DFU_DNLOAD с указанным типом запуска в поле данных (3 или 5 байт). За этим запросом немедленно следует второй запрос DFU_DNLOAD без поля данных, который приводит к старту приложения по одному из выбранных вариантов. Внимание: бутлоадер выполняет watchdog reset (сброс, генерируемый сторожевым таймером) для генерации "аппаратного сброса" (hardware reset), что позволяет выполнить код из секции приложения (application section). После того, как произойдет watchdog reset, AVR watchdog останется в работающем состоянии, так что приложение пользователя должно его запретить при своем старте, если watchdog не нужен. Иначе приложение, которое не позаботится о работающем сторожевом таймере (т. е. не будет его обнулять в бесконечном цикле), будет снова сброшено сторожевым таймером. 4.11 Запрос от хоста
4.12 Ответы от бутлоадера Устройство не будет выдавать никакого ответа. [5. Защита данных программы (Security)] Когда инициировано USB-соединение с загрузчиком, то загрузчик автоматически входит в режим защиты программы от чтения/записи (независимо от установленных битов защиты продукта lock bits). Это позволяет защитить содержимое встроенной в чип памяти FLASH от доступа на чтение/запись через интерфейс USB. Таким образом, допускается выполнение только одной команды DFU, команды полной очистки "Full Chip Erase". После того, как команда "Full Chip Erase" была принята и должным образом выполнена, становятся доступными все команды DFU, и память FLASH может быть перепрограммирована и проверена. [6. Получение доступа к драйверам FLASH низкого уровня (Low level Flash Drivers)] USB-загрузчик AT90USB размещен в секции загрузки (boot section) встроенной в чип памяти FLASH, причем секция загрузки имеет уникальное свойство, что из этих ячеек памяти программ допускается выполнение операций записи во встроенную память FLASH (только в секции загрузки декодируется и выполняется инструкция SPM). Подробнее см. [4]. Таким образом приложения, которым требуется доступ на запись встроенной в чип памяти FLASH, должны выполнять вызовы подпрограмм драйвера Flash по специальным адресам в пределах кода загрузчика USB. Загрузчик USB предоставляет несколько интерфейсов программного доступа (Application Programming Interfaces, API) которые позволяют получить доступ к драйверам низкого уровня FLASH, находящимся в секции загрузки (boot section, там размещено тело загрузчика). Эти интерфейсы API позволяют выполнять следующие операции с памятью FLASH: • Очистка страницы (Page Erase). Рис. 6-1. Вызовы API бутлоадера USB. API расположены по заранее известным абсолютным адресам в коде firmware бутлоадера USB, и принимает в качестве параметров значения из заранее известных регистров. Эти параметры совместимы с соглашением о вызовах (calling convention) компилятора C, так что вызовы подпрограмм драйвера можно осуществлять через указатель на функцию, как показано в примере ниже: #if (FLASH_END==0x1FFFF)
//чипы с памятью FLASH на 128 килобайт #define LAST_BOOT_ENTRY 0xFFFE #elif (FLASH_END==0xFFFF)
//чипы с памятью FLASH на 64 килобайт #define LAST_BOOT_ENTRY 0x7FFE#else #error Вы должны указать значение FLASH_END в байтах. #endif
// Эти указатели на функции используются для вызова функций драйвера FLASH,
// находящихся в теле загрузчика.
void (*boot_flash_page_erase_and_write)(unsigned long adr) = (void (*)(unsigned long))(LAST_BOOT_ENTRY-12); U8 (*boot_flash_read_sig) (unsigned long adr) = (U8 (*)(unsigned long))(LAST_BOOT_ENTRY-10); U8 (*boot_flash_read_fuse) (unsigned long adr) = (U8 (*)(unsigned long))(LAST_BOOT_ENTRY-8); void (*boot_flash_fill_temp_buffer) (unsigned int data,unsigned int adr) = (void (*)(unsigned int, unsigned int))(LAST_BOOT_ENTRY-6); void (*boot_flash_prg_page) (unsigned long adr) = (void (*)(unsigned long))(LAST_BOOT_ENTRY-4); void (*boot_flash_page_erase) (unsigned long adr) = (void (*)(unsigned long))(LAST_BOOT_ENTRY-2); void (*boot_lock_wr_bits) (unsigned char val) = (void (*)(unsigned char))(LAST_BOOT_ENTRY); // Эта функция записывает 0x55AA по адресу 0x1200 во встроенную в чип
// память FLASH с помощью использования драйверов FLASH, размещенных
// в теле USB bootloader.
void basic_flash_access(void) { unsigned long address; unsigned int temp16; temp16=0x55AA; address=0x12000; (*boot_flash_fill_temp_buffer)(temp16,address); (*boot_flash_page_erase)(address); (*boot_flash_prg_page)(address); } Полный код на языке ассемблера для API драйверов FLASH приведен в Приложении B. [7. Использование бутлоадера USB для программирования "прямо в системе" (In System Programming)] Для связи с бутлоадером и перепрошивки программы пользователя на компьютере PC может использоваться программа Flip (её можно свободно скачать с сайта компании Atmel website). Подробные инструкции по использованию Flip и загрузчика USB см. в [2] (там же в разделе Ссылки можно найти ссылку на загрузку старых версий Flip). [8. История развития загрузчика USB] В следующей таблице показаны разные ревизии бутлоадера и связанные с ними изменения. Таблица 8-1. История версий USB Bootloader.
[9. Приложение A] Таблица 9-1. Краткий обзор фреймов от хоста.
[10. Приложение B] ;*A**************************************************************************
; $RCSfile: flash_boot_drv.s90,v $
;----------------------------------------------------------------------------
; Copyright (c) Atmel.
;----------------------------------------------------------------------------
; RELEASE: $Name: $
; REVISION: $Revision: 1.7 $
; FILE_CVSID: $Id: flash_boot_drv.s90,v 1.7 2005/10/03 15:50:12 $
;----------------------------------------------------------------------------
; НАЗНАЧЕНИЕ:
; Этот файл содержит код драйверов низкого уровня для получения доступа
; к памяти FLASH (low level flash driver) из приложения пользователя.
;****************************************************************************
NAMEflash_drv(16) ;_____ I N C L U D E S ______________________________________________________ #define ASM_INCLUDE #include "config.h" ;****************************************************************************
; Здесь находится таблица абсолютных адресов входа в подпрограммы драйвера
; (low level flash drivers). Эта таблица задает точки входа, которые могут
; быть вызваны из секции приложения пользователя (application section),
; чтобы выполнять с памятью FLASH чипа следующие операции:
;
; entry_flash_page_erase_and_write (очистка и запись страницы FLASH):
; R18:17:R16: три байта, содержащие адрес страницы; ; entry_flash_fill_temp_buffer (заполнение промежуточного буфера FLASH):
; data16 : R16/R17: слово для загрузки в промежуточный буфер.
; address: R18/R19: адрес слова в промежуточном буфере.
;
; entry_flash_prg_page (байтовый адрес страницы):
; R18:17:R16: Байтовый адрес страницы FLASH.
;
; entry_flash_page_erase (очистка страницы FLASH):
; R18:17:R16: Байтовый адрес страницы FLASH.
;
;****************************************************************************
ASEG FLASH_END-0x0001Bentry_flash_page_erase_and_write: JMP flash_page_erase_and_writeentry_flash_read_sig: JMP flash_read_sigentry_flash_read_fuse: JMP flash_read_fuseentry_flash_fill_temp_buffer: JMP flash_fill_temp_bufferentry_flash_prg_page: JMP flash_prg_pageentry_flash_page_erase: JMP flash_page_erase_publicentry_lock_wr_bits: JMP lock_wr_bits RSEGBOOT ; ИМЯ: flash_page_erase_and_write
;----------------------------------------------------------------------------
; ПАРАМЕТРЫ: R18:17:R16: байтовый адрес страницы FLASH
;----------------------------------------------------------------------------
; НАЗНАЧЕНИЕ: Эта функция может быть вызвана из кода приложения пользователя,
; она выполняет операцию очистки выбранной страницы и запускает
; последовательность программирования той же самой страницы.
; Эта функция позволяет записать во FLASH 256 байт промежуточного буфера
; программы (software temporary buffer) из секции приложения пользователя.
;****************************************************************************
flash_page_erase_and_write: PUSH R18 RCALL flash_page_erase POP R18 RCALL flash_prg_page RET ;*F**************************************************************************
; ИМЯ: flash_prg_page
;----------------------------------------------------------------------------
; ПАРАМЕТРЫ: R18:17:R16: байтовый адрес страницы FLASH
;----------------------------------------------------------------------------
; НАЗНАЧЕНИЕ: запуск последовательности программирования страницы FLASH.
;****************************************************************************
flash_prg_page: RCALL WAIT_SPMEN ;ожидание, когда очистится флаг SPMEN MOV R31,R17 MOV R30,R16 ;перемещение адреса в указатель z (R31=ZH R30=ZL) OUT RAMPZ, R18 LDI R20,$05 ;(1 << PGWRT) + (1 << SPMEN)) OUT SPMCSR,R20 ; аргумент 2 функции (r18) SPM ; Store program memory (сохранить в памяти программ) RCALL WAIT_SPMEN ;ожидание, когда очистится флаг SPMEN RCALL flash_rww_enable RET ;*F**************************************************************************
; ИМЯ: flash_page_erase
;----------------------------------------------------------------------------
; ПАРАМЕТРЫ: R18:17:R16: байтовый адрес страницы FLASH
;----------------------------------------------------------------------------
; НАЗНАЧЕНИЕ: запуск последовательности очистки страницы FLASH.
;----------------------------------------------------------------------------
; ПРИМЕЧАНИЕ: эта функция не устанавливает бит RWWSE после очистки. Таким
; образом, она не очищает аппаратный промежуточный буфер страницы.
; Эта функция предназначена для использования в загрузчике.
;****************************************************************************
flash_page_erase: RCALL WAIT_SPMEN ;ожидание, когда очистится флаг SPMEN MOV R31,R17 MOV R30,R16 ;перемещение адреса в указатель z (R31=ZH R30=ZL) OUT RAMPZ, R18 LDI R20,$03 ;(1 << PGERS) + (1 << SPMEN))) OUT SPMCSR, R20 ; аргумент 2 функции (r18) SPM ; Store program memory (сохранить в памяти программ) RCALL WAIT_SPMEN ;ожидание, когда очистится флаг SPMEN ;RCALL flash_rww_enable ВНИМАНИЕ, НЕ АКТИВИРУЙТЕ ЗДЕСЬ, или ; потеряете все содержимое промежуточного буфера !!! RET ;*F**************************************************************************
; ИМЯ: flash_page_erase_public
;----------------------------------------------------------------------------
; ПАРАМЕТРЫ: R18:17:R16: байтовый адрес страницы FLASH
;----------------------------------------------------------------------------
; НАЗНАЧЕНИЕ: запускает последовательность очистки страницы FLASH.
;----------------------------------------------------------------------------
; ПРИМЕЧАНИЕ: !!!! Эта функция устанавливает бит RWWSE после очистки. Так что
; после очистки будет очищен также и промежуточный аппаратный буфер.
;****************************************************************************
flash_page_erase_public: RCALL WAIT_SPMEN ;ожидание, когда очистится флаг SPMEN MOV R31,R17 MOV R30,R16 ;перемещение адреса в указатель z (R31=ZH R30=ZL) OUT RAMPZ, R18 LDI R20,$03 ;(1 << PGERS) + (1 << SPMEN))) OUTSPMCSR, R20 ; аргумент 2 функции (r18) SPM ;Store program memory (сохранить в памяти программ) RCALL WAIT_SPMEN ;ожидание, когда очистится флаг SPMEN RCALL flash_rww_enable RET ;*F**************************************************************************
; ИМЯ: flash_rww_enable
;----------------------------------------------------------------------------
; ПАРАМЕТРЫ: отсутствуют
;----------------------------------------------------------------------------
; НАЗНАЧЕНИЕ: устанавливает бит RWSE. Это позволяет выполнить код в секции
; приложения пользователя (application section) после программирования
; FLASH (очистка или запись страницы).
;****************************************************************************
flash_rww_enable: RCALL WAIT_SPMEN ;ожидание, когда очистится флаг SPMEN LDI R20,$11 ;(1 << WWSRE) + (1 << SPMEN))) OUT SPMCSR, R20 ; аргумент 2 функции (r18) SPM ;Store program memory (сохранить в памяти программ) RJMP WAIT_SPMEN ;ожидание, когда очистится флаг SPMEN ;*F**************************************************************************
; ИМЯ: flash_read_sig
;----------------------------------------------------------------------------
; ПАРАМЕТРЫ: адрес байта сигнатуры
; Возвращает R16: значение сигнатуры
;----------------------------------------------------------------------------
; НАЗНАЧЕНИЕ: читает аппаратный байт сигнатуры чипа (его идентификатор).
; Какой байт прочитать - выбирается через аргумент (см. даташит на чип).
;****************************************************************************
flash_read_sig: RCALL WAIT_SPMEN ;ожидание, когда очистится флаг SPMEN MOV R31,R17 MOV R30,R16 ;перемещение адреса в указатель z (R31=ZH R30=ZL) OUT RAMPZ, R18 LDI R20,$21 ;(1 << SPMEN) | (1 << SIGRD)) OUT SPMCSR, R20 ; аргумент 2 функции (r18) LPM ;Load program memory (загрузить из памяти программ). MOV R16, R0 ;Сохранить возвращаемое значение (1 байт -> регистр R16) RJMP WAIT_SPMEN ;ожидание, когда очистится флаг SPMEN ;*F**************************************************************************
; ИМЯ: flash_read_fuse
;----------------------------------------------------------------------------
; Возвращает R16: значение фьюза
;----------------------------------------------------------------------------
; НАЗНАЧЕНИЕ: читает байт фьюза. Байт фьюзов выбирается через адрес,
; передаваемый в качестве аргумента (см. даташит на чип, чтобы узнать
; значение адреса).
;****************************************************************************
flash_read_fuse: RCALL WAIT_SPMEN ;ожидание, когда очистится флаг SPMEN MOV R31,R17 MOV R30,R16 ;перемещение адреса в указатель z (R31=ZH R30=ZL) OUT RAMPZ, R18 LDI R20,$09 ;(1 << SPMEN) | (1 << BLBSET)) OUT SPMCSR, R20 ; аргумент 2 функции (r18) LPM ;Load program memory (загрузить из памяти программ). MOV R16, R0 ;Сохранить возвращаемое значение (1 байт -> регистр R16) RJMP WAIT_SPMEN ;ожидание, когда очистится флаг SPMEN /*F************************************************************************** * ИМЯ: flash_fill_temp_buffer *---------------------------------------------------------------------------- * ПАРАМЕТРЫ: * data16 : R16/R17: слово для загрузки в промежуточный аппаратный буфер. * address: R18/R19: адрес слова. * return: ничего не возвращает *---------------------------------------------------------------------------- * НАЗНАЧЕНИЕ: эта функция позволяет загрузить слово в аппаратный * промежуточный буфер страницы. *---------------------------------------------------------------------------- * ПРИМЕР: * fill_temp_buffer(data16, address); *---------------------------------------------------------------------------- * ПРИМЕЧАНИЕ: первый параметр использует регистры R16, R17. Второй параметр * использует регистры R18, R19. *****************************************************************************/ flash_fill_temp_buffer: MOV R31,R19 ;перемещение адреса в указатель z (R31=ZH R30=ZL) MOV R30,R18 MOV R0,R17 ;переместить data16 в регистры 0 и 1 MOV R1,R16 LDI R20,(1 << SPMEN) OUT SPMCSR, R20 ; r18 выбирает функцию SPM ; Store program memory (сохранить в памяти программ) RJMP WAIT_SPMEN ; ожидание, когда очистится флаг SPMEN ;*F**************************************************************************
; ИМЯ: lock_wr_bits
;----------------------------------------------------------------------------
; ПАРАМЕТРЫ: R16 значение для записи
;----------------------------------------------------------------------------
; PURPOSE: записывает биты защиты
;****************************************************************************
lock_wr_bits: RCALL WAIT_SPMEN ; ожидание, когда очистится флаг SPMEN MOV R0,R16 LDI R18,((1 << BLBSET)|(1 << SPMEN)) OUT SPMCSR, R18 ; r18 выбирает функцию SPM ; запись битов защиты (lockbits) RJMP WAIT_SPMEN ; ожидание, когда очистится флаг SPMEN ;*F**************************************************************************
; ИМЯ: wait_spmen
;----------------------------------------------------------------------------
; ПАРАМЕТРЫ: нет параметров
;----------------------------------------------------------------------------
; НАЗНАЧЕНИЕ: выполняет ожидание флага SPME
;****************************************************************************
WAIT_SPMEN: MOVR0, R18 INR18, SPMCSR ; получить SPMCR в регистр r18 SBRC R18,SPMEN RJMP WAIT_SPMEN ; ожидание, когда очистится флаг SPMEN MOVR18, R0 RET [Ссылки] 1. USB DFU Bootloader Datasheet site:atmel.com. |