Доброго времени суток! Не так давно я опубликовал небольшую статью на основе своего онлайн-урока для студентов 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. Если по какой-то причине Вы его закрыли, открыть его можно через панель инструментов
В открытом окне Pack Installer необходимо найти наш контроллер. В рамках серии статей использоваться будет GD32F103TBU6 (последние 2 символа не важны при установке пакетов). В левом меню необходимо найти нужный контроллер (можно воспользоваться поисковой строкой).
Выбрав нужный контроллер (на скриншоте они подсвечены зелёным, но до установки они будут серыми) перенесите взгляд в правую часть окна. В нём необходимо найти раздел Device Specific. В данном разделе содержатся пакеты с описанием периферии и подготовленной библиотекой StdPeriph. Жмём установить.
Отлично. Мы закончили настройку IDE - быстро, удобно и просто. Теперь можно закрывать Pack Installer и приступать к созданию проекта.
В верхней панели выбираем раздел Project → New uVision Project. После этого перед Вам появится окно выбора цели проекта - выбор микроконтроллера из установленных пакетов. Выбираем тот что потребуется нам
Нажимаем ОК и переходим к настройке проекта. На данном этапе важно настроить только основные элементы, недостающие элементы всегда можно подключить по ходу разработки. Важно подключить следующие модули:
CMSIS - Core (основа всех библиотек)
Device - GD32F10x_libopt, Startup (файл первоначальной настройки и общий заголовочный файл для удобства работы с StdPeriph)
Device - GD32F10x_StdPeripherials - MISC, PMU, RCU (основные модули работы с микроконтроллером)
И дополнительно модуль работы с GPIO (так как мы хотим всё протестировать работу устройства) Device - GD32F10x_StdPeripherials - GPIO
Далее можно нажать кнопку ОК и приступить к работе с кодом. Наконец-то!
По умолчанию Keil создаёт пустой проект, так что нужно добавить новый исходник (*.с файл).
Для файла в котором храниться точка входа (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.
Далее по коду происходит включение тактирования периферии. Опять же при помощи готовых функций и макросов 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.
GPIOA - адрес порта (или имя, если так удобно)
GPIO_MODE_OUT_PP - режим работы. Посмотреть весь перечень режимов можно в Reference Manual или в файле gd32f10x_gpio.h
GPIO_OSPEED_2MHZ - скорость работы. Все варианты описаны там же где и режим работы
GPIO_PIN_10 - номер пина в порту (можно указать несколько через побитовые ИЛИ).
Для записи значений в порт используется gpio_bit_write(). Аргументы думаю наглядны и не нуждаются в описании)
Теперь можно переходить к компиляции и прошивке. Необходимо скомпилировать программу и залить её на контроллер. Первым делом открываем настройки проекта: Project → Option for target 'Target 1'. Переходим во вкладку Output и ставим галочку «Crate HEX File»
Нажимаем кнопку ОК. Теперь пора запустить компиляцию и прошить контроллер. Компиляцию можно вызвать клавишей F7 или в меню Project → Build Target. По итогу, если всё успешно в нижней части экрана мы увидим сообщение о успехе
Теперь запускаем ST-Link Utility, подключаем программатор к вашему контроллеру/отладочной плате и нажимаем на кнопку Connect (вилка) либо Target → Connect. Далее вы увидите прошивку контроллера в HEX формате и сообщение о успешном подключении (не обращайте внимания, STM32 и GD32 идентичны и ST-Link думает что это родные STM32).
Далее открываем свой файл прошивки File → Open (он лежит в папке проекта →Objects) и выбираем Target → Program & Verify …
Жмём Start…
Несколько секунд и … Готов! Он светится!
Это обрезанный скриншот с учёбной трансляции. На фото, слева, находится STM32 Nucleo. Её я использую только как программатор. Сама же "отладка" с GD32 почти вне кадра.
Надеюсь я смог достаточно хорошо объяснить самый первый шаг работы, а именно настройка среды работы. В дальнейшем будут выходить новые статьи. Буду рад обратной связи. Всем спасибо!