Gcc для windows stm32

Отладка STM32 в среде Eclipse+GCC

Так как я недавно перешел на использование связки Eclipse+CodeSourcery G++ Lite в качестве среды разработки для микроконтроллеров STM32, то у меня встал вопрос об отладке с помощью ST-Link.
Решение было найдено в виде ST-Link gdbserver, который легко прикручивается к Eclipse. О чем я кратко и расскажу в этой статье.

Взять ST-Link gdbserver можно из дистрибутива Atollic TrueStudio или скачать сдесь.

Если у вас не установленны драйвера для ST-Link то необходимо их установить (идут в комплекте с gdb сервером, ST-Link_V2_USBdriver).

Приступим к настройке Eclipse. Для начала необходимо установить плагин для аппаратной отладки Help->Install New Software.

Далее идём в меню Run->External Tools->External Tools Configurations. и создадим новую конфигурацию для запуска GDB сервера, примерно как показанно на скриншоте.

В поле Location путь к GDB серверу, в поле Arguments ключи с которыми будем его запускать.
-e: Enable persistent mode.
-d: Enable SWD debug mode.

Сохраняем настройки и приступаем к следующему шагу, настройке проекта.
Идём в меню Run->Debug Configurations и создадим новую конфигурацию отладчика.

В поле C/C++ Application указываем расположение и название *.elf файла, в поле Project название проекта.
Далее переходим на вкладку Debugger.

В поле GDB Command укажем путь к GDB клиенту, у меня это C:\CodeSourcery\bin\arm-none-eabi-gdb.exe, в поле Port number укажем порт к которому будет подключатся GDB клиент, ST-Link gdbserver работает на порту 61234.
Далее переходим на вкладку Startup и настроим стартовые опции, примерно как на скриншоте.

На этом настройку отладчика можно считать законченной и можно приступать к отладке нашего проекта.

Для начала отладки сначала запускаем GDB сервер

Затем запускаем отладку

Теперь можно пошагать по нашему проекту

Использование gcc для stm32f100

Примерно полгода назад я обзавелся самым мелким контроллером stm32f100c4. Здесь я хотел бы изложить свой опыт применения средств разработки gcc вживую, без графической оболочки. Описывается установка, создание проекта — использование Makefile, прошивка через UART, отладка через gdb на stm32vldiscovery, ну и самое главное — грабли
GNU cредства разработки
Устанавливаем собственно компилятор. Я предпочел YAGARTO, как наиболее часто обновляемый дистрибутив gcc под arm (yagarto.de). Но пойдет и любой другой. Необходимо скачать собственно сам компилятор и набор утилит типа make и т.д. Все это устанавливается в отдельный каталог. Я не ставил его в Program Files, как он хотел по умолчанию, поскольку пробел в имени – это нехорошо, да и набирать в случае надобности долго. Установщик просит включить путь к gcc файлам в PATH. Но он у меня и так длинный, так что я отказался. Результатом этого является необходимость устанавливать переменную среды PATH перед первым вызовом сборки проекта:

Все действия по сборке можно проводить из программы “Командная строка”, но я предпочел использовать far.
Как оказалось впоследствии в yagarto не совсем правильный make. Он не понимает символа перенаправления вывода в файл (>). Так что пришлось использовать make от mspgcc. Этот файл я приложил в архиве в каталоге add.

Стандартная библиотека периферии.
Для использования всяких символических имен регистров, а также компиляции примеров от ST необходима стандартная библиотека для STM32. Качается она с сайта ST. В последнее время они изменили дизайн. Так что трудно что либо найти. Нужно найти любой более старый микроконтроллер stm32 серии (например stm32f103re) и выбрать вкладку Design Support. Оттуда необходимо скачать архив стандартной библиотеки периферии (Standard peripheral library). На сегодняшний день там лежит версия 3.4.0, в которой добавлена поддержка мелких дешевых arm серии stm32f100 (low density value line в терминологии ST). Оттуда же необходимо скачать и демонстрационную утилиту загрузки через rs232 (Flash loader demonstrator последняя версия 2.2.0). Все это бесполезно искать для контроллеров stm32f100, этих документов не существует для этой серии. Но поскольку библиотека и загрузчик унифицированы, то они одинаковы для всего семейства stm32.
Стандартную библиотеку необходимо разархивировать. Из получившегося каталога STM32F10x_StdPeriph_Lib_V3.4.0 нас интересует собственно сама библиотека – подкаталог Libraries. Также интерес представляют примеры из каталога STM32F10x_StdPeriph_Lib_V3.4.0\Project\STM32F10x_StdPeriph_Examples.

