Как заставить 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
особенности используются.