Доброго времени суток! Не так давно я опубликовал небольшую статью на основе своего онлайн-урока для студентов 2020 года, по работе с GD32F103TB. Статья была выложена в ВКонтакте и как оказалось, была многим полезна. По этой причин я решил выложить её здесь с дополнительными комментариями, а так же продолжить цикл статей по данным контроллерам.


Для работы с данными контроллерами была выбрана IDE Keil uVision. Данная среда мне не очень нравиться, но с ней будет меньше всего проблем с настройкой (см. под спойлер), что будет крайне важно для старта.

Возможные проблемы с настройкой среды

Изготовитель GigaDevices выложил не полный комплект Firmware (на момент написания статьи 29.12.2023), в котором отсутствуют скрипты линковки (ld-файлы). В целом, если Вы опытный разработчик, то большой проблемы это не вызовет, но если мы говорим о начале работы, то это проблема.

Если Вы не страшитесь написания ld-скрипта, то советую использовать Eclipse for Embedded Developer

Следующим шагом, перед тем как начать, необходимо обзавестить SWD программатором. Для GD32 есть фирменные программаторы GD-Link, отлично работающие с фирменным софтом GD-Link Programmer. Классно? Да! Однако программатор GD стоит от 2 тыс. руб. и в продаже почти не найти. По этой причине нам прекрасно подойдёт любой ST-link V2, цена которого варьируется от 200 до 5000 рублей, с софтом ST-Link Utility. Почему? А вот тут кроется интересная особенность контроллеров GD32F - они являются скопированными совместимыми с STM32F. Речь не только о корпусе, а о самой периферии. С большой вероятностью код написанный для STM32F103C8T6 будет корректно работать на GD32F103C8T6.

Ключевые различия между GD32F и STM32F

Главные различия контроллеров заключаются в размере памяти и максимальной частоте работы ядра. Так же важным моментом является особенность подключения внутренней Flash памяти. Насколько я верно понял документацию, она подключена через внутренний QSPI, что как по мне не однозначное решение

И так, мы определились с средой разработки и обзавелись необходимым программатором. Теперь необходимо загрузить всё программное обеспечение. Сделать это можно с официальных сайтов. Учитывайте, что Вас попросят заполнить информацию о себе. Не указывайте страну - Россия. При такой конфигурации Вам не дадут ничего загрузить)

Теперь запустим Keil. При первом включении Вы должны увидеть окно Pack Installer. Если по какой-то причине Вы его закрыли, открыть его можно через панель инструментов

Рис. 1. Расположение Pack Installer на панели инструментов
Рис. 1. Расположение Pack Installer на панели инструментов

В открытом окне Pack Installer необходимо найти наш контроллер. В рамках серии статей использоваться будет GD32F103TBU6 (последние 2 символа не важны при установке пакетов). В левом меню необходимо найти нужный контроллер (можно воспользоваться поисковой строкой).

��ис. 2. Выбор нужного пакета для контроллера
Рис. 2. Выбор нужного пакета для контроллера

Выбрав нужный контроллер (на скриншоте они подсвечены зелёным, но до установки они будут серыми) перенесите взгляд в правую часть окна. В нём необходимо найти раздел Device Specific. В данном разделе содержатся пакеты с описанием периферии и подготовленной библиотекой StdPeriph. Жмём установить.

Рис. 3. Выбор необходимого пакета для работы StdPeriph
Рис. 3. Выбор необходимого пакета для работы StdPeriph

Отлично. Мы закончили настройку IDE - быстро, удобно и просто. Теперь можно закрывать Pack Installer и приступать к созданию проекта.

Рис. 4. Создание нового проекта
Рис. 4. Создание нового проекта

В верхней панели выбираем раздел Project → New uVision Project. После этого перед Вам появится окно выбора цели проекта - выбор микроконтроллера из установленных пакетов. Выбираем тот что потребуется нам

Рис. 5. Выбор нужного контроллера
Рис. 5. Выбор нужного контроллера

Нажимаем ОК и переходим к настройке проекта. На данном этапе важно настроить только основные элементы, недостающие элементы всегда можно подключить по ходу разработки. Важно подключить следующие модули:

  • CMSIS - Core (основа всех библиотек)

  • Device - GD32F10x_libopt, Startup (файл первоначальной настройки и общий заголовочный файл для удобства работы с StdPeriph)

  • Device - GD32F10x_StdPeripherials - MISC, PMU, RCU (основные модули работы с микроконтроллером)

  • И дополнительно модуль работы с GPIO (так как мы хотим всё протестировать работу устройства) Device - GD32F10x_StdPeripherials - GPIO

