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

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

152

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

Если у вас есть существующий проект и вы хотите включить полухостинг, вам необходимо выделить два случая.

Первый более простой. Если вы сгенерировали проект с помощью плагина GNU MCU, вам нужно всего лишь добавить следующий глобальный макрос в настройках проекта:

Если вы хотите использовать только функции trace_printf() от Ливиу Ионеску,

добавьте макросы TRACE и OS_USE_TRACE_SEMIHOSTING_DEBUG.

Если вы хотите использовать функции манипулирования вводом/выводом из стандартной библиотеки Си, добавьте макрос OS_USE_SEMIHOSTING и снимите фла-

жок Assume freestanding environment (-ffreestanding).

Второй случай более сложный. У вас есть существующий проект, импортированный в Eclipse, который не был создан с помощью плагина Eclipse GNU MCU. Если достаточно использовать функцию trace_printf(), то вы можете импортировать в свой проект следующие файлы, взятые из проекта, сгенерированного с помощью плагина GNU MCU:

src/diag/trace_impl.c

src/diag/Trace.c

include/diag/Trace.h

Затем вы должны определить макросы TRACE и OS_USE_TRACE_SEMIHOSTING_DEBUG на уровне проекта и вызвать процедуру initialise_monitor_handles() в вашей процедуре main().

Если вы хотите использовать все стандартные процедуры ввода/вывода библиотеки Си, вам необходимо:

импортировать в свой проект файл src/newlib/_syscalls.c;

определить макрос OS_USE_SEMIHOSTING на уровне проекта;

снять флажок Assume freestanding environment (-ffreestanding);

вызвать процедуру initialise_monitor_handles() в вашей процедуре main().

5.2.3. Недостатки полухостинга

Полухостинг – отличная функция, но он также имеет несколько недостатков. Прежде всего, он работает только во время сеанса отладки, и полностью «подвешивает» микропрограмму, если она не работает под управлением GDB. Например, загрузите один из предыдущих примеров на вашу плату Nucleo и завершите сеанс отладки. Если вы перезагрузите плату, нажав кнопку RESET, светодиод LD2 не будет мигать. Это происходит потому, что микропрограмма зависла в процедуре trace_printf() (подробнее о том, почему это происходит в следующем параграфе). Это достаточно распространенная проблема, с которой сталкивается каждый новичок всякий раз, когда начинает работать с платформой STM32.

Еще один важный аспект, который следует иметь в виду, заключается в том, что полухостинг оказывает большое влияние на производительность программного обеспечения. Каждый вызов полухостинга затрачивает несколько тактовых циклов ЦПУ, и он влияет на общую производительность. Более того, эти затраты непредсказуемы, поскольку они включают в себя действия, которые происходят вне потоков выполнения микроконтроллера (подробнее об этом в следующем параграфе).

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

153

В Главе 8 мы увидим еще один интересный способ обмена сообщениями с хост-ПК с помощью одного из USART STM32.

5.2.4. Как работает полухостинг

Если вы новичок в мире STM32 и вас немного смущает его первоначальная сложность, вы можете перестать читать данный параграф и перейти к следующей главе. Здесь мы будем описывать сложную тему, которая требует небольшого понимания того, как работает архитектура ARM, и некоторых продвинутых функций GCC. Вам не обязательно читать данный параграф, но если вы рассмотрите его, это может улучшить ваше общее понимание.

Существует несколько способов реализовать возможности полухостинга. Одним из них является использование программных точек останова. ARM Cortex-M предлагает два типа точек останова: аппаратные (HBP) и программные (SBP).

HBP устанавливаются программированием модуля точек останова (аппаратного модуля внутри каждого ядра Cortex-M) для мониторинга шин ядра с целью выборки команд из определенной ячейки памяти. HBP могут быть установлены в любом месте в ОЗУ или ПЗУ с использованием внешнего физического программатора, подключенного к интерфейсу отладки. В случае платы Nucleo встроенный программатор ST-LINK подключен к интерфейсу отладки микроконтроллера, и он, в свою очередь, управляется OpenOCD. На рисунке 20 показана взаимосвязь между внешним отладчиком и внутренним модулем отладки микроконтроллера.