Для проекта я создал новый каталог. В него поместил каталог Libraries из стандартной библиотеки периферии. Туда же скопировал пример ADC_ADC1_DMA из той же библиотеки. Каталог этого примера я обозвал prj. Таким образом, в каталоге проекта 2 подкаталога: Libraries и prj. В перовом – исходные тексты библиотеки стандартной перифирии, а во втором – пример приложения.
В моем случае – пример использования аналого-цифрового преобразования и прямого доступа к памяти.
Забегая вперед, скажу, что не все примеры из состава стандартной библиотеки периферии у меня собрались. Некоторые предназначены для конкретной платы. Догинать эти примеры для сборки я не стал.

Сборочный файл. Введение в синтаксис.
Основой всего процесса сборки в GNU средствах разработки является сборочный файл (Makefile). Это файл, который выполняется утилитой make для сборки проекта. У сборочного файла очень простой синтаксис. Он описывает, что нужно выполнять (какие программы, и с какими ключами), что бы выполнить цель. Цель в makefile – это файл на диске или просто имя для какого либо действия. Цель зависит от других целей (файлов). Для выполнения цели, необходимо выполнить какую либо программу, которой на вход передаются входные файлы (цели, от которых зависит конечная цель). Результатом работы программы является выходной файл (цель) зависящий от входных и промежуточных файлов (целей). Синтаксис такой зависимости в makefile следующий:

Читайте также:  Linux ос только консоль

Данную запись можно прочитать следующим образом: что бы получить КОНЕЧНУЮ_ЦЕЛЬ нужно выполнить Программу вот с такими аргументами. В случае если файл ЦЕЛЬ1 или ЦЕЛЬ2 изменились, то нужно снова проделать действия по вызову Программы, что бы обновить результат. В оригинальном файле условные наименования целей должны быть заменены именами файлов, программа – именем программы.
Действий по выполнению цели может быть несколько, по одному в каждой строке. Перед каждым действием в начале строки должен стоять символ табуляции, который является частью синтаксиса, пробелы здесь недопустимы. Цель должна начинаться с первого символа строки.
Таким образом, из исходного файла на языке C утилита make строит путем вызова компилятора объектный файл, а из объектных файлов – собственно программу, из программы – hex файл.
Что бы сделать makefile более гибким, используют переменные. Переменная определяется как НАЗВАНИЕ_ПЕРЕМЕННОЙ = ЗНАЧЕНИЕ. Ни разу не пробовал называть переменные и цели русскими буквами. Лучше использовать латинские. После того, как переменная определена, ее можно несколько раз использовать ниже определения в Makefile.
При использовании переменная должна браться в скобки и перед скобками помещаться символ $. В нашем случае использовать переменную можно так: $( НАЗВАНИЕ_ПЕРЕМЕННОЙ). Значения переменных могут перемежаться с обычным текстом. При этом результатом будет строка с подставленными значениями переменных. Так, например, можно формировать командную строку запуска программы.
Обычно переменные определяются в начале файла. После определения переменных идут цели. Имя первой цели в файле является целью по умолчанию. Именно она начнет выполняться, в случае, если не указать явно цель при запуске make. Обычно она же и является конечной целью. Но в makefile могут присутствовать и другие цели. Типично в каждом makefile присутствует дополнительная цель clean. При выполнении этой цели удаляется результат всей работы по сборке проекта. Что бы выполнить ее, необходимо запустить утилиту make с аргументом – именем цели:
make clean
в нашем случае. Эта цель не имеет зависимостей от файлов и является только именем для действия. При ее запуске не создается никаких файлов, выполняются только действия по удалению. Поскольку зависимостей от файлов нет, то и изменения файлов не отслеживаются и действия выполняются всегда при запуске данной цели.
Существуют так называемые предопределенные цели. Это цели, для которых правила зашиты в сам make. Например, make знает, как из исходного файла на языке C файла получить объектный файл. Он считает, что для этого нужно запустить программу, определенную переменной CC, с аргументами, определяемыми переменной CFALGS. Но это действует только, если исходные файлы находятся в текущем каталоге.
Обычно Makefile строится таким образом, что для получения результата (в нашем случае прошивки) достаточно выполнить утилиту make в каталоге с Makefile.

