2020-08-25 04:55 PM
Hi,
I have a "C" project where the printf detailed below works for outputting to a UART.
When I change the STM32IDE compiler to a C++ project, the printf no longer works.
/****************************************************
* UART Redirect
* Re-directs printf() to the UART8 for display
* on the console
****************************************************/
int __io_putchar(int ch)
{
HAL_UART_Transmit(&huart8, (uint8_t *)(&ch), 1, 0xFFFF);
setbuf(stdout, NULL);
return 1;
}
int __io_getchar(void)
{
uint8_t ch;
HAL_UART_Receive(&huart8, (uint8_t *)(&ch), 1, 0xFFFF);
return (int)ch;
}
My understanding is that COUT should be used for C++ projects.
How do I get the cout (& cin) operational (Redirect) ??
// main.cpp
using namespace std;
#include <iostream>
int main()
{
// Usage
cout << "Some String";
}
Thanks.
2020-08-25 05:07 PM
printf should work just fine in C++. I doubt cout is going to perform better.
Make sure you put those functions within "extern C" or within a C source file so they have the right linkage.
2020-08-25 06:33 PM
Thanks,
I have tried the extern "C" and it made no difference. Still on output.
COUT would still be preferable because it handles C++ strings better.
2021-04-10 12:12 AM
Hi TDK,
I have exactly the same problem as NW27,
"printf should work just fine in C++" ... it sounds for me that there is not verification of this issue on the g++ compiler yet
2021-04-10 02:30 AM
Try suggestions from this topic:
2021-04-10 06:02 AM
2021-04-12 12:02 AM
Hi Piranha,
thank four your reply,
finally, i got that think working somehow..
as a take_home_message: io_redirect compiles with g++ but does not work on reality. It must be done with gcc
2022-09-19 10:15 PM
Hi every body.
I have a crazy problem and I`m stuck in a nerve-racking simple work.
working with STM32CubeIDE 1.5.1, code created from stm32cubemx 6.5.0
project converted to c++
wanna retarget printf to uart
in a .h file have this:
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
and in the .cpp file with the same name, have this:
PUTCHAR_PROTOTYPE
{
while( !(USART1->ISR & 0x80) ); //TXE = 0: data is not transferred to the shift register
USART1->TDR = ch;
return ch;
}
apart from the odd problem of jumping into HardFault_Handler() when using HAL_UART_Transmit()
I can never build the project successfully, I do have lots of different errors when changing all files to .cpp. the only file I dont change to .cpp is syscall.c, with that I get the first_error.
and when changing to syscalls.cpp, I get the second_error.
2023-02-04 05:24 AM
Try it. It works for me:
/* USER CODE BEGIN 0 */
extern "C" {
int __io_putchar(int ch) {
if (ch == '\n') {
__io_putchar('\r');
}
HAL_UART_Transmit(&huart2, (uint8_t*) &ch, 1, HAL_MAX_DELAY);
return 1;
}
int _write(int file, char *ptr, int len)
{
__io_putchar(*ptr);
}
}
/* USER CODE END 0 */
2023-03-03 01:53 AM
Worked in my C but not in (the same in fact) C++ project. Solution:
1) declare __io... function as "C". Otherwise name of function will be "C++ decorated" and linker doesn't use it instead of default empty stub. OK, now it works at least but stops after some printed chars.
2) use setbuf(stdout, NULL); as suggested here to disable buffering.
3) enjoy! :)
DbgConsole.h
#ifndef INC_DBGCONSOLE_H_
#define INC_DBGCONSOLE_H_
#include "usart.h"
#ifdef __cplusplus
extern "C" {
#endif
// Serial port to use. Pass NULL to disasable output
void SetConsole(UART_HandleTypeDef* huart);
#ifdef __cplusplus
}
#endif
#endif /* INC_DBGCONSOLE_H_ */
DbgConsole.c
#include <stdio.h>
#include "usart.h"
#include "DbgConsole.h"
static UART_HandleTypeDef* huart;
void SetConsole(UART_HandleTypeDef* huart_)
{
huart=huart_;
setbuf(stdout, NULL);
}
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
if(huart)
HAL_UART_Transmit(huart, (uint8_t*)&ch, 1, HAL_MAX_DELAY);
return ch;
}
Usage:
/* USER CODE BEGIN Includes */
...
#include "DbgConsole.h"
...
/* USER CODE END Includes */
...
int main(void)
{
...
/* Initialize all configured peripherals */
...
MX_USART1_UART_Init(); // for example
...
/* USER CODE BEGIN 2 */
//--------------------------------------------------------------------
SetConsole(&huart1);
printf("Hello World\n");
...
}