Рисунок 20. Компоненты отладки в микроконтроллерах Cortex-M

SBP реализуются добавлением специальной инструкции bkpt непосредственно перед кодом, который мы хотим проверить. Когда ядро выполняет инструкцию точки останова, оно переводится в состояние отладки. Отладчик видит, что микроконтроллер приостановлен, и начинает его отладку. Инструкция bkpt принимает немедленный 8-бит- ный код операции (immediate 8-bit opcode), который может использоваться для указания какого-либо условия прерывания. Если вы хотите остановить выполнение вашей микропрограммы и передать управление отладчику, то инструкция:

asm("bkpt #0")

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

154

то, что вам нужно. Данный метод используется для реализации программной условной точки останова. Например, предположим, что у вас есть странное условие (condition) отказа, которое вам нужно проверить. Вы можете применить фрагмент кода, подобный следующему:

if(cond == 0) {

...

}else if(cond > 0) {

...

}else { /* Ненормальное состояние, давайте отладим его */

asm("bkpt #0");

}

В приведенном выше коде, если переменная cond принимает отрицательное значение, микроконтроллер останавливается и управление передается GDB, что позволяет нам проверять стек вызовов и текущий стековый кадр.

Полухостинг реализован с использованием специального немедленного кода операции 0xAB. То есть инструкция:

asm("bkpt #0xAB")

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

asm (

"mov r0, 0x4 \n /* код операции для записи строки с завершающим нулем */ "mov r1, 0x20001400 \n" /* адрес строки для передачи в OpenOCD */

"bkpt #0xAB"

);

В таблице 3 приведены поддерживаемые операции полухостинга. Пожалуйста, обратите внимание, что OpenOCD в настоящее время не поддерживает все из них.

Следующий полный код Cи показывает, как реализовать функцию trace_printf().

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

34 #include "stm32f4xx_hal.h"

35

36void SystemClock_Config(void);

37static void MX_GPIO_Init(void);

39int main(void)

40{

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

43HAL_Init();

44SystemClock_Config();

45MX_GPIO_Init();

 

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

155

46

 

 

47

asm volatile (

 

48

" mov

r0, 0x4 \n"

49

" mov

r1, %[msg] \n"

50

" bkpt #0xAB"

51

:

 

52

: [msg]

"r" (msg)

53

: "r0",

"r1"

54

);

 

55

 

 

56while(1);

57}

Здесь мы используем возможности функции GCC asm() для передачи указателя на бу-

фер msg, содержащий строку "Hello STM32 lovers!\n".

Теперь вы можете понять, почему при полухостинге микроконтроллер зависает, если отладчик не активен. Инструкция bkpt останавливает выполнение микроконтроллера, и восстановить его невозможно без использования внешнего отладчика (или аппаратного сброса). Более того, каждый раз, когда выдается команда bkpt, внутренние действия микроконтроллера приостанавливаются до тех пор, пока управление не перейдет к отладчику. В течение этого времени важные асинхронные события (например, прерывания, генерируемые периферийными устройствами) могут быть потеряны. Этот интервал времени абсолютно непредсказуем и зависит от многих факторов (скорость аппаратного интерфейса, текущая загрузка хост-ПК, скорость микропрограммы ST-LINK и т. д.).

 

Таблица 3: Сводка операций полухостинга

Операция полухостинга

Немедленный оп. код

Описание

 

 

 

EnterSVC

0x17

Устанавливает процессор в режим супервизора

 

 

и отключает все прерывания, устанавливая обе

 

 

битовые маски прерываний в новом CPSR.

ReportException

0x18

Данный SVC может вызываться приложением,

 

 

чтобы напрямую сообщить об исключении от-

 

 

