Программирование ARM nRF5x: отладка с помощью RTT Mon, September 27 2021  

Поделиться

Нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.

nRF5x: отладка с помощью RTT Печать
Добавил(а) microsin   

В SDK 12.0.0 или более новой версии встроена функция вывода отладочных сообщений в терминал реального времени (logging/debugging over Real Time Terminal, сокращенно RTT) соответствующий код находится в logger module NRF_LOG. Чтобы разрешить вывод в лог через RTT, разрешите опции NRF_LOG_ENABLED и NRF_LOG_BACKEND_SERIAL_USES_RTT в sdk_config.h (опции файла sdk_config.h можно редактировать как напрямую, так и через утилиту CMSIS Configuration Wizard [2]). Таким образом, это руководство (перевод [1]) больше подходит для SDK 11 или его более ранней версии.

При создании программы для MCU обычно возникает необходимость отладки и мониторинга поведения кода в реальном времени. Есть несколько способов организации такого мониторинга - управление уровнем ножки порта GPIO, подключение отладчика, вставка в код точек останова (breakpoints), выполнение операторов по шагам. Однако наиболее информативный способ отладки приложений, критичных ко времени выполнения (таких, как приложения Bluetooth) - вывод информационных сообщений через последовательный порт в реальном времени, без остановки программы. Хороший вариант организации такого вывода - текстовый лог с использованием Real Time Terminal (RTT) от SEGGER. В этом руководстве показано, как эту функцию отладки добавить в любой существующий проект.

Что потребуется:

• J-Link software pack v4.98 (или более свежей версии) [3].
• Файлы RTT [4].
• Keil uVision 5.14 (или более свежей версии).

Как добавить файлы RTT в любой проект nRF5x (на примере проекта ble_app_uart):

• Загрузите zip-архив [4] и распакуйте его.
• Скопируйте папки RTT и Syscalls, распакованные из zip-архива, в каталог C:\Keil_v5\ARM\Pack\NordicSemiconductor.
• Зайдите в меню Keil Project -> Options for target.
• На закладке C/C++ добавьте C:\Keil_v5\ARM\Pack\NordicSemiconductor\RTT в пути поиска заголовков (include path).
• Подключите SEGGER_RTT.h к проекту, добавив строчку #include "SEGGER_RTT.h" в начало модуля main.c проекта.

Мы добавили файл заголовка для функций RTT, но еще нужно добавить в проект модули *.c.

• В Keil сделайте правый клик на папку проекта, и кликните Add Group, введите RTT для имени группы.
• Сделайте правый клик на созданной новой группе, и выберите Add existing files to group 'RTT'.
• В диалоге выбора файлов перейдите в C:\Keil_v5\ARM\Pack\NordicSemiconductor\RTT, и добавьте SEGGER_RTT.c.

Теперь у Вас должна работать отправка простых строк через интерфейс RTT. Добавьте в функцию main сразу перед входом в бесконечный цикл следующую строку:

SEGGER_RTT_WriteString(0, "Hello World!\n");

Первый аргумент задает, в какой канал записывать текст. Канал по умолчанию 0, более подробно про каналы можно прочитать на сайте SEGGER.

[Использование Real Time Terminal]

Наш код посылает строку сообщения в RTT, но у нас также должна быть возможность её прочитать. Есть несколько способов, описанных на страничке SEGGER [5]. Самый простой из них - использовать J-Link RTT Viewer, который входит в пакет программ для J-Link (J-link software package).

• Откройте J-Link RTT Viewer, появится окно, как на скриншоте ниже. Если подключено больше одного адаптера J-Link, то поставьте галочку "Serial no.", и введите серийный номер устройства, к которому нужно подключиться.

nRF5x Debug RTT Viewer

• Кликните Ok. Появится окно J-Link RTT Viewer:

nRF5x Debug RTT Terminal0

Загрузите скомпилированный код, и после его запуска Вы увидите текст "Hello World!". Обратите внимание, что если открыть окно терминала с последовательным соединением UART (Termite, putty, HyperTerminal и т. п.), то Вы также увидите в нем текст "Start..", который все еще печатается через последовательный порт, как и раньше. Теперь Вы можете использовать проект ble_app_uart, как это предполагалось изначально, однако также можете посылать текст через RTT, и использовать эту возможность для отладки. Имейте в виду, что SEGGER_RTT_WriteString() работает намного быстрее, чем printf, так что можно безопасно вызывать эту функцию без влияния на параметры поведения в реальном времени своего приложения.

[Передача текста в приложение]

Вы также можете посылать текст через RTT своему MCU, как альтернативу использованию UART. Измените главный цикл функции main в проекте ble_app_uart так, как показано ниже. Для использования функции задержки необходимо также подключить заголовок nrf_delay.h.

char c = 0;
for (;;)
{
   c = SEGGER_RTT_WaitKey(); // блокировка, пока не поступят данные
   if(c == 'r'){
      SEGGER_RTT_WriteString(0, "Resetting..\n");
      nrf_delay_ms(1000);
      sd_nvic_SystemReset();
   }
   //power_manage();
}

• Скомпилируйте проект, и прошейте код в свое устройство.
• В RTT Viewer перейдите в меню Input -> Sending и кликните Send on Enter (иначе при каждой нажатой Вами клавише будет происходить отправка соответствующего символа).
• Введите букву r в текстовое поле и нажмите Enter. Устройство перезагрузится.

nRF5x Debug RTT Terminal0 output example

