cancel
Showing results for 
Search instead for 
Did you mean: 

No printf support on STM32H735G-DK

Arno1
Senior

Hi,

I'm trying to run some code on the STM32H735G Development Kit.

When simply generating a new firmware in CubeMx (v6.1.1), printf doesn't seem to want to work out of the box and the system hangs. I disable FDCAN init and OCTOSPI init and it can at least start up.

I'm using UART3 and added an `__io_putchar` implementation but that makes no difference.

It's only when I add an implementation for `int puts(const char* str)` that printf somewhat works: I can do `printf("text")` but not `printf("num: %d", 5)`.

I guess some stdio binary is not being linked in.

Thanks.

4 REPLIES 4
Houssem CHAABANI
Senior II

Hi @Arno​ ,

Could please share your .ioc file ?

Thanks!

Hi Houssem,

Here is the IOC file I use.

Also, here is the code I added to get output:

in usart.c:

int __io_putchar(int c)
{
    HAL_UART_Transmit(&huart3, (uint8_t *)&c, 1U, 0xFFFFU);
    return c;
}
 
int putchar(int c)
{
    HAL_UART_Transmit(&huart3, (uint8_t *)&c, 1U, 0xFFFFU);
    return c;
}
 
int puts(const char* str)
{
	static const char eol[2] = { '\r', '\n' };
	int ctr = 0;
	while ((str[ctr] != '\0') && (ctr < 128)) {
		HAL_UART_Transmit(&huart3, (uint8_t *)&str[ctr], 1U, 0xFFFFU);
		ctr++;
	}
	HAL_UART_Transmit(&huart3, (uint8_t *)&eol[0], 1U, 0xFFFFU);
	HAL_UART_Transmit(&huart3, (uint8_t *)&eol[1], 1U, 0xFFFFU);
    return 0;
}

The `puts` and `putchar` implementations should not be needed but they are part of my experiments to get some output.

This is what I changed in main:

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_ADC1_Init();
  MX_ADC2_Init();
  MX_ADC3_Init();
  MX_DAC1_Init();
//  MX_FDCAN1_Init();
//  MX_FDCAN2_Init();
  MX_I2C4_Init();
  MX_LTDC_Init();
//  MX_OCTOSPI1_Init();
//  MX_OCTOSPI2_Init();
  MX_SAI1_Init();
  MX_TIM1_Init();
  MX_TIM4_Init();
  MX_TIM5_Init();
  MX_USART1_UART_Init();
  MX_USART3_UART_Init();
  MX_USB_OTG_HS_USB_Init();
  MX_RNG_Init();
  MX_ETH_Init();
  /* USER CODE BEGIN 2 */
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  puts("____________________");
  while (1)
  {
		HAL_GPIO_TogglePin(USER_LED1_GPIO_Port, USER_LED1_Pin);
 
		bool button_val = HAL_GPIO_ReadPin(USER_BUTTON_Port, USER_BUTTON_Pin);
		HAL_GPIO_WritePin(USER_LED2_GPIO_Port, USER_LED2_Pin, button_val);
		printf("printf\r\n");
		printf("printf num %d\r\n", 5);
		puts("puts");
		putchar('c');
		putchar('\r');
		putchar('\n');
		HAL_Delay(500);
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */

Weirdly, sprintf and vsprintf do work.

I tried implementing my own printf which works but still strange why printf specifically does not work.

The solutions in this discussion:

https://community.st.com/s/question/0D50X0000AuqfAaSQI/how-to-redirect-printf

did not work (fflush, '\n' and setvbuf) either.

Here is my implementation:

#define STDOUT_BUFFER_SIZE 128
int __io_putchar(int c)
{
    HAL_StatusTypeDef sts = HAL_UART_Transmit(&huart3, (uint8_t*)&c, 1U, 0xFFFFU);
    return (sts == HAL_OK) ? c : EOF;
}
static int putstr(const char* str)
{
    int ctr = 0;
    while ((str[ctr] != '\0') && (ctr < STDOUT_BUFFER_SIZE)) {
        if (__io_putchar(str[ctr]) == EOF) {
            return EOF;
        }
        ctr++;
    }
    return ctr;
}
 
int printf(const char* format, ...)
{
    char buffer[STDOUT_BUFFER_SIZE] = { };
    va_list args;
    va_start(args, format);
    vsnprintf(buffer, sizeof(buffer), format, args);
    va_end(args);
    return putstr(buffer);
}

Arno1
Senior

Turns out that generating the project for STM32CubeIDE (v1.5.1 here) does work with printf support. However when generating a makefile project with the exact same code it does not.

Weirdly also, generating for CubeIDE gives us 2 linker scripts: STM32H735IGKX_FLASH.ld, STM32H735IGKX_RAM.ld (only xx_FLASH is used by CubeIDE)

but when generating a Makefile project you get one: STM32H735IGKx_FLASH.ld (notice the lowercase x in the name as opposed to an uppercase X).

These are also somewhat different.

The makefile is missing the files sysmem.c and syscall.c.

Update:

It now works, used wildcard for Core/Src, this seems to solve it