Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Кармин Новиелло - Освоение STM32.pdf
Скачиваний:
2739
Добавлен:
23.09.2021
Размер:
47.68 Mб
Скачать

Введение в отладку

147

наших проектов. Однако глубокое понимание того, как работает полухостинг, может значительно упростить процесс отладки в определенных критических операциях.

В следующем параграфе будет дано краткое объяснение того, как настроить наш проект Eclipse для использования полухостинга в нашем коде. Это позволит нам печатать сообщения на консоли OpenOCD. Это фантастический инструмент отладки, особенно в ситуациях, когда вам нужно понять, что происходит с вашей микропрограммой.

5.2.1. Включение полухостинга в новом проекте

Плагин GNU MCU позволяет легко включить поддержку полухостинга при генерации проекта. Мы уже сталкивались с данными опциями, но для простоты мы не беспокоились о них. Сейчас самое время рассмотреть их. Давайте создадим новый проект.

Рисунок 17: Настройки проекта, необходимые для включения полухостинга

Перейдите в меню File → New → C Project. Выберите тип проекта Hello World ARM Cortex-M C/C++ и выберите название проекта, которое вам нравится. На следующем шаге заполните связанные с ядром Cortex-M поля в соответствии с вашей целевой пла-

той. Выберите «Freestanding (no POSIX system calls)» для поля Use system calls и «Semihosting DEBUG channel» для поля Trace output. Продолжайте работу с мастером проекта до его завершения. Затем импортируйте HAL от ST и «скелет» проекта из CubeMX, как описано в Главе 4.

Теперь у нас есть проект, готовый к использованию полухостинга. Процедуры трассировки доступны в файле system/src/diag/Trace.c. Среди них:

trace_printf(): это эквивалент функции Си printf(). Она позволяет форматиро-

вать строку с переменным числом параметров и принимает то же соглашение о форматировании строки языка программирования Си.

trace_puts(): записывает строку в консоль отладки, автоматически заканчивая ее

символом конца строки '\n'.

trace_putchar(): записывает один символ в консоль отладки.

trace_dump_args(): это удобная процедура, которая автоматически печатает аргу-

менты командной строки.

Введение в отладку

148

В следующем примере показано, как использовать функцию trace_printf().

 

Имя файла: src/main-ex1.c

34#include "stm32f4xx_hal.h"

35#include "diag/Trace.h"

36

37void SystemClock_Config(void);

38static void MX_GPIO_Init(void);

40int main(void)

41{

42char msg[] = "Hello STM32 lovers!\n";

44HAL_Init();

45SystemClock_Config();

46MX_GPIO_Init();

47

 

48

trace_printf(msg);

49

 

50

while(1) {

51

HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);

52

HAL_Delay(500);

53}

54}

Прежде всего, чтобы использовать процедуры трассировки, мы должны правильно импортировать заголовочный файл Trace.h, как это сделано в строке 35. Далее, в строке 48 мы вызываем функцию trace_printf(), передающую строку для печати. Остальная часть main() просто бесконечно мигает светодиодом LD2 платы Nucleo.

Прочитайте внимательно

Реализация полугостинга в OpenOCD разработана таким образом, что каждая строка должна заканчиваться символом конца строки (\n), прежде чем строка появится в консоли OpenOCD. Это достаточно распространенная ошибка, которая приводит к большим разочарованиям, когда программисты начинают его использовать впервые. Никогда не забывайте завершать каждую строку, переданную в trace_printf() или процедуру Си printf() при помощи (\n).

Чтобы использовать полухостинг, нам нужно сделать еще один важный шаг: мы должны дать OpenOCD команду включить его. Создайте новую конфигурацию отладки, как показано в предыдущих параграфах, но убедитесь, что в разделе Startup включена опция Enable ARM semihosting, как показано на рисунке 9 (эта опция стоит по умолчанию, но лучше посмотреть). Хорошо. Теперь мы готовы запустить нашу микропрограмму. Строка "Hello STM32 lovers!" появится в консоли OpenOCD, как показано на

рисунке 18.

Введение в отладку

149

Рисунок 18: Выходная строка, поступающая из Nucleo и отправленная на консоль OpenOCD

Иногда бывает так, что консоль OpenOCD не отображается автоматически при печати сообщения, но консоль GDB остается активной. Вы можете переключиться на консоль OpenOCD, щелкнув на значок консоли (обведен красным на изображении ниже).

Этот режим можно изменить, перейдя в глобальные настройки Eclipse →

Run/Debug → Console и выбрав флажок Show when program writes to standard out.

5.2.1.1.Использование полухостинга со Стандартной библиотекой Си

