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 и последующую перезагрузку системы.

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

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

12 комментариев:

  1. Спасибо! Это гораздо удобнее, чем использовать stm32flash через последовательный порт.

    ОтветитьУдалить
  2. с последней версией st-util не получается. При выполнении команды load пишет Load failed. Зашить получается только утилитой flash

    ОтветитьУдалить
  3. Судя по рассылке разработчиков, на которую я подписан, в новых коммитах они что-то поломали, пытаясь перевести stlink с kernel-модуля sg на libusb.
    Только что мне пришло письмо, что у одного из разработчиков получилось заставить снова писать и стирать STM32-*Discovery через stlink. Надо подождать, пока они закончат или же использовать срез репозитория, который не младше моего поста...

    ОтветитьУдалить
  4. круто все работает

    ОтветитьУдалить
  5. Доброго времени суток. Пытаюсь собрать ваш шаблонный проект, make валится на сборке цели ldall, там, как я понимаю, должна происходить итоговая линковка, но флаги в переменной LDFLAGS одновременно и для линковщика и для компилятора и по умолчанию сборка валится со словами unrecognized option '--section-start=.text=0x8000000'. Сам начинаю осваивать разработку под arm из под линукса по вашему блогу и потому не могу понять, это косяк моего toolchain'а (так же стянутая сборка от CodeSourcery) или я что-то упускаю в статье?

    ОтветитьУдалить
  6. Хм, наверное это особенность тулчейна. Я использовал свой, самосборный и помнится, когда пытался перелезть на CodeSourcery, чуть ли не половину Makefile'а приходилось перелопачивать...

    ОтветитьУдалить
  7. Только начинаю... Спрашивать не где, а своих мыслей ещё мало.

    Ошибка на цела ldall:
    /home/ajk/stm32/gcc-arm-none-eabi-4_7-2012q4/bin/../lib/gcc/arm-none-eabi/4.7.3/../../../../arm-none-eabi/lib/armv7-m/libc.a(lib_a-exit.o): In function `exit':
    exit.c:(.text.exit+0x16): undefined reference to `_exit'
    collect2: error: ld returned 1 exit status
    make: *** [ldall] Ошибка 1

    Хоть и чтото прочео про make, но ещё не осмыления. Что это за ошибка?

    Спасибо Александр

    ОтветитьУдалить
  8. Подскажите что нeжно дописать в makefile чтобы получить .hex? (у меня versaloon)

    ОтветитьУдалить
  9. В принципе, можно воспользоваться утилитой elf2hex. Насчет ключей, с которыми её вызывать не подскажу -- тут все зависит от применяемой программно-аппаратной системы.

    ОтветитьУдалить
  10. Начинаю осваивать STM32 (раньше программировал AVR). Пробовал Eclipse - как-то глючно (то работает, то выдает ошибки), пробовал настроить Code::Blocks (брал готовый проект) - он выдает .sys (куда его пихать так и не нашел). Теперь пытаюсь найти проект make. Из переловаченных 7 только ваш заработал и выдает .elf. В других проектах написано что будут выдавать и .hex. Но они не запустились. Нашел способ преобразовывать через arm-none-eabi-objcopy - но хочется меньше телодвижений. У меня Debian, arm-none-eabi-gcc, versaloon, openocd.

    ОтветитьУдалить
  11. Как все сложно. Теперь я понимаю, почему на платформу СТМ32 никто не хочет переходить. АВР и ПИКи и Ардуино рулят. Нафига нужны такие напряги? В Линухе я просто запускаю Коде Блокс и вот тебе готовая среда для АВР без всяких лишних телодвижений и шаманства. Нафиг-нафиг этот СТМ...

    ОтветитьУдалить
  12. Во-первых, всё, что описано в данной статье, как правило скрыто под капотом всяких-разных IDE, и вытаскивалось наружу лишь для развлечения.
    За прошедшие несколько лет кросскомпиляторы с поддержкой STM32 и загрузчики наверняка появились в репозиториях.

    Во-вторых, в производстве и прочем бизнесе, удобство среды разработки это далеко не первый критерий, по которому выбирают микроконтроллеры (а за Ардуино вообще ногами бьют ;-) ). Куда больший интерес вызывает цена, толщина списка ошибок в кристалле и наличие необходимой периферии.
    Хотя конечно, для разовых хобби-проектов всё может быть и по другому.

    ОтветитьУдалить