Программирование ARM: решение проблем, FAQ IAR EW ARM: как перенаправить вывод printf и putchar Fri, August 18 2017  

Поделиться

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

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


IAR EW ARM: как перенаправить вывод printf и putchar Печать
Добавил(а) microsin   

В IAR имеется довольно удобная возможность для отладки - вывод в окно терминала текстовых сообщений.

[Вывод отладочных сообщений в окно терминала]

Для вывода отладочных сообщений используется оператор printf. По умолчанию все отладочные сообщения выводятся во встроенное в IAR окно терминала (Terminal I/O). Чтобы задействовать эту возможность, нужно выполнить следующие простые шаги:

1. Добавьте в код заголовочный файл stdio.h.

#include < stdio.h >

2. Укажите в нужном месте кода, где должен быть отладочный вывод, оператор printf с нужным текстовым сообщением:

printf("Hello world!\r\n");

3. Запустите отладку () и откройте окно терминала (View -> Terminal I/O). После выполнения оператора printf в окне терминала Вы увидите свое сообщение.

IAR-printf-terminal-IO

Обработка форматного вывода (%) printf может занимать много места в памяти программ. Поэтому В IAR есть выбор опций вывода printf, что иногда полезно для экономии памяти и ресурсов микроконтроллера. Выбор типа форматера printf (как и scanf) задается через настройку опций библиотеки проекта, Project -> Options... -> General Options -> закладка Library options (Full, Large, Small, Tiny). На возможности вывода также влияет выбор на закладке Library Configuration (None, Normal, Full, Custom). Подробнее по возможностям вариантов настройки форматтера смотрите Руководство разработчика IAR (IAR C/C++ Development Guide), раздел "Choosing formatters for printf and scanf".

[Перенаправление вывода printf IAR 4]

Вывод printf можно перенаправить в любое устройство ввода/вывода, например в DBGU или на экран LCD. Встроенная в IAR библиотека содержит готовый модуль, который для этого Вам нужно заменить на свою собственную реализацию, причем нет необходимости перекомпилировать всю библиотеку. Библиотечные файлы исходного кода, которые пользователь может перезадать на свои, для IAR 4.0 находятся в папке C:\Program Files\IAR Systems\Embedded Workbench 4.0 Evaluation\ARM\src\lib\. Здесь приведена пошаговая инструкция для изменения низкоуровневого вывода printf, для чего нужно определить свою собственную версию модуля write.c (нужно будет исправить код функции __write), и добавить реализацию функции MyLowLevelPutchar. В оригинальной версии модуля write.c функционал перенаправления вывода закомментирован, и в нем даны инструкции, как этот функционал включить.

1. Скопируйте файл write.c в папку своего проекта IAR, где находятся все модули исходного кода программы.
2. Добавьте скопированный модуль write.c в Ваш проект (Project -> Add Files...), и откройте его в текстовом редакторе. Посмотрите реализацию функции __write: в ней блоком #if 0 / #else удалена реализация низкоуровневого вывода printf. Функция __write предназначена для вывода size символов из буфера buffer, причем она может делать этот вывод специальным, определяемым Вами способом (благодаря вызову MyLowLevelPutchar). Удалите директивы #if 0 / #else / #endif и последний ненужный оператор return _LLIO_ERROR; (он находится между #else и #endif).
3. Определите в проекте (в любом модуле, или прямо в модуле write.c) код функции MyLowLevelPutchar. Эта функция предназначена для низкоуровневого вывода одного символа на любое устройство вывода. Это может быть порт DBGU, файл, экран LCD или любой выбранный Вами интерфейс, поэтому в этой функции Вы сами должны определить код для вывода символа. Функция MyLowLevelPutchar должна возвратить тот же символ, который был у неё во входном параметре, либо -1 в случае ошибки (_LLIO_ERROR).

Внимание: после вышеуказанных шагов вывод printf во встроенное окно терминала перестанет работать (теперь printf будет выводить символы в указанное Вами устройство вывода).

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

/*******************
 *
 * Copyright 1998-2003 IAR Systems. All rights reserved.
 *
 * $Revision: 1.14 $
 *
 * Это шаблон реализации функции "__write", используемой стандартной
 * библиотекой. Замените её своей реализацией, адаптированной
 * специально для Вашей системы.
 *
 * Функция "__write" должна выводить "size" байт из буфера 
 * "buffer" некоторым способом, зависящем от Вашей системы
 * (это может быть RS232, LCD или другое устройство вывода).
 * Функция "__write" должна возвратить количество записанных
 * байт, или в противном случае должна вернуть _LLIO_ERROR,
 * что сигнализирует об ошибке.
 *
 * Если буфер "buffer" нулевой (NULL), то функция __write должна
 * выполнить очистку (сброс, синхронизацию, flushing) внутренних
 * буферов, если они есть. В этом случае "handle" может быть -1,
 * что показывает, что все хендлы должны быть сброшены (flushed).
 *
 * Реализация шаблона ниже подразумевает, что приложение предоставило
 * функцию "MyLowLevelPutchar". Она должна возвратить количество 
 * записанных символов, ли -1 в случае ошибки.
 *
 ********************/
