Технология Real Time Transfer (RTT) от SEGGER предназначена для мониторинга системы и интерактивного ввода/вывода пользователя во встраиваемых приложениях. RTT сочетает достоинства SWO и семихостинга с очень высоким быстродействием.
Примечание: незнакомые термины и сокращения см. в Словарике [7].
Основные возможности RTT:
• Двунаправленный обмен с приложением MCU. • Очень высокая скорость передачи, без влияния на поведение приложения в реальном времени. • Для обмена используется канал отладчика. • Не требуется дополнительных выводов и дополнительной аппаратуры на стороне MCU. • Поддерживается любой моделью отладчика J-Link. • Поддерживается архитектурами ARM Cortex-M0/M0+/M1/M3/M4/M7/M23/M33 и Renesas RX100/200/600. • Полная реализация кода, обеспечивающая функциональность и свободу.
[Что такое RTT]
С помощью RTT можно выводить информацию из целевого MCU, и также передавать данные в его приложение на очень высокой скорости, не влияя на поведение приложения, в реальном времени. SEGGER RTT может использоваться с любой моделью адаптера J-Link и любым поддерживаемым целевым MCU, который обеспечивает фоновый доступ к памяти (архтектуры Cortex-M и RX).
RTT поддерживает несколько каналов для передачи данных в обоих направлениях (от MCU в сторону хоста отладки и обратно). Эту возможность можно использовать для разных целей, предоставляя пользователю максимальную свободу действий.
Реализация по умолчанию использует один канал на направление, которые предназначены для печатающего ввода и вывода терминала. Утилита J-Link RTT Viewer может использовать этот канал для организации нескольких "виртуальных" терминалов, что позволяет печатать в несколько окон. Например, одно окно используется для стандартного вывода (standard output), еще одно для сообщений об ошибках (error output), и одно для вывода сообщений отладки (debugging output) - только с одним буфером на целевом MCU. Дополнительный up-канал (в сторону хоста отладки) может использоваться, например, для отправки данных профайлинга или трассировки событий.
Канал
Обычное применение
UP Channel 0
Отладочный вывод в терминал из firmware MCU
DOWN Channel 0
Клавиатурный ввод на хосте PC, передаваемый в MCU
[Коммуникации RTT]
Обмен данными с помощью RTT на целевом MCU может осуществляться с различными приложениями. Эта функциональность может быть даже интегрирована в пользовательские программы при использовании J-Link SDK.
Применение RTT в приложении MCU довольно простое. Соответствующий код доступен для свободной загрузки, и может быть интегрирован в существующие приложения.
Для коммуникаций через RTT может использоваться любой J-Link. Простой способ обмена через терминал (Channel 0) - создать на хосте отладки соединение localhost:19021 через telnet-клиент, когда активно подключение MCU к адаптеру J-Link (например, во время сессии отладки).
J-Link Software Package поставляется с дополнительными продвинутыми примерами приложений для разных применений.
J-Link RTT Viewer. J-Link RTT Viewer это основная GUI-утилита Windows, предназначенная для использования возможностей RTT на хосте отладки.
RTT Viewer может использоваться либо самостоятельно, путем открытия собственного соединения с J-Link и целевым MCU, или параллельно с работающей сессией отладки, путем подключения к ней и использования уже открытого соединения с J-Link.
RTT Viewer поддерживает все основные функции RTT:
• Вывод в терминал через Channel 0. • Отправка текста на ввод через Channel 0. • До 16 виртуальных терминалов только с одним каналом целевого MCU. • Управление выводом текста: цветной текст, очистка экрана консоли. • Лог данных через Channel 1.
Для получения полной документации по J-Link RTT Viewer загрузите руководство пользователя J-Link [2] обратитесь к главе, посвященной RTT. J-Link RTT Viewer входит как часть в пакет ПО и документации J-Link [3], свободно доступный для загрузки.
J-Link RTT Client. Утилита J-Link RTT Client работает как telnet-клиент, однако в отличие от обычной программы telnet пытается восстановить соединение с J-Link, когда сессия отладки закрыта. J-Link RTT Client входит как часть в пакет ПО и документации J-Link [3] для операционных систем Windows, Linux и macOS.
J-Link RTT Logger. С помощью утилиты J-Link RTT Logger данные, поступающие из Up-Channel 1, могут быть прочитаны и записаны в файл. Этот канал может использоваться, например, для отправки на хост отладки данных анализа производительности. J-Link RTT Logger открывает выделенное соединение с адаптером J-Link, и может использоваться самостоятельно, без запуска отладки.
Логгер RTT входит как часть в пакет ПО и документации J-Link [3] для операционных систем Windows, Linux и macOS. Исходный код логгера может использоваться как начальная точка интеграции функций RTT в другие приложения PC, наподобие отладчиков и компонентов J-Link SDK.
[Как работает RTT]
Реализация на MCU. Real Time Transfer использует структуру блока управления (SEGGER RTT Control Block), расположенную в памяти целевого MCU, для поддержки операций чтения и записи данных. Блок управления содержит ID, чтобы его можно было найти подключенному J-Link. Также блок управления и содержит структуру кольцевого буфера для каждого доступного канала, описывающую буфер канала и его состояние.
Максимальное количество доступных каналов может быть сконфигурировано во время компиляции, и каждый буфер может быть сконфигурирован и добавлен приложением во время выполнения в реальном времени (run time). Буферы "вверх" и "вниз" могут обрабатываться отдельно.
Каждый канал может быть сконфигурирован для работы с блокированием и без блокирования выполнения. В блокирующем режиме приложение будет ждать, когда буфер заполнится, до тех пор, пока не удастся записать всю память, что приведет к блокировке состояния приложения, но в то же время предотвращает потерю данных. В неблокирующем режиме записываются только те данные, которые помещаются в буфер, или вообще не записываются, и остальная часть отбрасывается. Это позволяет работу в реальном времени, даже когда отладчик не подключен. Разработчику в этом случае не нужно создавать специальную отладочную версию разрабатываемого firmware, и отладочный код может оставаться в релизе приложения.
Место размещения Control Block. Когда работа RTT активна на PC хоста отладки, либо прямым использованием RTT с помощью приложения наподобие RTT Viewer [5], или путем подключения через Telnet к приложению, которое отлаживает firmware с использованием J-Link, наподобие отладчика, то J-Link автоматически ищет SEGGER RTT Control Block в известных регионах RAM целевого MCU. Эти регионы RAM или определенный адрес места нахождения Control Block можно также установить через приложения хоста отладки PC, чтобы ускорить процесс детектирования Control Block, или если Control Block не может быть найден автоматически.
Внутренние структуры. На рисунке ниже показана упрощенная структура памяти целевого MCU.
Здесь может быть любое количество как дескрипторов буфера вверх, "Up Buffer Descriptors" (Target -> Host), так и дескрипторов буфера вниз, "Down Buffer Descriptors" (Host -> Target). Размер каждого буфера можно конфигурировать индивидуально. Серые области в буферах это места, которые содержат достоверные данные. Для буферов вверх, указатель записи (Write Pointer) записывается целевым MCU, а указатель чтения (Read Pointer) записывается через адаптер отладки (хостом PC через J-Link). Когда указатели чтения и записи указывают на один и тот же элемент, буфер пуст. Это гарантирует отсутствие состояния конкурентного доступа (race condition).
Требования к использованию. SEGGER RTT не нуждается ни в каких дополнительных выводов целевого MCU или дополнительного оборудования, несмотря на то, что J-Link подключен через стандартный порт отладки целевого MCU. RTT не требует какой-либо конфигурации целевого MCU или среды отладки, и может даже использоваться с изменениями скоростей работы целевого MCU.
RTT может работать как параллельно с активной сессией отладки (без нарушения её работы), так и без какой-либо IDE или программного отладчика.
[Производительность RTT]
Быстродействие SEGGER RTT значительно выше, чем у любой другой технологии, используемой для вывода данных в хост отладки PC. Вывод строки среднего размера может занимать одну микросекунду или меньше. Обычно занимаемое время соответствует времени выполнения одного вызова memcopy().
На картинке ниже показано сравнение, выполненное на STM32F407 Cortex-M4, работающего с тактовой частотой 168 МГц. Удалена загрузка процессора на выполнение вызовов printf().
Скорость перемещения данных. Максимальная скорость, на которой данные могут быть отправлены хосту отладки PC, зависит от размера буфера целевого MCU и скорости его интерфейса отладки. Даже с маленьким буфером 512 байт скорость RTT доходит до 1 MiB/s на высокой скорости интерфейса, и 0.5 MiB/s на обычной модели адаптера J-Link.
Размер буфера MCU. Буфер RTT канала "вверх" (MCU -> хост PC) может быть относительно небольшим. Требуемый минимальный размер буфера может быть аппроксимирован по количеству данных, записанных в 1 миллисекунду, и максимальный размер определяется тем, сколько будет передано за одно действие записи. Если посылаемые данные менее часто, то в буфере должно быть достаточно места для данных, которые записываются за одно действие. Если данные посылаются более часто, то размер буфера должен быть достаточен, чтобы пропустить максимальное количество данных, записанных в течение одной миллисекунды. Диаграмма показывает требуемый минимальный размер буфера, когда отправляются разные количества данных - случайным образом, каждые 100 мкс и каждую 1 мс.
Отправка каждые 100 мкс
Отправка каждую 1 мс
Байт/запись
Байт/мс
Размер буфера
Байт/запись
Байт/мс
Размер буфера
1
10
6
10
10
11
2
20
11
20
20
21
5
50
31
50
50
51
10
100
61
100
100
101
20
200
101
200
200
201
50
500
401
500
500
501
Показанные значения были измерены на J-Link PRO V4, на скорости JTAG 36 МГц. Отладочная плата и целевой MCU: SEGGER emPower eval board с процессором NXP K66, работающим на частоте 168 МГц.
Расход памяти. Код для реализации RTT занимает примерно 500 байт ROM и 24 байта ID + 24 байта на канал для Control Block в RAM. Каждому каналу необходим некоторый объем RAM для буфера. Рекомендуемый размер 1 килобайт для каналов "верх" и от 16 до 32 байт для каналов "вниз", в зависимости от нагрузки ввода/вывода.
Память
Используемый объем
ROM (FLASH)
~500 байт
RAM
24 байта постоянно + (24 + SizeofBuffer) байт на канал
[Реализация RTT]
Поддержка SEGGER RTT написана на ANSI C, и он может быть интегрирован в любое встраиваемое приложение с помощью кода, который можно загрузить с сайта SEGGER.
RTT легко и просто применять через его API. Можно даже переназначить стандартные функции printf() для использования RTT. Использование RTT уменьшает время отработки printf() до минимума, и позволяет делать печать отладочной информации на хост PC, в то время как приложение firmware выполняет в реальном времени задачи, критичные по времени выполнения.
Реализация SEGGER RTT включает в себя простую реализацию printf(), которая может использоваться для записи результата обработки форматированной строки через RTT. SEGGER_RTT_Printf() меньше, чем большинство библиотечных реализаций printf, не требует наличия кучи (heap), и занимает только лишь конфигурируемое пространство из стека.
Реализация SEGGER RTT конфигурируется полностью через директивы #define препроцессора. Операции чтение и записи могут быть сделаны безопасными для задач (task-safe) с использованием подпрограмм Lock() и Unlock(), несколькими буферами, и также можно легко настроить размер буферов терминала.
Код RTT для целевого MCU поставляется как часть пакета программного обеспечения и документации J-Link (J-Link Software and Documentation Pack), который можно загрузить по ссылке [3]. Модули исходного кода RTT можно найти в каталоге Samples/RTT пакета ПО J-Link.
API-функции RTT:
Имя функция
Описание
SEGGER_RTT_Read()
Чтение данных из буфера ввода.
SEGGER_RTT_Write()
Запись данных в буфер вывода.
SEGGER_RTT_WriteString()
Запись ASCIIZ-строки в выходной буфер.
SEGGER_RTT_printf()
Запись форматированной строки в выходной буфер.
SEGGER_RTT_GetKey()
Получение одного символа из входного буфера 0.
SEGGER_RTT_HasKey()
Проверка - есть ли символ во входном буфере 0.
SEGGER_RTT_WaitKey()
Ожидание появления символа во входном буфере 0 и получение его.
SEGGER_RTT_ConfigUpBuffer()
Конфигурирование UP-буфера (вывод).
SEGGER_RTT_ConfigDownBuffer()
Конфигурирование DOWN-буфера (ввод).
SEGGER_RTT_Init()
Инициализация структуры RTT Control Block, когда используются целевые MCU, у которых только RAM.
SEGGER_RTT_SetTerminal()
Установка виртуального терминала для использования вывода на channel 0 операциями Write и WriteString.
SEGGER_RTT_TerminalOut()
Отправка ASCIIZ-строки через виртуальный терминал.
[Пример кода]
RTT поддерживается максимально простым и может использоваться без какой-либо конфигурации.
Назначение : Простая реализация для вывода через RTT.
Она может использоваться вместе с любой IDE. */
#include "SEGGER_RTT.h"
staticvoid_Delay(int period)
{
int i =100000*period;
do { ; } while (i--);
}
intmain(void)
{
do
{
SEGGER_RTT_WriteString(0, "Hello World from SEGGER!\r\n");
_Delay(100);
} while (1);
return0;
}
Работа printf через RTT. Низкоуровневые функции, используемые в библиотеках для printf() часто могут быть переназначены, чтобы была возможность применять свои собственные функции вывода. Пакет реализации SEGGER RTT включает необходимый код для GCC/Newlib, IAR и KEIL MDK, который можно легко подключить в проект, чтобы перенаправить printf() для вывода данных через RTT. Дополнительно пакет реализации SEGGER RTT включает в себя упрощенную версию printf: SEGGER_RTT_printf(), которая может использовать для печати форматированных строк через RTT напрямую, без вовлечения (потенциально медленной) стандартной библиотеки.
[Поддерживаемые MCU]
RTT можно использовать с любым целевым MCU, который поддерживает J-Link, с возможностью фонового доступа к памяти на работающем MCU. Поддерживаемые ядра архитектур:
Cortex-M Cortex-R Cortex-A RISC-V Renesas RX
В некоторых случаях поддержка RTT опциональна, и должны быть удовлетворены определенные требования. Для дополнительной информации посетите страничку wiki.segger.com/RTT.
[RTT в приложениях PC]
Вместо того, чтобы запускать внешнее приложение клиента Telnet, функционал RTT можно также непосредственно интегрировать в любое приложение PC, наподобие отладчика. Сделать это можно двумя способами.
Приложение может либо установить соединение с сокетом сервера RTT Telnet (он прослушивает соединения на localhost:19021), либо приложение может использовать J-Link RTT API, которое входит как часть в J-Link SDK, чтобы непосредственно сконфигурировать RTT и получать / отправлять данные.
[Вывод текста разными цветами]
Все данные, прочитанные через RTT, принимаются от целевого MCU без каких-либо изменений. Это дает возможность обрабатывать управляющие последовательности ANSI (ESC-коды) в приложении, которое выводит на печать данные RTT, чтобы отобразить из жирным шрифтом или поменять цвет выводимого текста. Обработка управляющих последовательностей ANSI в приложениях терминала изначально поддерживается в консоли Linux.
Необходимо Windows-приложение наподобие ANSICON [4], и оно может использоваться для вызова клиента RTT. Некоторые приложения Telnet наподобие PuTTY на операционной системе Windows также поддерживают управляющие последовательности ANSI.
Существует 2 способа. Если отладчик (IDE) знает адрес структуры SEGGER_RTT, то он передает этот адрес в J-Link. Например, так делает Ozone, J-Link Debugger или SEGGER Embedded Studio. Если используется отладчик, не поддерживающий SEGGER-RTT, такой как IAR's Embedded Workbench или emIDE, то J-Link ищет ID в известной области RAM во время выполнения программы, прозрачно и в фоновом режиме. Процесс поиска этой строки ID занимает доли секунды, и задерживает выполнение программы.
Когда init-секция приложения находится в RAM, J-Link может быстро идентифицировать блок в init-секции вместо актуального блока в data-секции. Чтобы предотвратить это, установите #define-макрос SEGGER_RTT_IN_RAM в 1. Теперь J-Link найдет правильный буфер буфер RTT, но только после первого вызова в приложении функции SEGGER_RTT. Рекомендуется делать вызов SEGGER_RTT_Init() в начале приложения.
Да, потому что используется интерфейс отладки. Этим интерфейсом может быть JTAG или SWD (у SWD используется только 2 ножки сигналов) на большинстве устройств Cortex-M, или даже интерфейс FINE на некоторых устройствах Renesas, как интерфейс Infineon SPD (одна ножка!).
Вопрос: в некоторых случаях вывод (printf) приводит к краху выполнения программы, когда она работает вне среды отладки. Это происходит, потому что она использует программную точку останова (breakpoint) которая приводит к hardfault без отладчика, или к остановке (halt), потому что SWO не инициализирован. Это делает невозможным сборки Debug в режиме независимого запуска, без отладчика (stand-alone). Что можно сказать про SEGGER-RTT?
Ответ: SEGGER-RTT использует не блокирующий режим по умолчанию. Это означает, что работа RTT не приводит к остановке (halt) выполнения программы, если отладчик не присутствует, и даже если не подключен J-Link. В таких условиях программа firmware приложения будет продолжать работу.
В некоторых случаях J-Link не может найти буфер RTT в известной области RAM. В этом случае возможный регион или точный адрес можно установить для J-Link вручную, командой exec.
Установка адреса буфера RTT может быть сделана также через панель управления J-Link (J-Link Control Panel) -> RTT.
Команда exec отладчика J-Link может быть выполнена в большинстве приложений, например в J-Link Commander через "exec < Command >", в J-Link GDB Server через "monitor exec < Command >", или в среде IDE IAR Embedded Workbench через "__jlinkExecCommand("< Command >");" из файла макроса.
Таким образом, проблему можно решить двумя способами - либо вместо формата %i использовать формат %d, либо к метке case 'd' добавить еще и метку case 'i'.
Если не обрабатывается формат чисел с плавающей запятой, то скорее всего проблема в том, что в используемой библиотеке стандартного ввода/вывода (stdio) числа с плавающей запятой не поддерживаются, либо не настроена обработка этого формата. Это обычное поведение по умолчанию библиотеки stdio, потому что позволяет экономить на дефицитном ресурсе MCU - памяти программ и данных.
В любом случае возможность печати float/double зависит от используемых библиотек стандартного ввода/вывода в конкретной среде разработки, и вариантов выполнения настройки может быть много.
[ARM GCC]
Поддержка float для stdio может быть включена опцией командной строки компилятора:
-u _printf_float
[Keil μVision + SEGGER RTT]
Функции форматированного вывода SEGGER RTT не поддерживают числа с плавающей запятой, но можно решить эту проблему простым способом, если применить промежуточное преобразование числа float в строку с помощью функции sprintf. Для этого надо разрешить поддержку числе с плавающей запятой для компилятора и библиотеки stdio. Для Keil uVision v5.34 это делается выбором опции Floating Point Hardware: Single Precision в настройках проекта.
После этого можно перевести число в строку и вывести его через RTT с помощью самодельной функции, примерно вот так:
[Вывод на печать float с помощью целочисленной арифметики]
Ниже представлен универсальный способ, который может подойти во многих случаях, когда нет возможности или желания включить в stdio поддержку чисел с плавающей запятой.
Комментарии
RSS лента комментариев этой записи