Как заставить printf работать на STM32F103?

Я новичок в мире STM32F103. У меня есть демонстрационный код для STM32F103, и я использую arm-none-eabi для его компиляции.

Я попробовал то, что смог найти в Google, но пока ничего не получалось. Я уже потратил три дня на эту проблему.

Кто-нибудь может дать мне демонстрационный код для printf, который хорошо работает?

Часть моего make-файла:

CFLAG   = -mcpu=$(CPU) -mthumb -Wall -fdump-rtl-expand -specs=nano.specs --specs=rdimon.specs   -Wl,--start-group -lgcc -lc -lm -lrdimon -Wl,--end-group
LDFLAG  = -mcpu=$(CPU) -T ./stm32_flash.ld -specs=nano.specs --specs=rdimon.specs   -Wl,--start-group -lgcc -lc -lm -lrdimon -Wl,--end-group

4 ответа

Включая следующие флаги компоновщика:

LDFLAGS   += --specs=rdimon.specs -lc -lrdimon

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

Semihosting - это механизм, который позволяет коду, выполняемому на цели ARM, взаимодействовать и использовать средства ввода / вывода на главном компьютере, на котором выполняется отладчик.

Примеры этих средств включают ввод с клавиатуры, вывод на экран и дисковый ввод-вывод. Например, вы можете использовать этот механизм, чтобы включить функции из библиотеки C, такие как printf() и scanf(), чтобы использовать экран и клавиатуру хоста вместо экрана и клавиатуры в целевой системе.

Поскольку вы используете инструменты openSource для разработки STM32 (Makefile и arm-none-eabi), я предполагаю, что вы также используете openOCD для программирования своего микроконтроллера. openOCD требует, чтобы вы также включили полухостинг, используя следующую команду:

arm semihosting enable

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

 source [find target/stm32f1x.cfg]
 init
 arm semihosting enable

Другие решения, упомянутые здесь, где ваша цель fputc() Функция интерфейса UART также будет работать и может. Semihosting будет работать на всех последних ARM Cortex-M, но потребует некоторой конфигурации компилятора и отладчика (см. Выше). Ретаргетинг fputc() Функция для интерфейса UART будет работать с любым компилятором, но вам придется проверять конфигурацию выводов для каждой платы.

Ссылка: Как перенастроить printf() на STM32F10x?

Попробуйте угнать функцию _write следующим образом:

#define STDOUT_FILENO   1
#define STDERR_FILENO   2

int _write(int file, char *ptr, int len)
{
    switch (file)
    {
    case STDOUT_FILENO: /*stdout*/
        // Send the string somewhere
        break;
    case STDERR_FILENO: /* stderr */
        // Send the string somewhere
        break;
    default:
        return -1;
    }
    return len;
}

Оригинальный printf пройдет через эту функцию (в зависимости от того, какие библиотеки вы используете).

Написание собственного printf Реализация является вариантом, и, вероятно, наиболее рекомендуемым вариантом по моему мнению. Получите вдохновение от реализации стандартной библиотеки и напишите свою собственную версию только для удовлетворения ваших требований. В общем, что вам нужно сделать, это сначала перенаправить putc функция для отправки символов через ваш последовательный интерфейс. Затем переопределите printf метод с помощью putc Пользовательская реализация. Возможно, очень простой подход - посылать строку символьно с помощью рекурсивных вызовов putc функция.

Не в последнюю очередь, вы можете найти легкий printf Реализации. Размер кода и набор функций, предлагаемых этими облегченными реализациями, лежат между printf функция и стандарт запаса printf функция (он же зверь). Я недавно попробовал этот Tiny Printf и очень доволен его производительностью на ядре ARM с точки зрения занимаемой памяти и количества необходимых циклов выполнения.

-PS

Скопировано из моих собственных работ когда-то назад.

Посмотри туда. Это printf от glib, Но у вас есть микроконтроллер. Так что вы должны написать собственный printf, где vfprintf вернет результат в буфер, а затем вы отправите данные из буфера в UART. Вид

void printf( const char * format, ... )
{
  char buffer[256];
  va_list args;
  va_start (args, format);
  vsprintf (buffer,format, args);
  send_via_USART1 (buffer);
  va_end (args);
}

Также вы можете написать собственный vsprintf, Standart vsprintf очень тяжелый Обычно маленькая часть vsprintf особенности используются.

Другие вопросы по тегам