Файл конфигурации компоновщика.
Что бы собрать проект достаточно скопировать в каталог проекта Makefile и выполнить команду make в каталоге проекта. Но для сборки программы для микроконтроллера необходим особый файл правил для компоновщика. Он указывает, по каким адресам размещать код и переменные программы. Для этого в наш файл проекта добавляется еще один каталог – каталог файлов компоновщика ld.

В нашем случае этот особенный файл называется stm32f100c4.ld. Он предназначен для сборки программ для микроконтроллера stm32f100c4t6b. Этот файл можно адаптировать и для других контроллеров. Необходимо только поменять в строках

величины оперативной памяти и флеша.
Также в строке

нужно поменять значение указателя стека. Он должен указывать на самый конец (верх) оперативной памяти.

Настройка Makefile под контроллер и программу.
Настройка выполняется путем изменения в текстовом редакторе значений переменных. Так, что бы изменить файл компоновки нужно подставить в Makefile в строке

другое имя файла вместо stm32f100c4.ld.
Аналогично, настраиваются и другие параметры сборки.

  • DEVCLASS = STM32F10X_LD_VL – выбор класса контроллеров.
  • SOURCES – исходные тексты. Список исходных файлов проекта.
  • OBJECTS – объектные файлы. Список объектных файлов проекта. Должен соответствовать списку исходных…
  • DEBUG – флаги отладки
  • OPT – флаги оптимизации.

Оптимизацию рекомендуется либо не использовать (значение 0) либо использовать оптимизацию по размеру (s).

CFLAGS += -DUSE_STDPERIPH_DRIVER – эта строка определяет макрос USE_STDPERIPH_DRIVER при компиляции. Этот макрос необходим, если используются стандартные библиотеки периферии, а не только символические имена регистров и битов. Именно на это рассчитаны примеры, поставляемые ST.
Прим. В данном случае речь идет о конкретном makefile. Каждый может написать свой собственный с другими переменными.

Компиляция примера от ST.
Вот теперь после копирования Makefile и выполнения make в каталоге проекта мы будем иметь конечный файл, который можно залить в контроллер.

Читайте также:  Какую операционную систему выбрать mac os или windows

На самом деле в результате работы программы создаются целых 3 файла: один из них в elf формате, второй – binary (образ для заливки во флеш), и третий – hex (тот же образ, но в ascii шестнадцатеричном формате). Кроме того, формируются еще дополнительный файл отчета о сборке: файл дизассемблера – в нем дизассемблируется каждая строчка программы. В файле – строки C и соответствующие им ассемблерные коды. В случае высоких уровней оптимизации это соответствие может нарушаться.

Теперь можно компилировать примеры от ST. Для этого необходимо скопировать каталог с примером в каталог сборки, скопировать Makefile и выполнить make. Для примера я скопировал каталог DualModeDMA_SineWave с примером использования цифро-аналогового преобразователя. После выполнения make имеем файл прошивки main.hex.

Однако запускать примеры от ST на данном контроллере я не стал. Все примеры рассчитаны на подключение 8 МГц кристалла. На моей же плате кристалла нет совсем. Кроме того, примеры слишком сложны, все они используют библиотеку стандартной периферии. Мне же совсем не хотелось ее использовать, и для первого раза выбрать что ни будь попроще.

Hello world
Традиционно микроконтроллерным “Hello wold” является моргание светодиодиком. На easyelectronix.ru я нашел такой пример (кстати там же есть описание использования компиляторов Keil и IAR). Просто моргание светодиодиком. Включение, а потом выключение.

Для программы моргалки я создал отдельный каталог blinky. Туда поместил файл main.c с примером.
Исходный код я немного модифицировал. Прежде всего, использовал порт ввода -вывода B бит 12. Он выводится на 25 ногу 48 пинового корпуса. Отсчитывать ее очень удобно – она в углу корпуса. Не то, что 30, 31 или 44.

Итак, вот код с комментариями:
/* Включение заголовочного файла определения портов и их битов */

Здесь требуются дополнительные комментарии к коду.

