Микроконтроллер

Программа в STM 32

Скелетная программа

 

Программа в STM 32. В этой статье я расскажу о процессе создания, компиляции, загрузки, выполнения и отладки программы с помощью платы STM32 VL Discovery и инструментов Sourcery. Для настольных компьютеров стандартным первым примером является программа

hello world ! :

который может быть скомпилирован и выполнен за один шаг

 

Эта простая программа скрывает огромное количество сложностей, начиная от автоматического включения стандартных библиотек и заканчивая связыванием в коде запуска и взаимодействием с миром через оболочку. Во встроенном мире

большая часть этой сложности видна программисту, и, следовательно, необходимо немного больше понимать среду выполнения даже для самой простой программы (а  привет, мир  — не простая программа).

В мире встраиваемых систем самая простая программа на C — это та, которая не требует никаких стандартных библиотек и не взаимодействует с внешним миром:

 

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

Хотя мы не можем напрямую наблюдать за выполнением этой программы, мы можем подключить отладчик и контролировать ее выполнение с помощью точек останова и точек наблюдения. Обратите внимание, что в этой программе есть две глобальные переменные (выключенный) один из которых инициализирован нулем, а другой имеет ненулевой инициализатор. Более того, программа имеет единственную процедуру, отличную от main, и многократно вызывает эту процедуру.

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

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

Демонстрационная программа

 

Процесс компиляции программы для встраиваемых процессоров, таких как STM32, может включать довольно много деталей, таких как флаги компиляции для конкретного процессора, пути к инструментам компиляции и т. д. Как правило, лучший подход — создать скрипт  make , который будет управлять процессом. . Вместо того, чтобы углубляться в этот уровень, вам следует загрузить шаблон кода, как описано в Разделе 1.2, который содержит необходимые сценарии.

Чтобы построить этот пример в вашей системе, вам нужно будет изменить две константы в файле Makefile.common — ИНСТРУМЕНТЫ который должен указывать в каталог bin вашей установки Sourcery который должен указывать на вашу установку стандартной периферийной библиотеки STM32.

Чтобы скомпилировать эту программу, измените каталоги на каталог Demo и выполните make . Это должно создать файл с именем Демо.ELF который содержит скомпилированный

двоичный файл.

Чтобы загрузить и выполнить этот бинарный файл, нам понадобятся две программы — gdb (arm-none-eabi-gdb), которая является частью дистрибутива Sourcery, и st-util, который предоставляет сервер gdb, который взаимодействует с

заглушкой отладки stlink на плате обнаружения через соединение USB. Мы описали, как установить st-util в разделе 1.2. Я предполагаю, что вы установили и проверили соединение. Вы должны открыть два окна терминала. В одном выполните:

Примечание. В более ранних версиях st-util требуется другая последовательность запуска.

 

                                                                 st-util 4242 /dev/stlink

который запускает сервер gdb, прослушивающий порт 4242. Вы должны увидеть следующий вывод:

В другом окне терминала выполните (строки, начинающиеся с  (gdb) , находятся в отладчике):

Команда  target  должна подключиться к серверу gdb через порт 4242; команда загрузки загружает исполняемый файл во флэш-память STM32. Следующие две команды устанавливают точки останова в главный вкл. процедуры, а команда

continue выполняется до тех пор, пока не произойдет следующая точка останова. Затем вы можете повторно выполнить и проверить значения:

 

Упражнение 3.1 ГБД на STM32

Поэкспериментируйте с GDB, чтобы протестировать различные команды, такие как следующие:

1. Распечатать текущие значения регистров (например, напечатать /x $sp отображает указатель стека в шестнадцатеричном формате.

2. Попробуйте установить точку наблюдения ная.

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

Сделать скрипты

В то время как загрузка и выполнение двоичного файла сравнительно просты, процесс создания двоичного файла не так прост. Инструменты компиляции требуют неочевидных опций, библиотеки прошивки STM32 требуют различных определений, а

для генерации исполняемого файла из двоичных файлов требуется специальный скрипт компоновщика . Кроме того,  main.c  сама по себе не является законченной  программой — всегда есть шаги, необходимые для инициализации переменных и

настройки среды выполнения. В мире Unix каждая программа на C связана с  crt0.o для выполнения этой инициализации. Во встроенном мире необходима

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

Файлы make, включенные в демонстрационную программу, разделены на две части. Makefile.common делает тяжелую работу и может быть повторно использован для других проектов, в то время как Демо/Makefile зависит от проекта. Действительно, единственная функция make-файла конкретного проекта — определить необходимые объектные файлы и их зависимости. Makefile для демонстрационного проекта показан в листинге 3.1. Это можно изменить для других проектов, добавив дополнительные объекты и изменив флаги компиляции. Переменная ШАБЛОН следует изменить, чтобы он указывал на каталог шаблона.

Большинство Makefile.common определяет пути к инструментам и библиотекам. Единственными примечательными частями этого файла являются специфичные для процессора определения и флаги

компиляции. Определения, специфичные для процессора, включают скрипт компоновщика. LDSCRIPT который информирует компоновщика о правильном сценарии компоновки для использования — мы

кратко обсудим этот файл в следующем разделе. Тип процессора определяетТИП который управляет условной компиляцией библиотек прошивки, и два файла запуска

– один универсальный (system_stm32f10x.o) и один специфичный для процессоров STM32 Value Line (startup_stm32f10x.o). Библиотеки STM32 предназначены для

поддержки нескольких членов семейства STM32, требуя различных переключателей времени компиляции. Процессор на плате STM32 VL Discovery является частью  линии

значений средней плотности  — это отражено в определении времени компиляции. STM32F10X_MD_VL. Программа в STM 32

 

Флаги mcpu=cortex m3 mthumb информировать gcc о основных процессах

сор.

 

Модель памяти STM32 и последовательность загрузки

 

Память процессоров STM32 состоит из двух основных областей: флэш-память (эффективно только для чтения) начинается с адреса 0x08000000, а статическая оперативная память (чтение/ запись) начинается с адреса 0x20000000. Размер этих областей зависит от процессора. Когда программа выполняется, машинный код (обычно) находится во флэш-памяти, а изменяемое состояние (переменные и стек времени выполнения) находится в статической оперативной памяти (SRAM). Кроме того, первая часть флэш-памяти, начиная с адреса 0x08000000, содержит векторную таблицу, состоящую из указателей на различные обработчики исключений. Наиболее важными из них являются адрес обработчика сброса (хранится по адресу 0x08000004), который выполняется всякий раз, когда процессор перезагружается, и начальное значение указателя стека (хранится по адресу 0x08000000). Эта структура памяти отражена во фрагменте сценария компоновщика, показанном на рис. 3. Сценарий начинается с определения точки входа кода. (Reset_Handler) и две области памяти – flash и ram. Затем он помещает именованные разделы из связываемых объектных файлов в соответствующие места в этих двух областях памяти. С точки зрения исполняемого файла есть три соответствующих раздела —  .text , который всегда помещается во флэш-память,  .data  и  .bss , которым всегда выделяется место в оперативной памяти. Константы, необходимые для инициализации .data во время выполнения, также помещаются во флэш-память для копирования кода запуска. Обратите внимание, что скрипт компоновщика определяет ключевые метки _текст, _sidata, … на которые ссылается код запуска для инициализации оперативной памяти. Компоновщику GNU поручено разместить раздел данных во FLASH, а именно  в  местоположении _Сидата, но связывает ссылки на данные с местами в оперативной памяти с помощью следующего фрагмента кода:

Основная идея заключается в том, что компоновщик GNU различает

виртуальные (VMA) и загрузочные адреса (LMA). VMA — это адрес, который имеет

раздел при выполнении программы, LMA — это адрес, по которому загружается

раздел. Для данных наш скрипт компоновщика помещает LMA раздела данных во

FLASH, а VMA в RAM — обратите внимание, что _сидата = _etext.

 

Фрагмент скрипта компоновщика

 

Первая порция.текст Раздел загружается с векторами исключений (.isr_vector) которые позже определяются в коде запуска. Эти векторы начинаются с адреса 0x08000000, что требуется при загрузке STM32 с флэш-памяти.

 

Опущен ряд деталей, которые обеспечивают создание меток, принимаемых компилятором и стандартными библиотеками, а также обработку отладочных разделов двоичного файла. Сценарий компоновщика и код запуска совместно создают осмысленную исполняемую среду. Сценарий компоновщика отвечает за то, чтобы различные части исполняемого файла (например, векторы исключений) находились на своих местах, а также за связывание значащих меток с определенными областями памяти, используемыми кодом запуска. При сбросе вызывается обработчик сброса. Обработчик сброса (определенный в startup_stm32f10x.c) копирует начальные значения переменных из флэш-памяти (куда их помещает компоновщик) в SRAM и обнуляет так называемую часть не инициализированных данных SRAM. (см. листинг 3.2). Эти шаги необходимы всякий раз, когда процессор сбрасывается для инициализации среды  C . Затем обработчик сброса вызываетсистемная инициализация (определено в system_stm32f10x. С из библиотеки прошивки), который инициализирует систему тактирования, отключает и очищает прерывания. Флаг компиляцииSTM32F10X_MD_VL определенный в нашем make-файле, имеет решающее значение для этого кода, потому что код инициализации часов зависит от процессора. Наконец, обработчик сброса вызывает главная функция, определенная в пользовательском коде. Внешние переменные, необходимые обработчику сброса для инициализации памяти (например, _сидата, _сдата…) определяются сценарием компоновщика. Другой важной функцией кода запуска является определение таблицы векторов прерываний по умолчанию (листинг 3.3). Чтобы код приложения мог удобно переопределять различные обработчики прерываний, каждому требуемому вектору прерывания назначается переопределяемый (слабый) псевдоним обработчику по умолчанию (который зацикливается навсегда). Чтобы создать собственный обработчик прерывания в коде приложения, достаточно определить процедуру с соответствующим именем обработчика. Одно предостережение — вы должны быть осторожны, чтобы использовать именно те имена, которые определены в таблице векторов для вашего обработчика, иначе он не будет связан с загруженной таблицей векторов!

 

Листинг 3.2 обработчик сброса в startup stm32f10x.c

 

Листинг 3.3. векторы прерываний

 

 

Оставьте комментарий

Ваш адрес email не будет опубликован.

Exit mobile version