Библиотека среды выполнения Си предоставляет несколько функций, используемых для манипулирования вводом/выводом, например, процедуры printf()/scanf() для управления выводом/вводом терминала и функции манипулирования файлами (fopen(), fseek() и т. д.). Данные функции построены на низкоуровневых сервисах, предоставляемых базовой операционной системой, также называемых системными вызовами.

Приложения STM32, разработанные с помощью GCC, автоматически связаны с newlibnano – облегченной версией стандартной библиотеки C/C++, специально предназначенной для работы с микроконтроллерами. newlib-nano не обеспечивает реализацию низкоуровневых системных вызовов. Мы несем ответственность за реализацию данных функций, если нам нужно их использовать. Поскольку на целевой плате отсутствуют возмож-

Введение в отладку

150

ности управления терминалом (нет экрана и нет устройств ввода), мы можем использовать полухостинг для маршрутизации этих низкоуровневых функций на отладчик хоста, то есть OpenOCD.

Рисунок 19: Как системные вызовы направляются в отладчик с использованием полухостинга

Рисунок 19 четко показывает весь процесс. Например, давайте рассмотрим функцию printf(). Когда мы вызываем ее в нашей микропрограмме, newlib передает управление процедуре _write(). Итак, мы должны предоставить нашу реализацию этой функции, отправляющей строку в OpenOCD, которая, в свою очередь, отображает ее на консоли хост-ПК.

Ливиу Ионеску уже добавил в свой плагин наиболее часто используемые низкоуровневые системные вызовы. Нам нужно только включить их компиляцию, и мы можем начать использовать классическую среду манипуляции вводом/выводом в Си. Чтобы включить ее, зайдите в меню Project → Properties. Затем перейдите в раздел C/C++ Build → Settings. В разделе Optimization снимите флажок предположения среды авто-

номной Assume freestanding environment (-ffreestanding). Нажмите кнопку OK, пе-

рейдите в Project → Clean.. и пересоберите весь проект.

Что именно означает Автономная среда?

Стандарт Си не только точно определяет основной язык, но также характеризует некоторые библиотеки, считающиеся неотъемлемой частью самого языка. Например, управление строками, сортировка и сравнение, манипулирование символами и подобные сервисы неизменно ожидаются во всех реализациях компиляторов Си. Некоторые из этих библиотек неизбежно зависят от базовых операционных систем. Например, почти невозможно говорить о процедурах манипулирования файлами без базового понятия файловая система (open(), write() и т. д.). То же самое происходит с функциями управления терминалами (printf(), scanf() и т. д.).

Стандарт определяет размещенную среду (hosted environment) как среду выполнения, которая предоставляет все стандартные функции библиотеки, включая те функции, которым для выполнения своей задачи требуются некоторые

Введение в отладку

151

базовые службы ОС. Вместо нее он определяет автономную среду (freestanding environment) как среду выполнения, которая не зависит от операционной системы, и, следовательно, она не предоставляет все те стандартные библиотечные функции, которые связаны с «более низкоуровневыми» действиями.

При написании кода приложений для пустых систем, англ. bare metal (то есть при разработке приложений для встроенных устройств, таких как платформа STM32), принято допускать автономную среду. В противном случае мы несем ответственность за предоставление тех низкоуровневых процедур (_write(), _seek() и т. д.), которые стандартная библиотека принимает в своих функциях стандартной библиотеки.

Следующий код можно использовать, чтобы проверить, все ли работает корректно.

Имя файла: src/main-ex2.c

34#include "stm32f4xx_hal.h"

35#include <string.h>

36

37void SystemClock_Config(void);

38static void MX_GPIO_Init(void);

40int main(void)

41{

42char msg[20], name[20];

44HAL_Init();

45SystemClock_Config();

46MX_GPIO_Init();

47

48printf("What's your name?: \r\n");

49scanf("%s", name);

50sprintf(msg, "Hello %s!\r\n", name);

51printf(msg);

52

53FILE *fd = fopen("/tmp/test.out", "w+");

54fwrite(msg, sizeof(char), strlen(msg), fd);

55fclose(fd);

Код действительно говорит сам за себя. Он использует стандартные функции Си, такие как printf() и scanf(), для печати и считывания строки из консоли OpenOCD (строки 4851). Затем он открывает файл test.out в папке /tmp на хост-ПК12 и записывает в него ту же строку (строки 53-55).

Данная возможность чрезвычайно полезна во многих ситуациях. Например, ее можно использовать для регистрации действий микропрограммы в файле на ПК для целей отладки. Другой пример – когда веб-сервер работает на целевой плате, а все HTML-файлы находятся на хост-ПК: вы можете свободно изменять их для проверки того, как они выполняют разметку, без необходимости повторного перепрограммирования целевого файла при каждом его изменении.

12 Пользователи Windows должны соответствующим образом изменить путь. Например, используйте C:\Temp\test.out в качестве имени файла.