Во-первых, регистр Управления портом (старший и младший) ввода-вывода (GPIO_CRH, GPIO_CRL) имеют ненулевое начальное значение (0x44444444). Поэтому только перевода порта в режим вывода (настройка битов MODE) недостаточно. После этого порт будет настроен на работу в режиме с открытым стоком. Если между землей и ножкой порта включить резистор, то он гореть не будет. Поэтому выполняется сброс битов CNF – перевод порта в двухтактный (push-pull) режим. На эти грабли я потратил несколько часов. В результате собрал пример компилятором Keil, убедился, что в его симуляторе работает так же как в железе. Так что в каталоге теперь остался и проект Keil с его стартовым файлом.

Во-вторых, для gcc средствами прекомпилятора исключен вызов функции SystemInit. Однако она вызывается пред main и должна быть определена. И именно с таким именем. Вызов ее предусмотрен в стартовом коде, написанном на ассемблере. Этот стартовый код находится в файле Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\gcc_ride7\startup_stm32f10x_ld_vl.s. Вот его кусок, отвечающий за вызов SystemInit и main:

В-третьих, счетчик задержки нужно определять как volatile. Иначе компилятор увидит пустой цикл, в котором не выполняется никакой полезной работы, и исключит его для ускорения работы всей программы.
Makefile файл был также скопирован в каталог blinky. Он подвергся следующим модификациям:
Закомментированы неиспользуемые объектные и исходные файлы (stm32f10x_it system_stm32f10x), которые поставляются с каждым примером ST.
Закомментирована строчка с определением макроса USE_STDPERIPH_DRIVER. В программе не используется стандартная библиотека периферии.
Исключена зависимость от стандартной библиотеки периферии. Так что и сама библиотека больше не собирается.
Вызов утилиты make в каталоге blinky строит выходной hex файл main.hex.
Замечания о Keil и симуляции.

Кейл имеет прекрасный инструмент – симулятор. Поэтому перед прошивкой проекта можно опробовать, как он будет работать. Он обладает также отличным отладчиком. Симулятор поддерживает ограниченное количество кристаллов STM32. Я использовал stm32f103re. Поскольку это один из самых продвинутых кристаллов, а большинство периферии совместимо, то можно симулировать кристаллы высокой плотности, а заливать прошивку в Value line с меньшими объемами. Но я отступил от темы.

Заливка прошивки.
Для заливки прошивки используется утилита от ST Flash loader demonstrator (демонстрационная программа загрузчика, um0462), скачанная ранее. Устанавливать ее лучше в какой ни будь каталог с именами покороче и без пробелов для надежности. После установки в каталоге находятся две программы: графическая (STMicroelectronics flash loader.exe) и консольная (STMFlashLoader.exe), каталог исходников (Src), документации (Doc), конфигурации(Conf) и каталог настроечных файлов.
Если вы думаете, что ST дала исходники программы прошивки, то это глубокое заблуждение. Те исходники, что идут в демонстраторе только отрисовывают экран да читают-записывают файлы. Вся работа с контроллером зашита в dll-лях, для которых нет исходников.

Правда есть документ по описанию протокола загрузчика AN2606 (STM32F101xx, STM32F102xx and STM32F103xx system memory boot mode).

Для программирования контроллер через преобразователь уровней типа max3232, st3232 подключается к com порту компьютера. Причем выход USART подключается к входу преобразователя и наоборот. В данном корпусе выход USART – это нога 30, вход – нога 31 (согласно Table 4 datasheet на stm32f100c4). Кроме этого, нужно активизировать загрузчик путем подтяжки Boot1 (нога 20) к земле, а Boot0 (нога 44) — к питанию.

Читайте также:  Mac os excel автосохранение

После этого, согласно описанию в документации на загрузчик, нужно запустить графическую утилиту, выбрать настройки порта (обязательно с проверкой четности – even), включить (перегрузить) контроллер и нажать кнопку Next. Контроллер должен определиться, и появится другая картинка. Но другой картинки я так и не увидел. Думал, что уж спалил контроллер.

