На данный момент МК 1923ВК014 находится в стадии разработки, а в опытных образцах интерфейс JTAG не доступен, поэтому прошивка и отладка будет осуществляться по интерфейсу UART. Архив с примерами и программами, используемыми в статье, можно скачать здесь.
Для загрузки программы по UART интерфейсу на отладочной плате необходимо перемычками выставить режим работы МК MODE[7:0]= 00111100. Переключателем выбираем напряжение питания на плате 3.3 В или 5 В. Для работы с UART нам потребуется кабель переходник USB-RS232. Подключаем кабель USB-RS232, подаем питание на плату. При старте в микроконтроллере запускается BootLoader, проверяет выводы MODE и настраивает аппаратный UART с параметрами согласно спецификации:
Для загрузки программы через UART интерфейс мы воспользуемся специальной программой Loader, которая создана исключительно для МК 1923ВК014. Скачать её можно в архиве выше. Она не требует установки, но для её запуска нужны библиотеки Visual Basic Powerpacks 10, которые необходимо скачать и установить. Остановимся на основных моментах работы программы.
После подключения кабеля USB-RS232 и подачи напряжения на плату запускаем программу (информационное сообщение "please, power up board" высвечивается даже при поданном питании). Сначала необходимо провести инициализацию COM порта. Для этого во вкладке COM# выбираем COM порт, к которому подключен МК. В моём случае это COM9. Чтобы узнать номер порта переходим в диспетчер устройств (найти его можно, например, по поиску в меню "Пуск"), и во вкладке "Порты (COM и LPT)" находим наш. Для моего переходника он называется USB-SERIAL CH340, в скобочках указан номер порта.
В поле программы BR указываем скорость обмена. Можно выбрать либо 9600, либо 115200. Т.к. первоначально UART в МК настроен на скорость 9600, то при выборе 115200 будет подана команда перехода на новую скорость. После выбора этих двух параметров нажимаем кнопку "Init Port", в окошке консоли отобразится надпись "Port opened!".
Теперь необходимо добавить скомпилированную программу для загрузки в МК в формате *.hex. Файл формата *.hex автоматически создаётся в Keil при компиляции проекта, если в настройках проекта, вкладка Output, установлена галочка "Create HEX File".
Найти скомпилированный hex файл можно по пути корень_проекта/Objects. Программа мигания светодиодами led_blink находится в архиве, представленном в начале статьи. Обращаем внимание, что при создании своих проектов необходимо в настройках Keil, вкладка Target необходимо указывать следующие настройки для загрузки программы в область ОЗУ программ (Code Section)
для загрузки программы в область ОЗУ данных программ (Data Section).
Скомпилировав проект, добавим *.hex в программу Loader. Для этого нажимаем на кнопку "…" и выбираем файл led_blink.hex из примера мигания светодиодом. Выбираем пункт "Code Section" для загрузки программы в область ОЗУ программ и нажимаем кнопку "Set". Галочку "Load to Flash" не ставим. После нажатия на кнопку "Load" программа будет загружена в МК и начнётся её автоматическое выполнение.
Если при загрузке программы в МК не удается синхронизироваться (Sync error), необходимо выполнить следующие действия:
Для загрузки программы во внешнюю Flash память 1636РР3У в утилите Loader необходимо:
1. Нажать кнопку "…" и выбрать файл прошивки формата *.hex. Указать область «Code section», *.hex файл также должен быть сгенерирован для данной области. Установить галочку у опции «Load to Flash».
2. Нажать клавишу Set.
3. Установить на плате перемычку SPI SEL и нажать клавишу Load, после чего будет произведена загрузка в ОЗУ МК загрузчика Flash filefl.hex, который должен находиться в одном каталоге с программой.
4. После появления в консоли программы сообщения «Ready to load flash image!» нажать клавишу IMG load. Если программа имеет размер более 1024 слов, то она разбивается и загружается по частям.
Для проверки работы программы необходимо выключить питание на плате, изменить режим загрузки МК на SPI2+JB (MODE[7:0]=10011001) или SPI3+JA (MODE[7:0]=01011010), после чего снова включить питание на плате.
В первой ревизии МК 1923ВК014 интерфейс JTAG недоступен, поэтому для отладки программы в МК будем использовать удалённую отладку с помощью GDB по последовательному интерфейсу UART. Специальный проект для отладки led_blink_debug находится в архиве в начале статьи.
В GDB удалённая отладка возможна двумя способами: с использованием на целевой машине (МК) либо отладочной заглушки (GDB stub), либо программы GDB сервер (gdbserver). Последний вариант с GDB сервером работает только в Unix-подобных системах, поэтому для МК 1923ВК014 мы будем использовать отладочную заглушку. Отладочная заглушка представляет собой набор подпрограмм специального назначения, которые компилируются вместе с пользовательской программой, и реализуют удалённый последовательный протокол GDB. Подробнее про удалённую отладку в GDB можно прочитать на официальном сайте GNU (на английском), либо в книге "Отладка с помощью GDB", стр. 121 (на русском).
Отладочная заглушка (GDB stub) - это набор подпрограмм, выполняющих взаимодействие с ПК по протоколу GDB, и реализующее управление МК в зависимости от принимаемых с ПК команд (выполнить шаг, считать/записать значения регистров/памяти, установить/снять точку останова и т.д.). Все исходные файлы заглушки находятся в папке GDB.
Выполнение кода отладочной заглушки происходит, когда пользовательская программа остановлена. Основная функция GDB заглушки - это rt_hw_debugmon_exception(), однако пользовательская программа не должна вызывать её напрямую, для этого используется специальные ловушки. Чтобы исполнение GDB заглушки не было прервано аппаратными прерываниями от периферии, вход в функцию rt_hw_debugmon_exception() осуществляется в обработчике исключительных ситуаций - HardFaultHandler(). Для перехода в HardFaultHandler() в качестве ловушек используются недопустимые инструкции, например, 0xDEFE. Заглушка использует две запрещённые инструкции: 0xE7FF_DEFE - для программных точек останова и 0xE7FF_DEFF - для скомпилированных точек останова. Данные инструкции прописаны в файле arch_gdb.h. Скомпилированная точка останова вызывается с помощью функции gdb_bp(), в теле которой первой стоит запрещенная инструкция 0xE7FF_DEFF.
Таким образом, когда МК по ходу выполнения программы попадает на специальную ловушку (пытается выполнить запрещённую инструкцию), происходит переход в обработчик прерывания HardFaultHandler(), который описан в startup.s. В обработчике прерывания выполняется сохранение всех регистров ядра, после чего осуществляется переход в основную программу GDB заглушки, в которой происходит взаимодействие МК с ПК. МК не выйдет из программы заглушки, пока ПК не пошлёт соответствующую команду, например, "с" - продолжить выполнение программы.
Установка точки останова осуществляется заглушкой путём замены исходной инструкции на запрещённую инструкцию 0xE7FF_DEFE (ловушку). Таким образом, дойдя до точки останова МК попытается выполнить запрещённую инструкцию, свалится в HardFaultHandler() и управление перейдёт заглушке.
Взаимодействие отладочной заглушки с блоком UART осуществляется с помощью низкоуровневых функций gdb_uart_getc и gdb_uart_putc, которые описаны в файле hal_stub.c.
Отладчик GDB будем использовать из бесплатного набора инструментов GNU Embedded Toolchain for Arm. Скачать его можно по ссылке, я выбрал последнюю на тот момент версию 7 2018-q2-update.
Чтобы добавить в свой проект режим отладки, необходимо:
1. Подключить в проект все Си файлы из папки GDB/src. 2. Прописать в настройках Keil путь к заголовочным файлам: ./GDB/inc. 3. Подключить в main.c библиотеку GDB: #include "gdb_stub.h". 4. В начале main() вызвать функцию StartGDB(), которая инициализирует и включает UART для отладки. 5. Добавить начальную точку останова, вызвав функцию gdb_bp(). Данная точка останова будет использоваться для входа в режим отладки (должна находится после включения UART). 6. Использовать startup.s из примера led_blink_debug.
После компиляции программы её образ в формате *.hex зашивается в память МК, используя Loader, а образ в формате *.axf передается на исполнение программе клиенту на стороне ПК. Весь процесс отладки происходит в командной строке Windows. Чтобы запустить командную строку необходимо нажать сочетание клавиш "Пуск"+R и в открывшемся окне ввести CMD.
Чтобы запустить скомпилированный образ программы *.axf в GDB клиенте, необходимо перейти в папку с клиентом, в команде используется путь по умолчанию (здесь и далее представлены команды, которые необходимо ввести в командную строку):
cd C:\Program Files (x86)\GNU Tools ARM Embedded\7 2018-q2-update\bin
Вставка команды в консоль осуществляется кликом правой кнопкой мыши и выбором в открывшемся меню пункта "Вставить" .
Запускаем клиент с образом программы *.axf, расположенной по пути C:\CODE\Keil\1923BK014\led_blink_debug\Objects\led_blink_debug.axf. В названии папок должны использоваться только латинские буквы!
arm-none-eabi-gdb.exe C:\CODE\Keil\1923BK014\led_blink_debug\Objects\led_blink_debug.axf
Если всё прошло успешно и путь указан верно, должно появиться следующее сообщение
Теперь командная строка начинается с символов (gdb), означающие, что клиент GDB запущен, и все введённые команды обрабатываются им. Сначала необходимо настроить рабочую папку проекта, т.к. по умолчанию задана: C:\Program Files (x86)\GNU Tools ARM Embedded\7 2018-q2-update\bin. Нам же надо указать папку с проектом, в моём случае это C:\CODE\Keil\1923BK014\led_blink_debug. Проверить текущую рабочую папку можно командой "pwd"
cd C:\CODE\Keil\1923BK014\led_blink_debug pwd
Теперь необходимо задать настройки клиента на стороне ПК и установить соединение. В проекте мы настроили UART на скорость 115200, поэтому и здесь указываем такую же:
set serial baud 115200
Теперь нужно установить соединение по COM порту с МК, у меня он COM9 (перед этой операцией необходимо закрыть программу Loader, которая также использует порт для соединения с МК, иначе у нас не будет доступа к этому порту)
target remote COM9
В случае успешного подключения должно появиться следующее сообщение, программа в этот момент находится в начальной точке останова, указанной функцией gdb_bp()
Чтобы посмотреть листинг функции main введём команду
list main
Однако по умолчанию выводится только 10 строк кода, чтобы продолжить вывод кода, необходимо либо ввести команду "list", либо нажать клавишу Enter. Можно также задать произвольное количество строк выводимого кода командой:
set listsize N
где N - количество строк. В клиенте можно также устанавливать программные точки останова, привязанные к номеру строки. Для этого сначала нужно снова вывести листинг функции main командой:
list main
Сразу после вывода кода можно указать точку останова, например, на строке 36, командой
break 36
Эту команду необходимо вводить только после вывода кода функции, т.к. номер строки 36 считывается именно из кода выведенной функции.
Чтобы запустить выполнение программы, выполним команду:
с
Программа зайдёт в цикл while, мигнёт светодиодами, дойдёт до 36 строки и остановится, а в консоль будет выведено сообщение
Другие нужные команды для работы с точками останова:
info breakpoints // Вывести в консоль все поставленные программно точки останова delete breakpoints N // Удалить N точку останова, если ввести без аргумента N, то удалятся все точки останова
Чтобы выйти из режима отладки необходимо ввести команду:
detach
Выход из программы клиента GDB осуществляется командой:
quit
Полный набор команд приведён на официальном сайте клиента GDB.