Рис. 6. Выбор необходимых модулей периферии
Рис. 6. Выбор необходимых модулей периферии

Далее можно нажать кнопку ОК и приступить к работе с кодом. Наконец-то!

По умолчанию Keil создаёт пустой проект, так что нужно добавить новый исходник (*.с файл).

Рис. 7. Добавление нового файла к проекту
Рис. 7. Добавление нового файла к проекту

Для файла в котором храниться точка входа (main() функция) я обычно выбираю логичное имя - main.c

Теперь запишем стартовый код и разберёмся как он работает.

#include <gd32f10x_libopt.h>

int main(void)
{
  SystemInit();
  rcu_periph_clock_enable(RCU_GPIOA);
  gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, GPIO_PIN_10);

  gpio_bit_write(GPIOA, GPIO_PIN_10, 1);
  while(1)
  {

  }
}

Как ранее было описано, Вы добавили модуль GD32F10x_libopt. Этот модуль очень простой, всё что он делает, так это создаёт файл gd32f10x_libopt.h. Там наверное куча готового кода?) Нет. В нём находятся все необходимые include для работы с StdPeriph, не более. Мелочь, а приятно.

Далее у нас вызывается функция настройки системы тактирования - SystemInit(). Она входит в модуль RCU. По умолчанию контроллер запускается от внешнего источника на 8 МГц и при помощи PLL повышает частоту ядра до 108 МГц. Не смотря на низкую точность внутреннего RC источника и сильную зависимость от температуры, в рамках данного урока его будет достаточно. Для быстрой настройки в файле system_gd32f10x.c есть набор define'ов. Закомментируем 59-ую строчку и раскомментируем строку 49.

Рис. 8. Переключение источника тактирования
Рис. 8. Переключение источника тактирования

Далее по коду происходит включение тактирования периферии. Опять же при помощи готовых функций и макросов StdPeriph.

gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, GPIO_PIN_10);
gpio_bit_write(GPIOA, GPIO_PIN_10, 1);

А на этом моменте можно немного остановиться. Сейчас мы его разберём, что бы в дальнейшем не останавливаться. Функция gpio_init(), как ни странно, инициализирует порты GPIO.

  1. GPIOA - адрес порта (или имя, если так удобно)

  2. GPIO_MODE_OUT_PP - режим работы. Посмотреть весь перечень режимов можно в Reference Manual или в файле gd32f10x_gpio.h

  3. GPIO_OSPEED_2MHZ - скорость работы. Все варианты описаны там же где и режим работы

  4. GPIO_PIN_10 - номер пина в порту (можно указать несколько через побитовые ИЛИ).

Для записи значений в порт используется gpio_bit_write(). Аргументы думаю наглядны и не нуждаются в описании)

Теперь можно переходить к компиляции и прошивке. Необходимо скомпилировать программу и залить её на контроллер. Первым делом открываем настройки проекта: Project → Option for target 'Target 1'. Переходим во вкладку Output и ставим галочку «Crate HEX File»

Рис. 9. Настройки выходных файлов
Рис. 9. Настройки выходных файлов

Нажимаем кнопку ОК. Теперь пора запустить компиляцию и прошить контроллер. Компиляцию можно вызвать клавишей F7 или в меню Project → Build Target. По итогу, если всё успешно в нижней части экрана мы увидим сообщение о успехе

Рис. 10. Вывод терминала
Рис. 10. Вывод терминала

Теперь запускаем ST-Link Utility, подключаем программатор к вашему контроллеру/отладочной плате и нажимаем на кнопку Connect (вилка) либо Target → Connect. Далее вы увидите прошивку контроллера в HEX формате и сообщение о успешном подключении (не обращайте внимания, STM32 и GD32 идентичны и ST-Link думает что это родные STM32).

Рис. 11. Страшные цифры внутри контроллера
Рис. 11. Страшные цифры внутри контроллера

Далее открываем свой файл прошивки File → Open (он лежит в папке проекта →Objects) и выбираем Target → Program & Verify …
Жмём Start…

Несколько секунд и … Готов! Он светится!

Рис. 12. It's a LIGHT
Рис. 12. It's a LIGHT

Это обрезанный скриншот с учёбной трансляции. На фото, слева, находится STM32 Nucleo. Её я использую только как программатор. Сама же "отладка" с GD32 почти вне кадра.

Надеюсь я смог достаточно хорошо объяснить самый первый шаг работы, а именно настройка среды работы. В дальнейшем будут выходить новые статьи. Буду рад обратной связи. Всем спасибо!