Информационный портал технической поддержки Центра проектирования интегральных микросхем |
Для отладки часто используется функция printf(), которая выводит какое-нибудь сообщение или статус, раскрывающий внутреннюю работу программы. Поскольку, в отличие от ПК, в микроконтроллере нет монитора, и стандартный поток вывода STDOUT никуда не привязан, то для того, чтобы функция printf() работала, необходимо указать ей, куда выводить данные. Это реализуется через определение функции fputc(). В этой функции fputc() необходимо реализовать вывод символа char туда, где будут приниматься данные из МК. Чаще всего реализуют вывод сообщений в подключенный UART, от которого сообщения по RS-232 идут в COM-порт ПК и затем отображаются на экране в программе работы с COM-портом (например, PuTTY). Подробнее об этом способе описано в статье Printf через UART.
Однако, в Cortex-M3 и выше есть встроенный серийный порт отладки, который называется ITM (Instrumentation Trace Macrocell). Данные, записываемые в регистры модуля, передаются отладчику по интерфейсу ITM и отображаются на экране в среде разработки.
В данной статье рассматриваются настройки среды Keil, необходимые для вывода информации через ITM с использованием функции printf(). Для этого можно использовать МК, в которых реализован порт ITM, а именно МК К1986ВЕ92QI и К1901ВЦ1QI (так как в нём использовано RISC-ядро, аналогичное ядру в основе К1986ВЕ92QI). В качестве отладчика могут использоваться CMSIS-DAP, J-LINK, ULINK2.
Интерфейс ITM работает только в SWD ( Serial Wire Debug) режиме отладчика!
Для того чтобы вывести отладочные данные в модуль ITM, обычно к проекту подключается файл типа retarget.c, в котором реализуется функция fputc(), перенаправляющая символ в регистр ITM.
Листинг файла retarget.c:
#include <stdio.h>
#include "MDR32F9Q2I.h"
struct __FILE
{
int handle;
};
FILE __stdin, __stdout;
volatile int32_t ITM_RxBuffer = 0x5AA55AA5; // Initialize as EMPTY
int fgetc(FILE *f)
{
char tmp;
while(ITM_CheckChar() == 0); // Wait if buffer is empty
tmp = ITM_ReceiveChar();
if(tmp == 13)
tmp = 10;
return ITM_SendChar(tmp);
}
int fputc(int c, FILE *f)
{
ITM_SendChar(c);
return c;
}
Сами функции ITM_SendChar, ITM_ReceiveChar, ITM_CheckChar уже реализованы Keil в файле core_cm3.h, то есть являются частью функционала ядра.
Есть и более простой способ вывести информацию от printf() через ITM - средствами Keil.
Перенаправление стандартных потоков ввода-вывода можно сделать в окне Manage Run-Time Environment, как показано на рисунке 1.
Рисунок 1 - Настройка потоков ввода-вывода в Manage Run-Time Environment
Пояснения к рисунку 1.
Теперь нужно настроить сам интерфейс ITM, как показано на рисунке 2.
Рисунок 2 - Настройка порта ITM для отладчика J-LINK
Пояснения к рисунку 2.
Важно, чтобы указанная частота в поле "Core Clock" совпадала с частотой, на которой будет работать МК в режиме отладки. Если частота будет указана неправильно, внизу экрана Keil будет статус "Trace: Communication Error". Также не всегда автоматическое определение частоты SWO работает корректно, поэтому рекомендуется установить настройки SWO (Settings SWO) вручную, как показано на рисунке 2. Для J-LINK максимальная частота SWO составляет 6 МГц, для ULINK2 и CMSIS-DAP - 1 МГц.
Теперь переходим к отладке проекта. Последовательность запуска отладки представлена на рисунке 3.
Рисунок 3 - Отладка проекта с использованием вывода информации через ITM
Пояснения к рисунку 3.
Как видно из рисунка 3, иногда самый первый символ при старте программы пропадает. Вероятно, требуется какое-то время на синхронизацию интерфейса ITM, так как после этого все сообщения доходят без потерь.
Также, если в конце выводимой строки не указать символ "\n", то строка может быть не выведена сразу в окно "Debug (printf) Viewer".
Сайт: | https://support.milandr.ru |
E-mail: | support@milandr.ru |
Телефон: | +7 495 221-13-55 |