23 авг. 2011 г.

Программируем STM32VLDiscovery в Linux'е и только в Linux'е!

Подобно многим любителям садистски потыкать раскаленным паяльником в нежные внутренности электронных девайсов я не избежал увлечения микроконтроллерами серии STM32 от STMicroelectronics, за их небольшую цену прозванные "убийцами" 8/16-битных микроконтроллеров, таких как AVR.
Поскольку основной операционной системой на моем компьютере является Линукс, а альтернативных операционных систем на нем нет и не предвидится, то встал вполне естественный вопрос - чем собирать программы под STM32 и чем их прошивать в имеющуюся у меня STM32VLDiscovery? Иначе говоря передо мной встал вопрос инструментального обеспечения.
Большинство руководств, найденных мною в Интернете, либо советовали перезагружаться в Windows, либо использовать утилиту stm32flash, которая прошивает кристалл при помощи встроенного bootloader'а через UART. При всем при этом, в некоторых руководствах еще и предлагалось немного пошаманить с состоянием выводов BOOT0 и BOOT1 или использовать такие громоздкие среды разработки как Eclipse.
Мне все вышеперечисленное показалось крайне неприемлемым и я стал искать свой способ работы с STM32VLDiscovery под Linux'ом. Результаты моих изысканий приведены далее, под катом.


Инструментальная цепочка
В деле программирования я предпочитаю минимализм - мне достаточно текстового редактора (хорошего текстового редактора, такого как vim или emacs), компилятора и утилиты make, которая будет собирать мой исходный код и мои инструментальные средства в один проект.
Для проектов под встраиваемые системы важно еще наличие каких-либо библиотек, облегчающих работу с выбранной встраиваемой системой и утилиты для загрузки скомпилированного кода в ядро встраиваемой системы.

Для STM32VLDiscovery нам потребуется:
  • компилятор GNU GCC, ориентированный на работу с архитектурой ARM (обязательно arm-none-eabi-, не arm-linux- ! Последний генерирует код под встраиваемый линукс на ARM'е, а не под сам ARM.)
  • отладчик GNU GDB (тоже arm-none-eabi-)
  • Утилита для заливки кода в STM32VLDiscovery через ST-Link - stlink
  • библиотека CMSIS - Cortex Microcontoller Software Interface Standard. Набор удобных макросов и функций, созданных для работы с внутренностями ядра Cortex-M3 - на этом ядре построен STM32F100RB, служащий сердцем STM32VLDiscovery
  • библиотека STM32 Standard Peripheral Library - еще один удобный набор макросов и функций от производителя чипа. Содержит в себе драйвера для работы со всей периферией STM32F100RB
Компилятор и отладчик ищите в репозиториях своего дистрибутива. На крайний случай можно скачать готовые бинарники от CodeSourcery (правда я не помню есть ли в них gdb). Библиотеки CMSIS и STM32StdPeriphLib можно взять единым архивом с сайта STMicroelectronics - http://www.st.com/internet/mcu/product/216844.jsp , вкладка "Design Support" и пункт ""STM32F 10X standard peripheral library".
Теперь перейдем к тому, как все это упаковать в один большой проект.

Шаблон проекта
Шаблонный проект для нашей отладочной платы будет иметь следующую структуру:

Все необходимые исходники библиотек и нестандартных утилит я предпочитаю держать в дереве проекта, чтобы можно было сразу скомпилировать и загрузить программу просто получив ее исходный код, без поисков "где же скачать и установить утилиту stlink" и так далее.
Итак, исходный код stlink'а и CMSIS лежит в соответствующих директориях, эти директории могут кочевать из проекта в проект без каких бы то ни было изменений.
Исходный код библиотеки стандартной периферии от STM32 лежит в подкаталоге stm32_lib. Содержимое этого подкаталога может варьироваться в зависимости от того, какие драйвера для программы нужны. Так, например, в нашем шаблонном проекте используются выводы общего назначения (чтобы зажечь светодиоды) - соответственно я скопировал из скачанного архива библиотеки файлы stm32f10x_gpio.c и stm32f10x_gpio.h. Остальные файлы в каталоге шаблонного проекта являются необходимыми для компиляции проекта, особенно стартовый ассемблерный код и скрипт для линкера.

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

И еще нужно подтвердить использование библиотеки стандартной периферии, раскомментировав соответствующий макрос в stm32f10x.h:
В этом же файле нужно раскомментировать соответствующее макроопределение для используемого в проекте микроконтроллера. Так например, STM32F100RB относится к линейке "Medium density Value Line" и соответственно нам нужно раскомментировать строчку с макросом STM32F10X_MD_VL:
На этом настройка библиотек закончена и можно переходить к написанию своего кода. В шаблонном проекте весь код сосредоточен в файле main.c в корне дерева исходников, но вы вольны использовать любую другую компоновку, немного подправив Makefile.
Для того, чтобы использовать в вашем исходном коде какие-нибудь драйвера из библиотеки от STM32, достаточно подключить заголовочный файл stm32f10x.h. Всякие же подробности использования драйверов скрыты в комментариях к исходному коду этих драйверов.

Сборка проекта
Компиляция и загрузка проекта осуществляется при помощи одного большого Makefile. Я не буду приводить в блоге код полностью - его вы сможете посмотреть сами в исходниках проекта (ссылка приведена в конце статьи).
Отмечу лишь, что для своего проекта вам нужно указать имя бинарника, пути к исходным файлам проекта и, если потребуется, к заголовочным файлам, список получающихся объектных файлов, а также путь к ARM'овскому кросскомпилятору.

Прошивка проекта в микроконтроллер производится через make load, при этом собирается утилита stlink из исходников и запускается скрипт flashing_stm32vldiscovery.sh, проверяющий все ли на месте и запускающий сервер для gdb (необходимы привилегии root - sudo спрашивает пароль!). При удачном подключении к плате должен зажечься еще один красный светодиод на ней (следует подождать некоторые время - примерно 7-9 секунд). После этого, вы можете запустить gdb для ARM в другой консоли и выполнить для загрузки прошивки в чип:
target remote :1234
load stm32vldiscovery-linux-template.elf
Загрузка прошивки в STM32VLDiscovery

Для запуска прошитой программы следует ввести команду continue, для остановки - нажать Ctrl+C.
Небольшой подводный камень - после выполнения make load лучше всего не прерывать работу запустившегося stlink'а, не выходить из gdb и не отсоединять STM32VLDiscovery от USB. Иначе возможна нестабильная работа системы, core dump'ы, kernel panic'и и прочие подобные вещи. Собирать ELF'ы лучше всего в отдельной вкладке консоли, а затем переходить на вкладку с GDB, чтобы залить изменения в чип.
Еще один подводный камень - для работы утилиты stlink необходим модуль ядра sg. Соответствующая опция расположена где-то в "Device drivers"->"SCSI drivers"->"....generic...". Если этого модуля нет или он вкомпилирован в ядро - вы получите красивый crashdump и последующую перезагрузку системы.

Если все прошло удачно и шаблонный проект прошился - мы должны получить плату с горящими зеленым и синим светодиодами:

Полезные ссылки