nRF5x Debug RTT UART output

[Более продвинутый вывод]

Мы только что рассмотрели вывод сырого текста с помощью функции SEGGER_RTT_WriteString(). Также есть функция с мощной поддержкой форматированного вывода, SEGGER_RTT_printf(). Чтобы её использовать, нужно дополнительно подправить проект.

• Добавьте в проект модуль SEGGER_RTT_printf.c точно так же, как мы добавляли ранее SEGGER_RTT.c.

• Убедитесь, что в проекте определен макрос NRF_LOG_USES_RTT:

#define NRF_LOG_USES_RTT 1

• Точно так же добавьте RTT_Syscalls_KEIL.c из папки C:\Keil_v5\ARM\Pack\NordicSemiconductor\Syscalls.

• Сделайте правый клик на nRF_Libraries в проекте, и выберите Options.

nRF5x Debug RTT options nRF Libraries

• В списке Software Components кликните на retarget (перенаправление), и затем на кнопку Remove.

• Перейдите в меню Project -> Options for target, и снимите галочку "Use MicroLIB".

nRF5x Debug RTT options nRF Libraries retarget remove

• Отредактируйте бесконечный цикл main следующим образом:

char c = 0;
for (;;) {
   c = SEGGER_RTT_WaitKey(); // блокировка, пока не поступят данные
   if(c == 'r'){
      SEGGER_RTT_printf(0,
                        "%sResetting in %d second..%s\n",
                        RTT_CTRL_BG_BRIGHT_RED,
                        1,
                        RTT_CTRL_RESET);
      nrf_delay_ms(1000);
      sd_nvic_SystemReset();
   }
   //power_manage();
}

Скомпилируйте и запустите проект. Теперь вывод текста может быть разными цветами, что удобно для визуального выделения отладочных сообщений. В RTT Viewer перейдите в Terminal 0, чтобы увидеть раскрашенный текст.

nRF5x Debug RTT Terminal0 output example colored

Теперь функция printf перенаправляет свой вывод в RTT, поэтому для отладки стал доступен стандартный форматированный вывод. Проект ble_app_uart все еще будет работать так же, как и раньше, потому что в нем вывод app_uart_put осуществляется через последовательный порт.

Пример использования форматированного вывода printf:

SEGGER_RTT_printf(0, "Значение переменной: %d\n", variable);

Здесь первый параметр указывает, что вывод должен осуществляться в Terminal 0 утилиты J-Link RTT Viewer, второй параметр это строка для печати с форматом, и третий параметр это переменная, преобразованное в текст значение которой будет подставлено вместо "%d".

Для дополнительной информации по RTT и различным функциям см. главу 10 руководства J-Link [6].

[2 простых шага для включения вывода через RTT в IDE Keil]

Поскольку модули SEGGER_RTT.c и SEGGER_RTT_printf.c уже добавлены почти во всех примерах из SDK для Keil (они находятся в папке nRF_Segger_RTT дерева модулей проекта), то добавить вывод отладочных сообщений RTT становится очень просто. Процесс по шагам:

1. Добавьте директивой #include заголовочный файл SEGGER_RTT.h в код, где нужно использовать функции вывода через RTT.

#include "SEGGER_RTT.h"

2. Перейдите в свойства проекта (меню Project -> Options for ...), и на закладке C/C++ в поле ввода Preprocessor Symbols Define добавьте макроопределение NRF_LOG_USES_RTT.

После выполнения этих двух шагов можно в коде выполнять вывод произвольных сообщений с помощью функции SEGGER_RTT_printf. Чтобы не вводить каждый раз такое длинное имя функции, я для себя сделал удобный макрос umsg:

#include "SEGGER_RTT.h"
 
#define umsg(...) \
        { \
            SEGGER_RTT_printf(0, __VA_ARGS__); \
        }

[Перенаправление вывода NRF_LOG_INFO в RTT]

Поменяйте в файле sdk_config.h макроопределение NRF_LOG_BACKEND_SERIAL_USES_RTT, установив его в 1 (по умолчанию оно определено как 0):

// < e > NRF_LOG_BACKEND_SERIAL_USES_RTT - Если разрешено (1),
//       то вывод функций NRF_LOG_ будет печататься через RTT
//============================================================
#ifndef NRF_LOG_BACKEND_SERIAL_USES_RTT
//#define NRF_LOG_BACKEND_SERIAL_USES_RTT 0
#define NRF_LOG_BACKEND_SERIAL_USES_RTT 1
#endif

Как вариант это макроопределение можно установить в отдельном подключаемом файле настроек app_config.h. После этого функции NRF_LOG_INFO, NRF_LOG_DEBUG и NRF_LOG_WARNING будут выводить свои сообщения через RTT.

[Ток потребления]

Для приложений, у которых потребление энергии - критичный параметр, в Release стоит отключить функционал RTT, потому что в типовых сценариях устройств BLE включение RTT добавляет дополнительный ток потребления порядка 40 мкА.

[Ссылки]

1. Debugging with Real Time Terminal site:nordicsemi.com.
2. Конфигурационный заголовок nRF5x SDK.
3. J-Link / J-Trace Downloads site:segger.com.
4. RTT_Implementation_141217.zip - файлы RTT.
5. J-Link RTT – Real Time Transfer.
6. UM08001 J-Link / J-Trace User Guide site:segger.com.

 

Добавить комментарий


Защитный код
Обновить

Top of Page