#include < yfuns.h >
_STD_BEGIN #pragma module_name = "?__write"
int MyLowLevelPutchar(int x);
 
/*
 * Если реализация __write использует внутреннее буферизирование,
 * то раскомментируйте следующую строку, чтобы убедиться, что мы были
 * вызваны с "buffer" как 0 (например flush), когда приложение 
 * завершает работу (terminate).
 */
size_t __write(int handle, const unsigned char * buffer, size_t size)
{
  size_t nChars = 0;
  if (buffer == 0)
  {
    /*
 * Это означает, что нужно сбросить (flush) внутренние буферы. Поскольку
 * мы ничего не делаем, то нужно просто сделать возврат. Помните, что 
 * "handle" == -1 означает, что все хендлы должны быть сброшены (flushed).
 */
    return 0;
  }
  /* Этот шаблон записывает только в "standard out" и "standard err",
 * для всех других файловых хендлов будет возвращена ошибка. */
  if (handle != _LLIO_STDOUT && handle != _LLIO_STDERR)
  {
    return _LLIO_ERROR;
  }
  for (/* Пусто */; size != 0; --size)
  {
    if (MyLowLevelPutchar(*buffer++) < 0)
    {
      return _LLIO_ERROR;
    }
    ++nChars;
  }
  return nChars;
}
_STD_END

Пример пользовательской реализации функции MyLowLevelPutchar. Функция пишет графику символов в видеопамять, массив video_memory, и обрабатывает символы CR, LF и TAB. Код скроллинга экрана ScrollUp не приведен (для упрощения).

//Текстовый экран имеет размерность 80x60 символов, в пикселах
// 640x480 точек (каждый символ имеет матрицу 8x10 точек).
#define VIDEO_MAX_COLUMNS 80
#define VIDEO_MAX_LINES 48
u8 currX = 0; u8 currY = 0; char video_memory [VIDEO_MAX_LINES*10][VIDEO_MAX_COLUMNS];
int MyLowLevelPutchar(int x) { u16 pixY; u8 nextX; if ('\r'==x) { //Обработка возврата каретки CR - переход позиции вывода // на начало строки. currX=0; } else if ('\t'==x) { //Обработка табуляции TAB на 4 символа. nextX = ((currX + 3) & ~3); if (nextX >= VIDEO_MAX_COLUMNS) nextX -= VIDEO_MAX_COLUMNS; while (currX != nextX) putchar(' '); } else if ('\n'==x) { //Обработка перевода строки LF - переход позиции вывода // на следующую строку (со скроллингом экрана вверх, // если позиция вывода находится на последней строке). if (currY<(VIDEO_MAX_LINES-1)) { currY++; } else { ScrollUp(); } } else { for(pixY=0; pixY < 10; pixY++) { video_memory[currY*10+pixY][currX]=data_table[(index_table[x]*10+pixY)]; } if (currX < (VIDEO_MAX_COLUMNS-1)) { currX++; } else { currX=0; if (currY < (VIDEO_MAX_LINES-1)) { currY++; } else { ScrollUp(); } } } return 1; }

[Перенаправление вывода printf IAR 5]

Для версии IAR 5.0 вывод printf настраивается аналогичным образом. Если подключен заголовок utility/trace.h, и определен символ TRACE_DBGU, то по умолчанию printf и putchar выводят символы в порт DBGU. Если Вы у себя в программе настроите этот порт (как это делать, см. в примерах от IAR - PIO_Configure (pPinsDBGU, PIO_LISTSIZE(pPinsDBGU)); DBGU_Configure (DBGU_STANDARD, 115200, BOARD_MCK);), и подключите к COM-порту компьютера, то увидите в консольной программе вывод printf. Для перенаправления вывода printf нужно также добавить в проект файл write.c (c:\Program Files\IAR Systems\Embedded Workbench 5.0 Evaluation\ARM\src\lib\write.c), подправить код функции __write (закомментировать #if 0/#endif), и написать код для функции int MyLowLevelPutchar(int x).

[Ссылки]

1. myARMprintf.zip - пример перенаправления printf для ЖКИ индикатора WG240128B и микроконтроллера AT91SAM7X256 (проект IAR EW ARM 5.20).
2. Как делать шрифты для устройств на микроконтроллерах.
3. Макетная плата AT91SAM7X.
4. IAR EW ARM: DBGU, хитрости в использовании printf.
5. IAR EWB ARM: форматированный вывод printf библиотеки DLIB.

 

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


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

Top of Page