AN3927 Freescale USB Mass Storage Device Bootloader Application Note Rev. 0, 11/2009 (перевод)
4. Использование загрузчика
Этот раздел описывают использование загрузчика, включая демонстрацию работы с использованием наборов разработчика и интеграцию с другими приложениями.
4.1 Предупреждение перекрёстных вызовов
Очень важно понимать, что хороший загрузчик может взаимодействовать с целевым приложением только через абсолютные адреса. В этом случае вектор пользователя, указывающий на точку входа приложения, расположен по заранее известному абсолютному адресу. Загрузчик "знает" его и, переключаясь в режим целевого приложения, просто переходит по означенному адресу (вектору пользователя), который, в свою очередь, передаёт управление на начало собственно приложения. Это принципиальный момент, так как каждый раз при пересборке приложения компоновщик может изменить адрес точки входа целевого приложения. Загрузчику не надо знать новый адрес, потому что вектор пользователя всегда располагается по одному и тому же адресу и всегда содержит адрес точки входа целевого приложения. Забота о корректности объявления вектора и адреса целевого приложения ложится на конечного пользователя. Этот процесс описывается в статье далее.
Перекрёстные вызовы - ситуация при которой загрузчик или целевое приложение вызывает функцию из чужого адресного пространства без использования абсолютных адресов. Такое развитие событий совершенно недопустимо. В исходных текстах, сопровождающих данную статью, присутствует пример в котором загрузчик и целевое приложение объединяются в единый проект. Использование единого проекта имеет то преимущество, что в процессе производства загрузчик и приложение записываются в устройство в едином цикле записи программной памяти. Отладка единого проекта проще. Тем не менее, использование единого проекта допускает появление перекрёстных вызовов, чреватых серьёзными неприятностями.
Рассмотрим такой вариант развития событий:
Загрузчик использует библиотеку и собирается в рамках единого проекта с приложением, использующим ту же библиотеку. При сборке версии "RevA" программного обеспечения используемая загрузчиком библиотечная функция " My_func() " располагается компоновщиком в области загрузчика и получает адрес 0x100 . Целевое приложение также использует функцию " My_func() " и вызывает её из области кода загрузчика посредством перекрёстного вызова. Версия "RevA" устройства переходит в фазу массового производства и всё работает отлично. Через какое-то время программа модернизируется до версии "RevB". В момент сборки проекта компоновщик помещает функцию " My_func() " по адресу 0x105 . Загрузчик и целевое приложение собираются вместе, поэтому и эта версия работает как надо. А теперь попытаемся модернизировать целевую программу до версии "RevB" с помощью загрузчика версии "RevA". Приложение обновляется до версии "RevB", а загрузчик по-прежнему имеет версию "RevA". Когда целевое приложение делает перекрёстный вызов функции " My_func() ", управление передаётся коду по адресу 0x105 , но в загрузчике версии "RevA" " My_func() " расположени по адресу 0x100 и программа улетает в космос.
Данный пример показывает причины по которым следует всячески избегать перекрёстных вызовов, допуская вызовы только по абсолютным адресам.
Единственным местом взаимодействия загрузчика и целевой программы является вызов последней посредством выбора адреса точки входа из вектора пользователя. Версия загрузчика для MC9S08 объединяется с целевым приложением иначе, чем в версиях для ColdFire, которые включают загрузчик в виде исходных текстов или библиотеки. В случае MC9S08 и загрузчик, и целевое приложение используют библиотеку "ansiis.lib". Для предупреждения перекрёстных вызовов загрузчик для MC9S08 собирается как отдельный проект. Получившийся на выходе файл S19 включается в проект целевой программы командой " HEXFILE " в PRM-файле компоновщика. В таком варианте подключения компоновщик остаётся в неведении относительно наличия библиотечных функций в коде загрузчика и включает их в состав целевой программы, полностью исключая возможность перекрёстных вызовов. Таким образом проект приложения получает дополнительный плюс от единого цикла записи целевого приложения и загрузчика в устройство при массовом производстве.
В процессе сборки загрузчика и целевой программы, как единого проекта, следует проводить тестирование на наличие перекрёстный вызовов. Простым методом тестирования на отсутствие вызовов загрузчиком кода из прикладной области является стирание приложения и проверка загрузчика на работоспособность. Загрузчик самодостаточен и должен работать в отсутствие стороннего кода. Для использования данного метода запишите в устройство единый проект, после чего сотрите область программной памяти целевого приложения. Это можно сделать вручную или с использованием отладчика. В варианте с отладчиком поставьте точку останова сразу после того, как загрузчик стирает приложение в процессе его обновления. Запустите процедуру обновления целевой программы и сбросьте контроллер, по достижении точки останова. Загрузчик должен работать нормально. Невозможность нормальной работы означает, что загрузчик вызывает код из прикладной области. Используйте отладчик для обнаружени проблемных мест и поправьте код.
Проверьте, что целевая программа не использует код из области загрузчика. Один из способов - внимательный просмотр ".MAP" файла после компоновки. Проверьте все имена функций, расположенных в области загрузчика, и убедитесь, что данные функции не используются целевой программой. Убедитесь, что загрузчик не использует общих библиотек. Проверьте инициализационный код, так как используемые им процедуры могут иметь одинаковые имена в областях загрузчика и целевого приложения. Другим методом проверки на перекрёстные вызовы является стирание области загрузчика, но этот метод довольно сложен, так как в ней расположена и таблица векторов прерываний.
4.2 Использование загрузчика с отладочными платами
Прилагаемые проекты для среды разработки CodeWarrior содержат примеры тестов для запуска на отладочных платах M52259DEMO и DEMOJM. Выберите, для начала, вычислительное ядро, соответствующее вашей отладочной плате. Изучите сопроводительную документацию на плату на предмет начала работы и процедуры записи программной памяти из среды CodeWarrior. После начального ознакомления со средой и платой проделайте следующие шаги:
-
Аппаратура должна быть настроена для работы с шиной USB. Данный режим соответствует заводским установкам всех переключателей. Подробности можно узнать в сопроводительной документации. Если вы используете плату DEMOJM убедитесь, что к плате подключён правильный процессорный модуль (MC9S08 или Coldfire V1). Подсоедините USB кабель к плате и компьютеру.
-
Запустите CodeWarrior и откройте один из файлов проекта ".MCP", соответствующий какому-либо примеру. Для Coldfire V2 убедитесь, что в свойствах проекта выбрана опция "52259 Example Flash". Соберите проект и запишите его в программную память.
-
Перезапустите плату. Один из светодиодов должен мигать, демонстрируя активность программы.
-
Перейдите в режим загрузчика, нажав и удерживая указанную ниже кнопку с последующим кратковременным нажатием на кнопку "Reset". На плате DEMOJM для перехода используется кнопка PTG0, для M52259DEMO - SW1. Плата перезапустится в режиме загрузчика, пройдёт процедуру опознания и появится в управляющем компьютере в виде нового диска. Рисунок 8 демонстрирует "диск" загрузчика в Windows XP. Обратите внимание на метку тома ("BOOTLOADER") и файл состояния ("READY.TXT"). Устройство готово к приёму файла в формате S19.
Рисунок 8. Опознанный операционной системой "диск" загрузчика -
Откройте каталог "\S19 files" и скопируйте файл S19, cоответствующий выбранному вычислительному ядру, на "диск" загрузчика. Вы можете выбрать файл проекта, управляющий другим светодиодом, или пример HID, собранный с использованием стека компании CMX.
-
Некоторые операционные системы, такие как "Linux Fedora 8", не записывают файл на диск до момента размонтирования диска из системы. Если вы используете одну из таких систем, размонтируйте диск загрузчика.
-
Проверьте файл состояния. После завершения передачи файла "диск" загрузчика пропадает и через несколько секунд - после проведения процедуры повторного опознания - появляется вновь. Проверьте, что "диск" загрузчика содержит файл "SUCCESS.TXT", который означает, что обновление памяти программ завершено успешно.
Рисунок 9. Загрузчик сообщает об успешном завершении операции -
Перезагрузите отладочную плату кнопкой "Reset". Должно запуститься новое приложение. Если вы выбрали пример CMX HID, то на экране управляющего компьютера указатель мыши начнёт покачиваться, другие примеры мигают светодиодами на плате.
Вы можете повторить данную процедуру, начиная с шага 4, для другого примера.
4.3 Создание нового проекта с загрузчиком
Загрузчик готов ко включению в состав других приложений. Новый проект легче начинать, используя предложенные примеры в качестве отправной точки. Включение загрузчика в существующий проект сложнее и требует некоторых дополнительный шагов, описываемых в следующих разделах.
Если вы принимаетесь за новый проект, начните процесс с изменения приводимых примеров под новые задачи. Примеры уже содержат в своём составе загрузчик и необходимые стартовые процедуры. Вы можете добавлять новые возможности в теле функции " main() " файла "main.c". Единственное необходимое изменение - правка таблицы векторов прерываний. Процедура переадресации таблицы векторов различна для различных версий вычислительного ядра и детализируется ниже.
4.3.1 Изменение таблицы векторов для Coldfire V2
Архитектура Coldfire V2 позволяет изменять расположение таблицы векторов. Базовый адрес таблицы содержится в регистре VBR и при необходимости может быть изменён. После сброса адрес в регистре VBR равен нулю и таблица векторов располагается в защищённой области программной памяти загрузчика. Таким образом, вектор сброса находится по адресу 0x00000004 в той же защищённой памяти и указывает на код загрузчика. После запуска целевое приложение может изменить содержимое VBR и переадресовать таблицу векторов в оперативную память, а затем заполнить её своими векторами.
|
Рисунок 10 демонстрирует код, используемый в примерах под Coldfire V2 для переназначения таблицы в оперативную память и её заполнения. Первая строка использует функцию " mcf5xxx_wr_vbr() " для переадресации таблицы в оперативную память. Вторая строка использует функцию " mcf5xxx_set_handler() " для установки вектора в таблицу. В приведённом примере вектор относится к переодическому прерыванию от таймера PIT0 и обработчик прерывания называется " pit0_isr() ". В MCF52259 PIT0 занимает 55-й вектор первого контроллера прерываний (Interrupt Controller0). Таким образом, номер вектора равен 64 + 55.
Когда вы изменяете таблицу векторов, используйте функцию " mcf5xxx_set_handler() " для установки новых обработчиков прерываний.
4.3.2 Изменение таблицы векторов для Coldfire V1
Архитектура Coldfire V1 позволяет изменять расположение таблицы векторов. Базовый адрес таблицы содержится в регистре VBR и при необходимости может быть изменён. После сброса адрес в регистре VBR равен нулю и таблица векторов располагается в защищённой области программной памяти загрузчика. Таким образом, вектор сброса находится по адресу 0x00000004 в той же защищённой памяти и указывает на код загрузчика. После запуска целевое приложение может изменить содержимое VBR и переадресовать таблицу векторов в оперативную память, а затем заполнить её адресами своих обработчиков.
Приложение для Coldfire V1 сохраняет свою собственную таблицу в программной памяти. На рисунке 11 изображена часть сохранённой в программной памяти таблицы векторов, названная " RAM_vector ". Целиком таблица приводится в приложении "Appendix F - hid_main.c из примера CMX для Coldfire V1". Тот факт, что таблица расположена в области целевого приложения, позволяет изменять её содержимое при обновлении памяти программ.
|
В начале работы целевого приложения первые две линии кода загружают в VBR значение, переадресующее таблицу векторов в оперативную память. После этого в цикле происходит копирование таблицы из программной памяти в оперативную.
|
Для новой программы нужно изменить в массиве " RAM_vector " содержимое соответствующего вектора.
4.3.3 Изменение таблицы векторов для MC9S08
В отличие от ColdFire, MC9S08 не может переадресовывать таблицу векторов в оперативную память. Вместо этого таблица векторов в области загрузчика указывает на таблицу переадресации, расположенную по известному (на момент компиляции) адресу, в области целевого приложения. На рисунке 13 изображена теблица переадресации " UserJumpVectors " из файла "main.c", расположенная по адресу " VectorAddressTableAddress ". Обратите внимание на константу " 0xCC ", стоящую перед каждым адресом в таблице. Это шестнадцатиричное значение инструкции " JMP " для MC9S08.
|
Таблица векторов прерываний " BootIntVectors " (рис. 14) объявляется в файле "Redirect_Vectors_S08.c" и располагается в области загрузчика. Каждый вектор в таблице указывает на соответствующий ему вектор в таблице " UserJumpVectors " (рис. 13). Когда происходит прерывание контроллер считывает содержимое соответствующего вектора из таблицы " BootIntVectors " и загружает его в указатель команд, после чего выбирает следующую команду уже из таблицы " UserJumpVectors ", расположенной в области целевого приложения. Эта команда - " 0xCC " - инструкция " JMP ", за которой следует адрес обработчика прерывания.
|
Для нового проекта заполните массив векторов " UserJumpVectors " в модуле "main.c" реальными адресами обработчиков прерываний.
- блог пользователя teap0t
- 54181 просмотр
Новые записи в блогах
- Устранение дребезга контактов на основе вертикальных счетчиков
- Диагностика Imprecise Bus Faults в микроконтроллерах Cortex-M3/M4/M4F
- Self-powered камера
- Фоновый модулятор: беспроводная связь из ничего (перевод)
- Texas Instruments Analog Applications Journal SLYT612 "Снижение искажений в аналоговых КМОП ключах" (перевод)
- USB MSD. Часть 6. Команды SCSI (перевод)
- USB MSD. Часть 3. USB класс накопителей данных (перевод)
- Texas Instruments Application Report SBAA042 "Кодовые схемы, используемые в аналогово-цифровых преобразователях" (перевод)
- 10 принципов правильного интерфейса
- Релиз SDK на русский микропроцессор КРОЛИК
Recent comments
5 лет 20 недель назад
5 лет 35 недель назад
5 лет 45 недель назад
5 лет 47 недель назад
6 лет 3 недели назад
6 лет 27 недель назад
6 лет 28 недель назад
6 лет 31 неделя назад
6 лет 42 недели назад
7 лет 22 недели назад