Запустил терминал termite (http://www.compuphase.com — как он сам о себе пишет, где я его скачал, уже не помню), выставил скорость 2400 и начал вводить всякие буковки и циферки. И о чудо, иногда он начал отвечать. Тогда полез вот в этот самый документ AN2606 и нашел, что имеется ограниченный набор команд. Первой должен идти один байт 0x7F, на который контроллер должен ответить 0x79. А при передаче ему двух байт 0x02+0xFD, он должен выдать версию чипа. Оказалось, что просто нет настроечного файла для данного микроконтроллера.

Взял за основу файл для 16 килобайтного stm32f103 STM32_Low-density_16K.Stmap из каталога Map. Изменил размер RAM и идентификатор устройства вот так:
Измененный файл сохранил под именем STM32_Low-density-value_16K.Stmap в том же каталоге. После этого запустил консольный загрузчик вот такой командой:

И файл загрузился. После отключения подтяжки на 44 ноге и перегрузки программа заработала, светодиод заморгал. Если необходимо повторно загрузить прошивку, то сначала нужно стереть флеш командой:

Грабли
Все, о чем я рассказал, работало, пока я использовал простейшие примеры. На реальном проекте вдруг код начал вываливаться в прерывание по умолчанию. После просмотра листинга и прохода отладчиком обнаружил, что неверная операция выглядит примерно так:

Структуры большие – 140 байт. Вот на присвоении все и происходит. Заменил присвоение на memcpy – ничего не изменилось. Посмотрел листинг. Оказалось компилятор подставляет инструкцию BLX #memcpy вызова функции. Вот в ней то вся проблема. Посмотрел интернет. Не у одного меня такие проблемы. Несколько сообщений размещены как баги GCC при работе с ARM Cortex-M3 (M0). И в одном сообщении – информация о причине. Оказывается, с gcc идут библиотеки внутренних функций под разные процессоры. Инструкции BLX в наборе Cortex нет. Это инструкция 32 битных команд ARM (7?). Используется она потому, что по умолчанию подхватываются чужие библиотеки. Что бы использовались нужные – нужно и для компоновки использовать gcc (что я делал) и подставлять опции -mthumb -mcpu=cortex-m3.

Использование отладчика gcc.
С того времени как я написал этот текст прошло несколько месяцев. Самодельную платку я замучил. Вместо нее я обзавелся stm32vldiscovery. Написал достаточно объемную программу, пока не столкнулся с вышеописанными граблями. Причем на keil все работает. Gcc отказывается. Пришлось запускать отладчик gdb.
Для запуска необходим gdb server. Пока с ST Link (то что стоит на discovery) работает только один пакет – Autollic TrueSTUDIO. Он раздается бесплатно – нужно только зарегистрироваться. Установить без регистрации не получается – требует ключ. Ключ привязывается к железу. После установки в меню пуск появляется ST-Link GDB Server. По умолчанию он работает через jtag. Настройка на SWD осуществляется в фале config.txt. Необходимо добавить строку: -d. Эта опция заставляет его работать через SWD.

После этого код загружаю STM32 ST-Link utility от ST. Он загружает либо бинарный, либо hex файл. Gdb (точнее arm-none-eabi-gdb – из yagarto) нужно указывать в качестве отлаживаемого файла – elf файл (main.out в примерах). После запуска необходимо выполнить команды:

Далее работа как с обычным gdb.

Грабли 2
После исправления Makefile код так и не начал выполняться. Но на этот раз попадание в обработчик по умолчанию происходило бессистемно при использовании отладчика. Зато вполне определенно в реальном запуске. На графическом дисплее отображалось всегда полторы первые буквы текста. Проблема оказалась в названии обработчика прерывания DMA, который запускался ADC, который запускался таймером. Оказалось, что в keil этот обработчик должен называться DMAChannel1_IRQHandler, а в GCC DMA1_Channel1_IRQHandler. Решается это применением условной компиляции примерно так:

Так же отличается названиями и обработчик ADC. Возможно, что-то есть еще. Расскажу принцип их формирования. Названия обработчиков задаются в startup файле, написанном на ассемблере. Keil и gcc имеют различающийся синтаксис ассемблера. Наверняка их писали разные люди. Поэтому такое различие в названиях. Поэтому, если вы активировали обработчик в NVIC, флаги прерывания в периферии устанавливаются, прерывание вызывается, но не то что нужно, а прерывание по умолчанию, нужно смотреть startup файлы на предмет названий обработчиков. Еще можно посмотреть отчеты о компоновке – map файлы и дизассемблированный код.

В заключение ссылка на весь демо проект:Пример проекта rar архив 270 килобайт
И на проект примеров от ST, собираемых gcc (проверял только под linux сборку, в контроллер не заливал): Примеры от ST для gcc архив tar gzip больше полмегабайта

Оцените статью