Blackfin: утилита elfloader.exe |
![]() |
Добавил(а) microsin | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
В этой статье приведен перевод частей документации [1], касающихся только процессоров Blackfin ADSP-BF53x. Описывается использования утилиты для генерации файла загрузки - elfloader.exe. [Введение: основные понятия и термины] Этот документ описывает главным образом функционал утилиты загрузки, а также процесс loading-а (загрузка) и splitting-а (разделение исполняемого кода). Некоторые непонятные сокращения и термины см. в разделе "Словарик" статей [3, 4]. Загрузчик и Утилита загрузки. Под термином утилита загрузки подразумевается программа elfloader.exe (Loader Utility), которая является частью пакета разработки VisualDSP++. Утилита загрузки выполняет завершающую обработку процесса компиляции, получая на входе один или несколько исполняемых файлов (с расширением *.dxe) и генерируя на выходе файл загрузки (с расширением *.ldr). В процессе обработки файлов *.dxe утилита загрузки распаковывает сегменты, декларированные командой TYPE(RAM) в файле Linker Description File (.ldf). Поскольку файл .dxe следует стандарту Executable and Linkable Format (ELF), утилита загрузки часто называют утилитой elfloader. См. также раздел "Как работает утилита загрузки". Splitter Utility. Splitter utility также является частью пакета VisualDSP++. Утилита сплиттера обрабатывает один или несколько файлов исполняемых файлов (с расширением .dxe), распаковывает сегменты, декларированные командой TYPE(ROM) файла Linker Description File (.ldf), и генерирует файл, состоящий из инструкций (команд) процессора. Это файл прошивается в память EPROM или flash процессора, которая подключена к нему через системную шину, так что процессор может напрямую выбирать оттуда команды и выполнять их. Подробнее про работу Splitter Utility см. раздел "Splitter Utility Operations" руководства [1]. Работа утилиты сплиттера и утилиты загрузки может быть обработана либо отдельными утилитами, либо одной и той же программой (см. раздел "Не загружаемые файлы (Non-bootable) и загружаемые (Boot-loadable) - в чем разница?"). Для загружаемых файлов выходной файл содержит как инструкции кода, так и специальные данные потоков загрузки (заголовки, описывающие секции файла загрузки, см. [2]). Примечание: splitter utility не имеет отношения к процессорам Blackfin, и в этом переводе документации [1] не рассматривается. Файл загрузки. Файл загрузки (loader file) генерируется утилитой загрузки. Обычно этот файл имеет расширение .ldr, и поэтому часто называется файлом LDR. Файлы загрузки могут удовлетворять одному или нескольким форматам. Общие форматы содержимого файла загрузки: Intel hex-32, binary или ASCII (чаще всего применяется двоичный формат, binary). Независимо от формата файл загрузки описывает образ загрузки (boot image), который можно увидеть в двоичной (binary) версии файла загрузки. Также см. раздел "Не загружаемые файлы (Non-bootable) и загружаемые (Boot-loadable) - в чем разница?". Опции командной строки утилиты загрузки. Поведение утилиты загрузки управляется многочисленными опциями командной строки, которые будут подробно рассмотрены далее (в этом переводе [1] только для процессора Blackfin). От опций зависит генерация выходного файла загрузки *.ldr. Раздел "Load" свойств проекта. В среде VisualDSP++ можно управлять свойствами проекта (Project Options). Диалог редактирования свойств проекта имеют раздел свойств загрузки (Load). Этот графический интерфейс помогает сформировать командную строку для утилиты загрузки (утилита elfloader.exe автоматически будет запущена средой VisualDSP, если выбрана генерация файла загрузки через Project Options -> Project -> раздел опций Target -> Type: Loader file). Режим загрузки (Boot Mode). Большинство процессоров поддерживают несколько режимов загрузки. Режим загрузки определяет специальные входные выводы процессора, которые опрашиваются им либо после сброса (reset), либо после выхода из состояния выключения (power-down state). Подробнее про режимы загрузки см. раздел "Boot Modes", а также статью [2]. Boot Strapping. Процесс загрузки состоит из нескольких шагов, таких как предварительная загрузка ядра (boot kernel) или управление загрузчиками второго уровня (second-stage loaders). Эта процедура называется boot strapping или boot ROM. Код инициализации (Init Code). Это часть потока загрузки процессоров Blackfin, и её можно рассматривать как специальный блок загрузки. В то время как обычно сначала загружаются все загружаемые блоки приложения, и затем управление передается в само приложение, код инициализации выполняется во время загрузки - как первый шаг всего процесса загрузки. Такое происходит, когда код инициализации загружается и выполняется перед любым другим загружаемым блоком. Необходимость наличия кода инициализации обусловлена такими случаями, как необходимость инициализации памяти SDRAM (например, код приложения и данные должны быть загружены в SDARM), настройка каких-то специфичных аппаратных средств системы, обеспечения процедуры обновления, или для оптимизации процесса загрузки основного приложения. Global Header. Некоторые загрузчики ядра (boot kernel) ожидают наличия в потоке загрузки специальной информации. Этот тег называется глобальным заголовком (global header). Callback Routine. Некоторые процессоры опционально могут вызывать подпрограмму, определенную пользователем - после того как блок загрузки загружен и обработан. Эта подпрограмма называется callback routine (процедура обратного вызова). Она может предоставить такие функции, как реализация контрольной суммы кода, стратегии декомпрессии. Slave Boot, Master Boot. Термин Slave Boot относится ко всем режимам загрузки, когда целевой процессор работает как подчиненное устройство. Master Boot - когда при загрузки внешнее хранилище образа загрузки обрабатывается самим процессором (т. е. хранилище работает как подчиненное устройство). Подробнее см. [2]. Менеджер загрузки (Boot Manager). Менеджер загрузки - код firmware, который определяет, какое приложение должно быть загружено. Приложение обычно представлено как проект среды VisualDSP++, и результат компиляции проекта сохраняется в исполняемом файле с расширением *.dxe. Сам по себе менеджер загрузки может быть реализован как в файле основного приложения *.dxe, так и в виде отдельного файла *.dxe. Часто менеджер загрузки выполняется в так называемом коде инициализации (Init Code). В сценариях загрузки slave boot управление загрузкой возлагается на процессор хоста, и это не требует специальной поддержки со стороны VisualDSP++. Multi-.dxe Boot. Файл загрузки может содержать в себе данные файлов нескольких приложений (*.dxe), если утилита elfloader была запущена с указанием нескольких входных файлов *.dxe. Либо менеджер загрузки должен решить, какое именно приложение из нескольких должно быть загружено и запущено, либо альтернативно одно загруженное приложение может остановить свою работу, после чего загрузится следующее приложение. В некоторых случаях одно приложение может также состоять из нескольких файлов *.dxe (чаще всего из DXE для Init Code и DXE для основного приложения). Next .dxe File Pointer. Если файл загрузки состоит из нескольких приложений, некоторые форматы потока загрузки позволяют организовать файл загрузки в виде связанного списка. Указатель на следующий DXE (next .dxe pointer, NDP) - просто указатель на место, где в потоке загрузки находится следующее приложение. Preboot Routine. Подпрограмма, выполняющаяся перед загрузкой (preboot routine), представлена в частях кода boot ROM процессора (однократно программируемая, OTP память, которая записана на заводе). Preboot читает память OTP, и настраивает некоторые регистры MMR на основе заводских инструкций и инструкций пользователя, как это запрограммировано в память OTP. Preboot routine запускается до загрузки ядра (boot kernel). [Что такое Loading, Splitting] После завершения цикла отладки, аппаратура процессора должна быть запущена отдельно, в составе рабочей системы (без подключенного отладчика). После включения питания нужно инициализировать встроенные в чип процессора, и находящиеся вне чипа устройства памяти. процесс инициализации областей памяти часто называют загрузкой (booting). Таким образом выходной файл линкера должен быть преобразован в формат, который может быть прочитан загрузчиком процессора (кодом Boot ROM). Этот процесс преобразования обрабатывается утилитой загрузчика и/или сплиттера. Утилита loader/splitter использует отлаженные и протестированные на этапе разработки исполняемые файлы (*.dxe), как и общую память и файлы оверлея в качестве входных данных, и генерирует читаемый процессором файл. В пакете разработки VisualDSP++ 5.0 включены следующие утилиты loader и splitter: • elfloader.exe (утилита загрузки, loader utility) для семейств процессоров Blackfin, TigerSHARC и SHARC. Утилита загрузки для процессоров Blackfin работает также и как утилита ROM splitter, когда запускается с соответствующими опциями командной строки. • elfspl21k.exe (утилита ROM splitter) для семейств процессоров TigerSHARC и SHARC. На выходе утилит loader/splitter получается либо загружаемый (boot-loadable), либо не загружаемый (non-bootable) файл. Под выходом понимаются данные (обычно это файл с расширением *.ldr), прошиваемые в память целевой системы (это может быть, например, FLASH-память на кристалле ADSP-BF538, или память SPI, откуда загружается программа при включении питания). Есть несколько способов использования выхода утилит загрузки/сплиттера: • Плагин Flash Programmer. Он позволяет записать файл загрузки в область PROM процессора платы разработчика EZ-KIT Lite®. Подробнее см. справочную систему VisualDSP++, раздел Flash Programmer. • Симулятор загрузки. Можно использовать VisualDSP++ для симулирования загрузки в сессии симулятора (в настоящее время поддерживается для процессоров ADSP-21060, ADSP-21061, ADSP-21065L, ADSP-21160 и ADSP-21161). Загрузите файл загрузки, и затем сбросьте процессор, чтобы отладить подпрограммы загрузки. Не требуется никакой аппаратуры: просто укажите на место положения файла загрузки, и позвольте симулятору выполнить остальную работу. Вы можете по шагам выполнит код boot kernel и посмотреть, как он переносит в память остальной код. • Многопроцессорная система. Можно сохранить файл загрузки в массив для многопроцессорной системы. Главный процессор (хост) распоряжается этим массивом памяти после сброса, и загружает файл в память подчиненного процессора. [Не загружаемые файлы (Non-bootable) и загружаемые (Boot-loadable) - в чем разница?] Не загружаемый файл выполняется напрямую из внешней памяти процессора (обычно FLASH), в то время как данные загружаемого файла транспортируются во внутреннюю (и/или иногда во внешнюю память SDRAM), и после этого запускается на выполнение. Загружаемый файл записывается в устройство внешней памяти (это может быть SPI EPROM, или FLASH) Вашей целевой системы. Утилита загрузки выводит загружаемые файлы в форматах, которые понимают большинство прошивальщиков EPROM (такие форматы, как Intel hex-32 и Motorola S). Для особых случаев поддерживаются другие форматы файла и режимы загрузки, часто используется сырой, двоичный формат (подробнее см. "File Formats" [1]). Не загружаемые образы выполняются из внешней памяти процессора, с пропуском механизмов загрузки. Подготовка не загружаемого образа EPROM называется сплиттингом (splitting). В большинстве случаев (за исключением процессоров Blackfin) разработчики, использующие процессоры с плавающей точкой или фиксированной точкой, используют splitter вместо утилиты loader, чтобы сгенерировать не загружаемый образ памяти. Как загружается процессор и дизайн программы диктуют метод, каким будет вызвана утилита loader/splitter, чтобы обработать и преобразовать исполняемые файлы: • Для процессоров Blackfin операции loader и splitter обрабатываются одной утилитой, elfloader.exe. Функция splitter вовлекается другим набором опций командной строки, отличающимся от опций функции loader. В VisualDSP++ 5.0, в дополнение к опции -readall, утилита loader для процессоров ADSP-BF51x, BF52x, BF54x Blackfin может автоматически вызывать программу сплиттера. Для дополнительной информации см. в [1] описание опции -readall. • Для процессоров TigerSHARC и SHARC операции splitter обрабатываются отдельной утилитой сплиттера elfspl21k.exe. Примечание: везде в тексте, где встречается наименование процессора без префикса BF51x, BF52x, BF53x, BF561 и т. п., подразумевается процессор Blackfin с префиксом ADSP- (ADSP-BF51x, ADSP-BF52x, ADSP-BF53x, ADSP-BF561 и т. п.). [Как работает утилита загрузки] Общие задачи, которые выполняет утилита загрузки, могут включать следующее: • Обработка опций loader в командной строке. Вы можете запустить утилиту loader неявно, когда запускаете компиляцию проекта из среды разработки VisualDSP++ (когда задано генерировать файл загрузки через Project Options -> Project -> раздел опций Target -> Type: Loader file), или из командной строки. Чтобы настроить поведение утилиты при запуске из VisualDSP++, откройте свойства проекта Project Options в меню Project, и в диалоге настройки свойств проекта поменяйте Target из типа Executable file в Loader File, и затем отредактируйте раздел Load свойств проекта. Работа утилиты загрузки elfloader.exe зависит от свойств загрузки (раздел Load свойств проекта), которые управляют тем, как утилита загрузки преобразует исполняемые файлы в загружаемые файлы, позволяя Вам выбрать такие возможности, как ядра (kernels), режимы загрузки (boot modes) и выходные форматы файла (output file formats). Эти опции настраиваются в разделе Load свойств проекта Project Options VisualDSP++, или их можно задать из командной строки. Опции страниц раздела Load соответствуют опциям командной строки утилиты elfloader.exe. [Режимы загрузки (Boot Modes)] Как только исполняемый файл полностью отлажен, утилита загрузки готова к преобразованию исполняемого файла (или нескольких исполняемых файлов) в загружаемый процессором (processor-loadable, или boot-loadable) файл. Загружаемый файл может быть автоматически загружен (booted) в процессор при включении питания (power-up) или программного сброса системы (software reset). Способ, каким утилита будет создавать загружаемый файл, зависит от того, как загружаемый файл загружается в процессор (и конечно же, это задается пользователем в разделе Load свойств проекта или через опции командной строки утилиты elfloader.exe). Режим загрузки (boot mode) процессора [2] определяется опросом одного или большего количества специальных внешних выводов корпуса процессора (например, для процессора Blackfin ADSP-BF538 это выводы BMODE1, BMODE0). Последовательности загрузки, жестко зависящие также от модели процессора, подробно описаны в следующих разделах. Процессоры компании Analog Devices поддерживают разные механизмы загрузки. Обычно могут использоваться следующие схемы, чтобы предоставить процессору инструкции - как действовать процессору после сброса. • No-Boot Mode No-Boot Mode. После сброса процессора начинает напрямую вычитывать и выполнять инструкции из устройств EPROM/flash (у процессора ADSP-BF538F эта память может быть даже встроена в кристалл чипа процессора). Эта схема не требует никаких механизмов загрузки (т. е. код Boot ROM не задействован). На программу пользователя возлагается инициализация работоспособности и содержимого энергозависимой памяти (SRAM L1, SDRAM). Утилита сплиттера генерирует файл, который может быть прошит в память PROM. PROM Boot Mode. После сброса процессор начинает вычитывать данные из параллельного или последовательного устройства памяти PROM. Память PROM хранит специальным образом отформатированный поток загрузки (заточенный под обработку кодом Boot ROM, см. [2]), а не просто код инструкций. Вместе с данными приложения поток загрузки содержит дополнительную информацию, такую как адреса назначения и счетчики слов. Маленькая программа, так называемый загрузчик ядра (или же Boot ROM, как у процессоров Blackfin) анализирует поток загрузки и в соответствии с ним инициализирует области памяти процессора. Загрузчик ядра (или код Boot ROM) работает под управлением целевого процессора. В зависимости от архитектуры, загрузчик ядра может выполняться либо из встроенной в чип памяти boot RAM, или из устройства памяти PROM, копируя код в SRAM процессора и выполняя его оттуда. Утилита загрузки генерирует данные потока загрузки из выходных данных линкера (один или несколько исполняемых файлов *.dxe) и сохраняет поток загрузки в файл (обычно это файл *.ldr) в формате, подходящем для прошивки в PROM. Host Boot Mode. В этой схеме целевой процессор ведет себя как подчиненное устройство, управляемое системой хоста [2]. После сброса процессор задерживает выполнение программы, пока не получит сигнал от хост-системы, что процесс загрузки завершен. В зависимости от возможностей аппаратуры, есть два разных метода загрузки под управлением хоста. Первый метод - когда система хоста получает полное управление над всеми областями памяти целевой подчиненной системы. Хост приостанавливает работу целевой системы, пока инициализирует все области памяти. По второму методу хост обменивается с целевой системой специальными сигналами (см. [2]), и последовательно передает данные подчиненному целевому процессору, на котором работает загрузчик ядра (или код Boot ROM). Код загрузчика может быть выполнен из встроенного в чип Boot ROM, или может быть загружен от хоста в SRAM по любой из других допустимых схем загрузки. Утилита loader/splitter генерирует файл, который использует система хоста. Он зависит от возможностей устройства хоста и от архитектуры целевой системы - ожидает ли хост сырые данные приложения, или же отформатированный поток загрузки. В этом контексте загружаемый файл отличается от не загружаемого тем, что загружаемый файл кроме кода приложения содержит дополнительные данные, которые должен обработать загрузчик ядра (код Boot ROM). Не загружаемый файл содержит только чистый исполняемый код инструкций (команд) процессора. [Загрузка процессора ADSP-BF53x/BF561] При включении питания и/или после сброса процессор переходит в последовательность boot mode, который конфигурируется внешними входными выводами BMODE (см. [2]). Это специальные, выделенные выводы корпуса процессора, которые не обслуживают никаких других функций. Состояние выводов BMODE может быть программно прочитано через биты регистра конфигурации системы после сброса (System Reset Configuration Register, SYSCR). Процессоры Blackfin моделей ADSP-BF53x или ADSP-BF561 могут загружаться либо из 8-битной, либо из 16-битной памяти flash/PROM, или из адресуемой 8 битами, 16 битами или 24-битами памяти SPI. Процессоры ADSP-BF561 не поддерживают загрузку через 24-битно адресуемую память SPI. Также имеются опции no-boot (bypass mode, пропуск запуска кода Boot ROM), когда выполнение программы сразу начинается из 16-разрядной внешней памяти. Опции загрузки также могут зависеть и от ревизии кристалла. Подробнее про варианты загрузки Blackfin см. [2]. После сброса процессор ADSP-BF531, BF532, BF533, BF534, BF536, BF537, BF538, BF539 передает управление во встроенный в кристалл код Boot ROM (если BMODEx != 00), или в область внешней 16-разрядной памяти (если BMODEx == 00) по адресу 0x20000000. Подробнее про Boot ROM процессора см. раздел "ADSP-BF531, BF532, BF533, BF534, BF536, BF537, BF538, BF539 On-Chip Boot ROM". В таблице 3-1 сведены режимы загрузки и стартовые адреса процессоров ADSP-BF531, ADSP-BF532, ADSP-BF533, ADSP-BF538 и ADSP-BF539.
• Выполнение из 16-разрядной внешней памяти – процессор начинает выполнение кода с адреса 0x20000000 (код с 16-разрядной упаковкой). В этом режиме передача управления в Boot ROM пропускается. Все конфигурационные настройки внешней шины сбрасываются в состояние, рассчитанное на самое медленное внешнее устройство памяти: 3 цикла время удержания (hold time), 15 циклов для доступа на чтение/запись, 4 цикла на предустановку (setup). • Загрузка из 8- или 16-разрядной внешней flash-памяти – в этом режиме подпрограмма загрузки расположена в области Boot ROM, и для потока загрузки используется асинхронный банк памяти 0. Все настройки конфигурации сбрасываются в расчете на самое медленное устройство памяти: 3 цикла время удержания (hold time), 15 циклов для доступа на чтение/запись, 4 цикла на предустановку (setup). Boot ROM анализирует первый байт потока загрузки по адресу 0x20000000. Если он равен 0x40, то выполняется 8-битная загрузка. Если байт равен 0x60, то подразумевается 16-разрядное устройство памяти и выполняется 8-разрядный DMA. Байт 0x20 также подразумевает 16-разрядную память, но выполняет 16-разрядный DMA. • Загрузка через SPI под управлением хоста – процессор Blackfin работает как подчиненное устройство SPI, и конфигурируется для приема байтов файла .ldr от хоста (мастера) шины SPI. Описание процедуры обмена и используемых сигналов см. в [2]. • Загрузка из последовательной памяти SPI (EEPROM или flash) – используются микросхемы памяти с 8-, 16- или 24-разрядной адресацией, также поддерживаются микросхемы AT45DB041, AT45DB081, AT45DB161, AT45DB321, AT45DB642 и AT45DB1282 DataFlash® от компании Atmel. Описание процедуры детектирования типа микросхемы и сигналов обмена см. в [2]. Процессоры ADSP-BF534, BF536, BF537 также поддерживают загрузку через интерфейсы TWI и UART, подробнее см. [1]. Благодаря наличию механизма Multi-.dxe Boot программист может создать собственный загрузчик кода, который позволит загрузить (или даже обновить) приложение из любых других источников или через любой другой доступный интерфейс связи с внешним миром. [ADSP-BF531, BF532, BF533, BF534, BF536, BF537, BF538, BF539 On-Chip Boot ROM] После того, как встроенный в процессор код загрузки (On-Chip Boot ROM) получает управление, то он выполняет следующие действия: 1. Настраивает режим супервизора (supervisor mode) путем выхода из обработчика прерывания RESET, и перехода в прерывание с самым низким приоритетом (IVG15). Обратите внимание, что on-chip boot ROM процессоров ADSP-BF534, BF536 и BF537 выполняется на уровне приоритета Reset, не снижая уровень приоритета выполнения на самый низкий уровень приоритета прерываний. 2. Проверяет, был ли RESET программным сбросом, и если это так, то либо пропускает всю последовательность загрузки и делает переход на начало памяти L1 (адрес 0xFFA00000 для процессоров ADSP-BF533, BF534, BF536, BF537, BF538 и BF539 processors; адрес 0xFFA08000 для процессоров ADSP-BF531, BF532). Проверка делается кодом Boot ROM путем анализа бита NOBOOT (бит 4) регистра конфигурации системы после сброса (System Reset Configuration Register, SYSCR). Если бит 4 не установлен, то код Boot ROM выполняет полную процедуру загрузки. Если бит 4 установлен, то код Boot ROM пропускает полную последовательность загрузки и сразу передает управление в начало памяти L1. 3. Бит NOBOOT (бит 4 регистра SYSCR) не установлен, начинается полная последовательность загрузки (см. рис. 3-1). Рис. 3-1. Последовательность загрузки процессоров ADSP-BF531, BF532, BF533, BF534, BF536, BF537, BF538, BF539. Последовательность загрузки процессоров ADSP-BF531, BF532, BF533, BF534, BF536, BF537, BF538, BF539 отличается от процессоров ADSP-BF535. On-chip boot ROM для этих процессоров ведет себя так же, как и загрузчик второй стадии процессора ADSP-BF535 (подробнее см. раздел "ADSP-BF535 Processor On-Chip Boot ROM"). У кода Boot ROM есть возможность обрабатывать адреса и количество байт для каждого загружаемого блока потока загрузки. Это смягчает требования к условиям работы загрузчика второго уровня, потому что полное приложение может быть загружено из различных устройств памяти, когда на самом процессоре есть только встроенный код Boot ROM. Как уже упоминалось, утилита загрузки преобразует исполняемое приложение (файл .dxe) в загружаемый файл, анализируя код и создавая файл, который состоит из различных блоков. Каждый блок снабжен 10-байтным заголовком, как это показано на рис. 3-1, и более подробно разъяснено в последующих секциях (также см. [2]). Заголовки, в свою очередь, читаются и обрабатываются кодом Boot ROM во время загрузки. 10-байтный заголовок предоставляет загрузчику (код Boot ROM) всю необходимую информацию — куда надо поместить блок, сколько байт занимает блок, и что нужно делать с этим блоком. [Потоки загрузки ADSP-BF531, BF532, BF533, BF534, BF536, BF537, BF538, BF539] Далее описаны поток загрузки, заголовки и флаги для процессоров ADSP-BF531, ADSP-BF532, ADSP-BF533, ADSP-BF534, ADSP-BF536, ADSP-BF537, ADSP-BF538 и ADSP-BF539. Когда утилита загрузки преобразует код из входного файла .dxe в блоки, помещаемые в выходной файл загрузки, каждый блок получает 10-байтный заголовок (показанный на рис. 3-2), за которым идет тело блока (если это не zero-блок) или тело no-block (если это zero-блок). Описание структуры заголовка приведено в таблице 3-3. Рис. 3-2. Процессоры ADSP-BF531, BF532, BF533, BF534, BF536, BF537, BF538, BF539: структура потока загрузки. Таблица 3-3. Структура заголовка блока ADSP-BF531, BF532, BF533.
На рис. 3-3 и в таблице 3-4 поясняется структура битов флагов. Рис. 3-3. Биты флагов для 2-байтового поля флагов заголовка. Таблица 3-4. Структура флагов.
Обратите внимание, что процессоры ADSP-BF534, BF536, BF537 могут иметь специальный последний блок, если режим загрузки TWI (Two Wire Interface, I2C, двухпроводный интерфейс). Утилита загрузки сохраняет все данные от 0xFF903F00 до 0xFF903FFF и делает последний блок с этими данными. Утилита загрузки, однако, создает обычный последний блок, если в этом диапазоне нет данных. Область 0xFF903F00 .. 0xFF903FFF сохраняется для Boot ROM, чтобы использовать эту память как буфер данных для процесса загрузки. Опция -init filename дает указание утилите загрузки генерировать блоки, полученные из кода инициализации (Init Code), код берется из файла filename. Блоки кода инициализации помещаются в начало файла загрузки. Они выполняются до того, как остальная часть кода в файле загрузки будет загружена в память и выполнена (см. рис. 3-4). Рис. 3-4. Выполнение блока инициализации (Init Code) процессоров ADSP-BF531, BF532, BF533, BF534, BF536, BF537, BF538, BF539. После выполнения кода из блоков инициализации, процесс загрузки продолжит загружать остальные блоки данных, пока не дойдет до последнего блока (см. рис. 3-5). Пример кода инициализации показан в листинге 3-1. Рис. 3-5. Загрузка кода приложения процессоров ADSP-BF531, BF532, BF533, BF534, BF536, BF537, BF538, BF539. Листинг 3-1. Пример блока кода инициализации. /* Этот файл содержит 3 секции: */
/* 1) Pre-Init Section – эта секция сохраняет в стек все регистры процессора.
2) Init Code Section – эта секция содержит код инициализации, который
может быть модифицирован пользователем. В качестве примера здесь
приведен код инициализации SDRAM (обычная задача для Init Code).
Настраивается контроллер SDRAM, как это требуется для основных типов
SDRAM. Разные типы SDRAM могут потребовать другой процедуры инициализации
(обычно просто других значений, записанных в регистры).
3) Post-Init Section – эта секция восстанавливает все регистры из стека.
Пользователь не должен менять секции Pre-Init и Post-Init. Секция
Init Code может быть модифицирована в соответствии с задачами
отдельного приложения. */
#include < defBF532.h >
.SECTION program;
/**********************Pre-Init Section************************/ [--SP] = ASTAT; /* Stack Pointer (SP) устанавливается на конец */ [--SP] = RETS; /* памяти scratchpad (0xFFB00FFC) */ [--SP] = (r7:0); /* кодом on-chip Boot ROM */ [--SP] = (p5:0); [--SP] = I0;[--SP] = I1;[--SP] = I2;[--SP] = I3; [--SP] = B0;[--SP] = B1;[--SP] = B2;[--SP] = B3; [--SP] = M0;[--SP] = M1;[--SP] = M2;[--SP] = M3; [--SP] = L0;[--SP] = L1;[--SP] = L2;[--SP] = L3; /*******************Init Code Section**************************/
/*****Пожалуйста, вставьте код инициализации в эту секцию******/
/*********************Настройка SDRAM**************************/
Setup_SDRAM: P0.L = LO(EBIU_SDRRC); /* SDRAM Refresh Rate Control Register */ P0.H = HI(EBIU_SDRRC); R0 = 0x074A(Z); W[P0] = R0; SSYNC; P0.L = LO(EBIU_SDBCTL); /* SDRAM Memory Bank Control Register */ P0.H = HI(EBIU_SDBCTL); R0 = 0x0001(Z); W[P0] = R0; SSYNC; P0.L = LO(EBIU_SDGCTL); /* SDRAM Memory Global Control Register */ P0.H = HI(EBIU_SDGCTL); R0.L = 0x998D; R0.H = 0x0091; [P0] = R0; SSYNC; /*********************Post-Init Section************************/ L3 = [SP++]; L2 = [SP++]; L1 = [SP++]; L0 = [SP++]; M3 = [SP++]; M2 = [SP++]; M1 = [SP++]; M0 = [SP++]; B3 = [SP++]; B2 = [SP++]; B1 = [SP++]; B0 = [SP++]; I3 = [SP++]; I2 = [SP++]; I1 = [SP++]; I0 = [SP++]; (p5:0) = [SP++]; (r7:0) = [SP++]; RETS = [SP++]; ASTAT = [SP++]; /************************************************************/
RTS;
Потоки загрузки процессора ADSP-BF531, BF532, BF533, BF534, BF536, BF537, BF538, BF539 аналогичны потоку загрузки, используемому загрузчиком ядра второго уровня процессора ADSP-BF535 (подробнее см. раздел "Файлы загрузки, используемые с загрузчиком второго уровня"). Однако, поскольку предыдущие процессоры не реализовали загрузчик второго уровня, их поток загрузки не включает в себя код второй стадии загрузки и связанный с ним 4-байтный заголовок, расположенный поверх кода ядра (kernel code). Здесь также нет 4-байтного глобального заголовка (global header). Аппаратная установка BMODE = 00 для процессоров ADSP-BF531, BF532 и BF533 или BMODE = 000 для процессоров ADSP-BF535 выберет опцию загрузки no-boot. В этом режиме после сброса выполнение кода загрузки, встроенного в процессор, пропускается, и процессор начинает выборку и выполнение инструкций по адресу 0x20000000 (эта память находится в асинхронном банке памяти 0). Процессор подразумевает наличие памяти с шиной 16 бит, где находятся допустимые для выполнения инструкции кода (т. е. по этому адресу должен находиться чистый код, без служебных заголовков загрузки). Чтобы создать корректный файл .ldr, который может быть записан либо в параллельную память flash, либо в параллельную память EPROM, Вы должны модифицировать стандартный файл LDF, чтобы в нем был правильно настроен вектор сброса. Фрагменты следующего кода (листинг 3-6 и листинг 3-7) иллюстрируют требуемые модификации в случае процессора ADSP-BF533. Листинг 3-2. Пример назначений секции (файл LDF). MEMORY { /* Постоянная память инструкций в (Instruction ROM) в Async Bank 0, находящемся вне чипа процессора */ MEM_PROGRAM_ROM { TYPE(ROM) START(0x20000000) END(0x2009FFFF) WIDTH(8) } MEM_DATA_ROM { /* Данные констант в Async Bank 0, находящемся вне чипа процессора */ TYPE(ROM) START(0x200A0000) END(0x200FFFFF) WIDTH(8) } MEM_DATA_RAM { /* Данные SRAM (память, физически находящаяся на кристалле процессора), не будет загружена автоматически */ TYPE(RAM) START(0xFF903000) END(0xFF907FFF) WIDTH(8) } Листинг 3-3. Пример определения сегмента ROM (файл LDF). PROCESSOR p0 { OUTPUT( $COMMAND_LINE_OUTPUT_FILE ) SECTIONS { program_rom { INPUT_SECTION_ALIGN(4) INPUT_SECTIONS( $OBJECTS(rom_code) ) } >MEM_PROGRAM_ROM data_rom { INPUT_SECTION_ALIGN(4) INPUT_SECTIONS( $OBJECTS(rom_data) ) } >MEM_DATA_ROM data_sram { INPUT_SECTION_ALIGN(4) INPUT_SECTIONS( $OBJECTS(ram_data) ) } >MEM_DATA_RAM С файлом LDF, модифицированным таким образом, файлы исходного кода могут теперь получить новые введенные секции, как это показано в листинге 3-4. Листинг 3-4. Пример использования секций (файл исходного кода). .SECTION rom_code; _reset_vector:
l0 = 0; l1 = 0; автоматически */
Встроенный в кристалл код Boot ROM процессоров Blackfin ADSP-BF531, BF532, BF533, BF534, BF536, BF537, BF538, BF539 позволяет загружать следующие диапазоны памяти.
Загрузка в память scratchpad (0xFFB00000) не поддерживается. Код пользователя должен предварительно инициализировать память SDRAM, чтобы неё можно было загрузить какие-либо данные или код. [ADSP-BF535 On-Chip Boot ROM] Рис. 3-6. Процессоры ADSP-BF535: On-Chip Boot ROM. Встроенный в кристалл процессора ADSP-BF535 код Boot ROM делает следующее (см. рис. 3-6): 1. Настраивает режим супервизора (supervisor mode) путем выхода из обработчика прерывания RESET и переходом в прерывание с самым низким приоритетом (IVG15). 2. Проверяет, был ли этот RESET программным сбросом, и если это так, то пропускается вся последовательность загрузки и делается переход в начало памяти L2 (0xF0000000) для выполнение кода. Код Boot ROM выполняет такую проверку тестированием бита 4 регистра конфигурации сброса (System Reset Configuration Register, SYSCR). Если бит 4 не установлен, то код Boot ROM выполняет полную последовательность загрузки. Если бит 4 установлен, то код Boot ROM пропускает последовательность загрузки, и передает управление по адресу 0xF0000000. 3. В случае запуска полной последовательности загрузки (если бит 4 регистра SYSCR не установлен) будут выполнены следующие действия: • Проверка источника загрузки (внешнее устройство памяти, это либо память flash/PROM, либо память SPI) путем чтения BMODE2–0 из регистра SYSCR. Код on-chip boot ROM загружает N из внешней памяти. Эти N байт могут определить размер кода действующего приложения, или это может быть код загрузчика второго уровня, который загрузит код действующего приложения. [Файлы загрузки без загрузчика второго уровня] На рис. 3-11 показана структура файла загрузки для 8-битной flash/PROM или адресуемой 8 или 16 битами микросхемы SPI при загрузке без использования загрузчика второго уровня. Рис. 3-11. Файл загрузки для 8-битной Flash/PROM и SPI без загрузчика второго уровня. На рис. 3-12 показана структура файла загрузки для 16-битной flash/PROM при загрузке без использования загрузчика второго уровня. Рис. 3-12. Файл загрузки для 16-битной Flash/PROM без загрузчика второго уровня. [Файлы загрузки, используемые с загрузчиком второго уровня] На рис. 3-13 показано графическое представление выходного файла загрузки для 8-битной загрузки из flash/PROM и адресуемой 8 или 16 битами загрузки из памяти SPI при наличии загрузчика второго уровня. Рис. 3-13. Файл загрузки для 8-битной Flash/PROM и SPI при использовании загрузчика второго уровня. На рис. 3-14 показано графическое представление выходного файла загрузки для 16-битной загрузки из flash/PROM при наличии загрузчика второго уровня. Figure 3-14. Файл загрузки для 16-разрядной Flash/PROM Boot при использовании загрузчика второго уровня. [Управление загрузкой нескольких приложений (Multi-DXE) ADSP-BF53x и ADSP-BF561] Эта секция статьи не относится к процессорам ADSP-BF535. Здесь описывается, как генерировать файл загрузки и загружать его для более чем одного входного файла .dxe для процессоров ADSP-BF531, BF532, BF533, BF534, BF536, BF537, BF538, BF539 и BF561. Дополнительную информацию по процессорам ADSP-BF561 см. в разделе "ADSP-BF561 Dual-Core Application Management" [1]. Структура файла загрузки ADSP-BF531, BF532, BF533, BF534, BF536, BF537, BF538, BF539 и BF561 и ревизия кристалла (silicon revision) от 0.1 и выше позволяют генерировать файл загрузки и загружать его из внешней памяти для больше чем одного блока исполняемого кода DXE на один процессор. Как показано на рис. 3-20, каждый входной файл с исполняемым кодом (executable file, расширение *.DXE) снабжается 4-байтным заголовком, к котором указано количество байт исполняемого кода, включая заголовки. Эта информация может использоваться для загрузки в процессор определенного, выбранного блока DXE из нескольких. 4-байтный блок, содержащий количество байт, инкапсулирован в 10-байтный заголовок, чтобы сохранить совместимость с silicon revision 0.0. Дополнительную информацию см. во врезке "Заголовки блоков и флаги ADSP-BF531, BF532, BF533, BF534, BF536, BF537, BF538, BF539". Рис. 3-20. Потоки загрузки с несколькими приложениями для процессоров ADSP-BF531, BF532, BF533, BF534, BF536, BF537, BF538, BF539, BF561. Загрузка нескольких исполняемых файлов может быть выполнена по одному из следующих методов. • Можно использовать для утилиты загрузки опцию загрузчика второго уровня (second-stage loader) -l userkernel.dxe. Здесь userkernel.dxe - исполняемый код DXE загрузчика второго уровня. Эта опция позволит Вам использовать свой собственный загрузчик второго уровня. После того, как загрузчик второго уровня будет загружен во внутреннюю память через под управлением on-chip Boot ROM, этот загрузчик второго уровня получит полный контроль над процессом загрузки. Теперь загрузчик второго уровня может использовать счетчики байт в блоках DXE, чтобы загрузить любой выбранный блок DXE (или несколько DXE друг за другом) из внешней памяти. • Можно использовать опцию блока инициализации -init filename.dxe, где filename.dxe имя исполняемого файла DXE, в котором содержится код инициализации (Init Code). Эта опция позволит Вам поменять указатель внешней памяти, и загрузить определенный DXE с задействованием Boot ROM. Достоинство этого метода в том, что свой загрузчик писать не надо, Init Code должен только уметь читать файл загрузки, декодировать в нем заголовки DXE и правильно менять указатель на нужный загружаемый DXE [2]. На процессорах ADSP-BF531 и ADSP-BF561 код инициализации представляет собой подпрограмму, написанную на ассемблере. Ниже на листинге 3-5 приведен пример кода инициализации. Регистры R0 и R3 используются как указатели на внешнюю память, используемые кодом on-chip Boot ROM. Регистр R0 используется для загрузки из flash/PROM, и R3 для загрузки из памяти SPI. В блоке кода инициализации нужно изменить значение R0 или R3 так, чтобы они указывали на место во внешней памяти, откуда начинается код нужного приложения. После того, как процессор вернет управление из кода инициализации обратно в код Boot ROM, код Boot ROM продолжит загружать байты с места, указанного регистрами R0 или R3. Листинг 3-5. Пример Init Code для загрузки в сценарии Multiple .dxe. #include < defBF532.h >
.SECTION program;
/*******Pre-Init Section***************************************/ [--SP] = ASTAT; [--SP] = RETS; [--SP] = (r7:0); [--SP] = (p5:0); [--SP] = I0;[--SP] = I1;[--SP] = I2;[--SP] = I3; [--SP] = B0;[--SP] = B1;[--SP] = B2;[--SP] = B3; [--SP] = M0;[--SP] = M1;[--SP] = M2;[--SP] = M3; [--SP] = L0;[--SP] = L1;[--SP] = L2;[--SP] = L3; /**************************************************************/
/*******Init Code Section**************************************
R0.H = старшая часть адреса места положения DXE
(R0 для flash/PROM boot, R3 для SPI boot)
R0.L = младшая часть адреса места положения DXE
(R0 для flash/PROM boot, R3 для SPI boot)
***************************************************************/
/*******Post-Init Section**************************************/ L3 = [SP++]; L2 = [SP++]; L1 = [SP++]; L0 = [SP++]; M3 = [SP++]; M2 = [SP++]; M1 = [SP++]; M0 = [SP++]; B3 = [SP++]; B2 = [SP++]; B1 = [SP++]; B0 = [SP++]; I3 = [SP++]; I2 = [SP++]; I1 = [SP++]; I0 = [SP++]; (p5:0) = [SP++]; /* УБЕДИТЕСЬ, ЧТО СЛУЧАЙНО НЕ ВОССТАНОВИЛИ R0 для flash/PROM Boot, или R3 для SPI Boot */ (r7:0) = [SP++]; RETS = [SP++]; ASTAT = [SP++]; /**************************************************************/
RTS;
[Руководство по использованию загрузчика процессоров ADSP-BF53x/BF561] Работа утилиты загрузки elfloader.exe зависит от опций, которые управляют процедурой обработки исполняемых файлов DXE. Вы выбираете такие возможности, как режим загрузки (boot mode), загрузка ядра (boot kernel), формат выходного файла и т. д. Опции указываются для утилиты загрузки через командную строку, или опосредованно через графический интерфейс диалога редактирования свойств проекта VisualDSP++ (Project Options -> Load). Раздел Load свойств проекта состоит из нескольких подразделов. Когда Вы выбрали раздел Load, то в нем уже будут установлены некоторые установки по умолчанию для загрузчика выбранного процессора. Настройки в разделе Load соответствуют опциям, которые будут указаны в командной строке утилиты загрузки elfloader.exe. Подсмотреть полное содержимое командной строки можно в лог-файле процесса сборки, см. подкаталог Release (или Debug), файл имя_проекта.log. Далее в нескольких секциях будет описано, как генерировать загружаемый и не загружаемый файл загрузки: • Использование командной строки утилиты загрузки Blackfin. [Синтаксис командной строки elfloader.exe] Утилита загрузки ADSP-BF5xx Blackfin использует loader следующий общий синтаксис командной строки. Для одного входного файла: elfloader inputfile -proc processor [-опция ...] Для нескольких входных файлов: elfloader inputfile1 inputfile2 ... -proc processor [-опция ...] Здесь указаны параметры: inputfile - это имя файла исполняемого кода (с расширением .dxe), который должен быть обработан, чтобы в результате получился один загружаемый (boot-loadable) или не загружаемый (non-bootable) файл. Имя входного файла может включать имя диска (C:, D:, и т. п.) и полный путь до каталога, где находится файл (в составе пути можно также применять . и ..). Для систем с несколькими процессорами или в сценарии загрузки Multi-DXE указываются несколько входных файлов .dxe. Укажите имена входных файлов в том порядке, в котором Вы хотите, чтобы утилита загрузки их обработала. Заключайте длинные имена файлов (и имена файлов с пробелами) в двойные кавычки ("long file name"). -proc processor - здесь указывается модель процессора (например, -proc ADSP-BF532), для которого будет построен файл загрузки. Если Вы разрабатываете файл загрузки для многопроцессорной системы, то для каждого входного файла .dxe укажите модель процессора. -опция ... - здесь указывается одна или несколько обрабатываемых опций. Опции выбирают операции и режимы для утилиты загрузки. Опции командной строки могут появляться в командной строке в любом порядке, за исключением порядка следования входных файлов для многопроцессорной системы. Для систем со сценарием загрузки Multi-DXE утилита загрузки обрабатывает входные файлы в том порядке, в каком они были указаны в командной строке. Пути поиска файлов. Это важный фактор для обработки файла загрузки. Утилита загрузки поддерживает относительные (т. е. относительно текущего каталога, т. е. в составе пути можно применять . и ..) и абсолютные имена каталогов, каталоги по умолчанию и каталоги, выбранные пользователем. Подробнее про обработку путей поиска см. [1], раздел "File Searches" на странице 1-17. Расширения файлов. Некоторые опции утилиты загрузки принимают имя файла в качестве параметра опции. В таблице 3-9 перечислены ожидаемые типы файла, имена и расширения файла. Таблица 3-9. Расширения файлов.
В некоторых случаях утилита загрузки ожидает входные файлы оверлея (overlay input files) с расширением .ovl, входные файлы обшей памяти (shared memory input files) с расширением .sm, или и те и другие, однако не ожидается появление этих файлов в командной строке или где-нибудь в разделе Load свойств проекта. Утилита загрузки ищет эти файлы в каталоге, связанном с файлами .dxe, в текущем рабочем каталоге, или в каталоге, указанном в файле .ldf. [Общие опции командной строки elfloader.exe] Таблица 3-10. Основные опции командной утилиты Blackfin Loader (elfloader.exe).
Таблица 3-11. Значения -pFlag для процессоров ADSP-BF531/BF532/BF533(1).
Примечание (1): для процессоров ADSP-BF531, BF532, BF533 бит RESVECT (бит 2 в поле флагов заголовка блока) всегда очищен (==0). Таблица 3-12. Значения -pFlag для процессоров ADSP-BF534, BF536, BF537(2).
Примечание (2): для процессоров ADSP-BF534, BF536, BF537 бит RESVECT (бит 2 в поле флагов заголовка блока) всегда установлен (==1). Таблица 3-13. Значения -pFlag для процессоров ADSP-BF538, BF539(3).
Примечание (3): для процессоров ADSP-BF538, BF539 бит RESVECT (бит 2 в поле флагов заголовка блока) всегда установлен (==1). Все настройки опций загрузки проекта делаются через диалог редактирования свойств проекта (меню Project -> Project Options...). Сначала нужно выбрать генерацию файла загрузки Loader file (.ldr) в качестве выходного типа компиляции проекта Вашего приложения (главный раздел опций Project, блок Target, параметр Type: Loader file). Аналогичный выбор делается в мастере (VisualDSP++ Project Wizard) при создании проекта приложения. После этого можно редактировать опции в разделе Load свойств проекта. Рис. 3-26. Опции Load свойств проекта для процессоров ADSP-BF535. Настройки раздела Load в дереве опций проекта состоят из нескольких страниц. Когда Вы откроете страницу Load -> Options (которая также называется страницей свойств загрузчика, "loader property page"), просмотрите настройки по умолчанию для загрузки. Как показано в примере на рис. 3-26 значения загрузки по умолчанию для процессора ADSP-BF535 рассчитаны на загрузку из PROM. Опции диалога имеют аналоги опций командной строки утилиты загрузки elfloader.exe. Обратитесь к таблице 3-10 для получения подробной информации по опциям командной строки утилиты загрузки. Используя графический интерфейс, Вы можете выбрать или модифицировать настройки, управляющие генерацией файла загрузки. В таблице 3-14 описывает каждый элемент управления диалога и соответствующую ему настройку. Когда Вы закончили настройку, кликните на кнопку OK для завершения настройки опций загрузки. Таблица 3-14. Базовые настройки страницы Load свойств проекта для процессоров ADSP-BF53x/BF561.
В отличие от утилиты загрузки, сплиттер никак не форматирует данных приложения, когда преобразует файл исполняемого кода .dxe в файл загрузки .ldr. Он только поставляет на выходе сырые данные. Какие будут обработаны данные - то ли исполняемый код приложения, то ли данные приложения - зависит от команды TYPE() файла LDF. Секции, декларированные с командой TYPE(RAM), будут потребляться утилитой загрузки, а секции, декларированные через TYPE(ROM), будут потребляться сплиттером. На рис. 3-29 показан диалог настройки Load -> Splitter, где настраиваются опции ROM-сплиттера. Когда не поставлена галочка Enable ROM splitter, будут обработаны только секции TYPE(RAM), и все сегменты TYPE(ROM) будут игнорированы утилитой загрузки. Если галочка Enable ROM splitter установлена, то секции TYPE(RAM) игнорируются, и утилитой сплиттера будут обработаны секции TYPE(ROM). Рис. 3-29. Страница настроек проекта в разделе Load -> Splitter для процессоров ADSP-BF533. Поле Mask Address маскирует все биты адреса EPROM, которые больше или равны указанному числу. Например, Mask Address = 29 (значение по умолчанию) маскирует все биты выше и включая A29 (операция AND между адресом и константой 0x1FFFFFFF). Таким образом, адрес 0x20000000 становится равным 0x00000000. Допустимо указывать целый числа от 0 до 32, однако на базе Вашего конкретного входного файла значение может быть в подмножестве от [0, 32]. Для выбора варианта без загрузки внешние выводы процессора BMODEx должны быть притянуты к состоянию 000 для процессоров ADSP-BF535 или 00 для процессоров ADSP-BF531, ADSP-BF532 и ADSP-BF533. В этом режиме работы пропускается встроенный в кристалл код загрузки Boot ROM, и процессор сразу приступает к выборке и выполнению команд с адреса 0x20000000, находящихся в асинхронном банке 0. Процессор подразумевает, что подключена 16-битная память, где записаны допустимые инструкции (команды) для процессора. Чтобы создать корректный файл .ldr, который можно записать либо в устройство параллельной памяти flash, либо параллельной памяти EPROM, Вы должны изменить стандартный файл LDF, чтобы вектор сброса был размещен соответствующим образом. Следующие фрагменты кода (листинги 3-6 .. 3-7) показывают необходимые модификации в случае процессора ADSP-BF533. Листинг 3-6. Пример назначения секций (файл LDF). MEMORY { /* ROM инструкций в Async Bank 0, находящееся вне чипа */ MEM_PROGRAM_ROM { TYPE(ROM) START(0x20000000) END(0x2009FFFF) WIDTH(8) } /* Данные констант в Async Bank 0, находящиеся вне чипа */ MEM_DATA_ROM { TYPE(ROM) START(0x200A0000) END(0x200FFFFF) WIDTH(8) } /* Данные SRAM, находящиеся на кристалле, не могут быть загружены автоматически */ MEM_DATA_RAM { TYPE(RAM) START(0xFF903000) END(0xFF907FFF) WIDTH(8) } ... Листинг 3-7. Пример определений сегмента ROM (файл LDF). PROCESSOR p0 { OUTPUT( $COMMAND_LINE_OUTPUT_FILE ) SECTIONS { program_rom { INPUT_SECTION_ALIGN(4) INPUT_SECTIONS( $OBJECTS(rom_code) ) } >MEM_PROGRAM_ROM data_rom { INPUT_SECTION_ALIGN(4) INPUT_SECTIONS( $OBJECTS(rom_data) ) } >MEM_DATA_ROM data_sram { INPUT_SECTION_ALIGN(4) INPUT_SECTIONS( $OBJECTS(ram_data) ) } >MEM_DATA_RAM ... С файлом LDF, измененным таким образом, исходные файлы могут получить в распоряжение новые созданные секции, как это показано в листинге 3-8. Листинг 3-8. Пример использования секций (файл исходного кода). .SECTION rom_code; _reset_vector: l0 = 0; l1 = 0; l2 = 0; l3 = 0; /* В этом месте может быть код для начальных настроек, и далее код приложения */ /* . . . */ .SECTION rom_data; .VAR myconst x = 0xdeadbeef; /* . . . */ .SECTION ram_data; .VAR myvar y; /* обратите внимание, что переменная y не может быть автоматически инициализирована */
[Практические примеры расшифровки дампов файлов загрузки] Из всего вышесказанного следует, что модули исполняемого кода *.dxe можно по отдельности преобразовывать в двоичные файлы, и записывать в любое произвольное место памяти, откуда происходит загрузка (загрузочная память). Т. е. двоичный код файлов загрузки никак не привязан к адресам загрузочной памяти, в ней можно сколько угодно разместить файлов загрузки, и в любом порядке, и даже с пропусками между ними. Главное условие - правильно управлять кодом Boot ROM, инициализируя регистр R0 (или R3, в зависимости от типа используемой загрузочной памяти) нужным абсолютным адресом загрузочной памяти. Ниже будут рассмотрены несколько примеров дампов файлов загрузки. В этих 3 примерах исполняемый код из файлов с расширением *.dxe преобразуются в загрузочные файлы с расширением *.ldr в двоичном формате с помощью elfloader.exe, вызываемой из командной строки. Командная строка elfloader: @rem Генерация LDR-файла для Init Code в формате BIN: @"C:\Program Files (x86)\Analog Devices\VisualDSP 5.0\elfloader.exe" .\Init_Sdram\Release\sdram.dxe -b Flash -f binary -Width 16 -o .\bin\sdram.ldr -si-revision 0.5 -proc ADSP-BF538 -MM В этом примере код инициализации SDRAM скомпилирован как обычная программа, без добавления кода инициализации (опция -init отсутствует). Это сделано только в целях демонстрации, потому что проект Init Code дает маленький, удобный для рассмотрения двоичный код. В результатом работы утилиты elfloader будет файл загрузки, который показан на скриншоте ниже. Отдельные части файла загрузки для наглядности выделены разными цветами. Давайте рассмотрим, что они означают.
Командная строка elfloader: @rem Генерация LDR-файла для Init Code в формате BIN: @"C:\Program Files (x86)\Analog Devices\VisualDSP 5.0\elfloader.exe" -init .\Init_Sdram\Release\sdram.dxe -b Flash -f binary -Width 16 -o .\bin\sdram-init-code.ldr -si-revision 0.5 -proc ADSP-BF538 -MM В этом примере код инициализации SDRAM скомпилирован как Init Code (с опцией -init), без добавления кода основной программы. Этот пример полезен, потому что может использоваться в реальных проектах.
До настоящего момента все почти совпадает с предыдущим примером (Пример 1), но в этом примере появляется еще и последний блок 2.
Командная строка elfloader: @rem Генерация совмещенного Init Code + основная программа в формате BIN: @"C:\Program Files (x86)\Analog Devices\VisualDSP 5.0\elfloader.exe" .\BF538\Release\main.dxe -b Flash -f binary -Width 16 -init .\Init_Sdram\Release\sdram.dxe -o .\bin\sdram-init-code-and-main.ldr -si-revision 0.5 -proc ADSP-BF538 -MM В этом примере в выходной файл загрузки попало два модуля DXE: Init Code (sdram.dxe, DXE0) и код основной программы (main.dxe, DXE1).
Пока все почти полностью совпадает с предыдущим примером (Пример 2), это были блоки исполняемого модуля Init Code (DXE0). В этом же примере в файл загрузки добавлен также код основной программы, поэтому далее идут блоки основной программы (DXE1).
В этом примере показан код, который возвращает управление в Boot ROM процессора, передавая в регистре R0 адрес начала DXE, который следует загружать. Загрузка происходит из памяти FLASH, поэтому для адреса используется регистр R0 (для загрузки по SPI для адреса используется регистр R3). Поскольку FLASH находится по абсолютному адресу 0x20000000 в адресном пространстве Blackfin, то в R0 записывается адрес 0x20004000, который указывает место положения загружаемого кода DXE. Обратите внимание, как происходит на выходе коррекция стека, чтобы не затиралось установленное значение регистра R0. #include < defBF532.h >
.section program;
.EXTERN _InitSDRAM;
start: [--SP] = ASTAT; [--SP] = RETS; [--SP] = (r7:0); [--SP] = (p5:0); [--SP] = I0; [--SP] = I1; [--SP] = I2; [--SP] = I3; [--SP] = B0; [--SP] = B1; [--SP] = B2; [--SP] = B3; [--SP] = M0; [--SP] = M1; [--SP] = M2; [--SP] = M3; [--SP] = L0; [--SP] = L1; [--SP] = L2; [--SP] = L3; CALL _InitSDRAM; R0.H = 0x2000; R0.L = 0x4000; L3 = [SP++]; L2 = [SP++]; L1 = [SP++]; L0 = [SP++]; M3 = [SP++]; M2 = [SP++]; M1 = [SP++]; M0 = [SP++]; B3 = [SP++]; B2 = [SP++]; B1 = [SP++]; B0 = [SP++]; I3 = [SP++]; I2 = [SP++]; I1 = [SP++]; I0 = [SP++]; (p5:0) = [SP++]; //(r7:0) = [SP++]; (r7:1) = [SP++]; RETS = [SP++]; // Модификация SP на 1 в случае R0 (загрузка из FLASH) RETS = [SP++]; ASTAT = [SP++]; END:
RTS;
Размещение кода основной программы по известному абсолютному адресу загрузочной памяти удобно для обновления программы. В нашем примере это адрес 0x4000, который соответствует следующему сектору памяти FLASH (размер сектора равен 0x4000, т. е. 16384 байта). Этот адрес выбран не случайно - как известно, память FLASH записывается сразу секторами. Т. е. загрузчик, который обновляет основную программу, вместе с кодом инициализации записан в секторе 0 (адреса 0x0000..0x3FFF), и он при обновлении не перетирается. Код основной программы находится в секторах остальной памяти, начиная с сектора 1 (т. е. с адреса 0x4000), и перепрошивка основной программы никак не запортит код загрузчика. [Ссылки] 1. VisualDSP++ 5.0 Loader and Utilities Manual site:analog.com. |