ладчику. Наиболее распространенное использо-

 

 

вание – сообщить о завершении выполнения,

 

 

используя ADP_Stopped_ApplicationExit.

SYS_CLOSE

0x02

Закрывает файл в хост-системе. Обработчик

 

 

должен ссылаться на файл, который был открыт

 

 

с помощью SYS_OPEN.

SYS_CLOCK

0x10

Возвращает количество сотых долей секунды с

 

 

момента начала выполнения.

SYS_ELAPSED

0x30

Возвращает количество прошедших целевых

 

 

тиков с момента начала выполнения. Исполь-

 

 

зуйте SYS_TICKFREQ, чтобы определить частоту

 

 

тиков.

SYS_ERRNO

0x13

Возвращает значение переменной errno биб-

 

 

лиотеки Си, связанной с реализацией хоста для

 

 

SVC полухостинга.

SYS_FLEN

0x0C

Возвращает длину указанного файла.

SYS_GET_CMDLINE

0x15

Возвращает командную строку, используемую

 

 

для вызова исполняемого файла, то есть argc и

 

 

argv.

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

156

Таблица 3: Сводка операций полухостинга (продолжение)

Операция полухостинга

Немедленный оп. код

Описание

 

 

 

SYS_HEAPINFO

0x16

Возвращает системный стек и параметры кучи.

 

 

Возвращаемые значения обычно являются зна-

 

 

чениями, используемыми библиотекой Си во

 

 

время инициализации.

SYS_ISERROR

0x08

Определяет, является ли код возврата от другого

 

 

вызова полухостинга состоянием ошибки или

 

 

нет. Этот вызов передает блок параметров, со-

 

 

держащий код ошибки для изучения.

SYS_ISTTY

0x09

Проверяет, подключен ли файл к интерактив-

 

 

ному устройству.

SYS_OPEN

0x01

Открывает файл в хост-системе. Путь к файлу

 

 

указывается либо относительно текущего ката-

 

 

лога хост-процесса, либо как абсолютный, ис-

 

 

пользуя соглашения о путях операционной си-

 

 

стемы хоста.

SYS_READ

0x06

Считывает содержимое файла в буфер.

SYS_READC

0x07

Считывает байт из консоли.

SYS_REMOVE

0x0E

Удаляет указанный файл в системе регистрации

 

 

документов (filing system) хоста.

SYS_RENAME

0x0F

Переименовывает указанный файл.

SYS_SEEK

0x0A

Ищет указанную позицию в файле, используя

 

 

смещение, указанное с начала файла. Предпола-

 

 

гается, что файл является байтовым массивом, а

 

 

смещение задается в байтах.

SYS_SYSTEM

0x12

Передает команду интерпретатору командной

 

 

строки хоста. Это позволяет вам выполнить си-

 

 

стемную команду, такую как dir, ls или pwd.

 

 

Ввод/вывод терминала находится на хосте и не

 

 

виден для целевого устройства.

SYS_TICKFREQ

0x31

Возвращает частоту тиков.

SYS_TIME

0x11

Возвращает количество секунд с 00:00 1 января

 

 

1970 года.

SYS_TMPNAM

0x0D

Возвращает временное имя для файла, иденти-

 

 

фицированного системным идентификатором

 

 

файла.

SYS_WRITE

0x05

Записывает содержимое буфера в указанный

 

 

файл в текущей позиции файла. Текущая реа-

 

 

лизация OpenOCD ожидает, что буфер заверша-

 

 

ется символом конца строки (\n).

SYS_WRITEC

0x03

Записывает символьный байт, на который ука-

 

 

зывает R1, в канал отладки. При выполнении в

 

 

отладчике ARM символ появляется на консоли

 

 

отладчика хоста.

SYS_WRITE0

0x04

Записывает строку с завершающим нулем в ка-

 

 

нал отладки. При выполнении в отладчике ARM

символы появляются на консоли отладчика хоста.