Skip to main content
NW27
Associate II
August 25, 2020
Question

STM32CubeIDE & C++ - Redirected printf no longer works - How to use cout?

  • August 25, 2020
  • 5 replies
  • 7937 views

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.

This topic has been closed for replies.

5 replies

TDK
Super User
August 26, 2020

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.

"If you feel a post has answered your question, please click ""Accept as Solution""."
Gmate.1
Visitor II
April 10, 2021

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

Piranha
Principal III
April 10, 2021
NW27
NW27Author
Associate II
August 26, 2020

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.

HSh..2
Associate
September 20, 2022

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.

0693W00000SvlBWQAZ.png 

and when changing to syscalls.cpp, I get the second_error.

0693W00000SvlBRQAZ.png 

Senior III
February 4, 2023

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 */

Dudo
March 3, 2023

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");
...
}

Senior
May 25, 2023

Your codes helped me. Thanks a lot.