cancel
Showing results for 
Search instead for 
Did you mean: 

printf() not working - _write() never gets called

CKauf
Associate III

Hello,

as the title suggest, I can't get printf() to work.

I implemented _write() in my main() but during debugging the program never get there.

The project was created with CubeIDE.

int _write(int file, char *data, int len)
{
   if ((file != STDOUT_FILENO) && (file != STDERR_FILENO))
   {
      errno = EBADF;
      return -1;
   }
 
   // arbitrary timeout 1000
   HAL_StatusTypeDef status =
      HAL_UART_Transmit(&huart1, (uint8_t*)data, len, 1000);
 
   // return # of bytes written - as best we can tell
   return (status == HAL_OK ? len : 0);
}

I know the hardware works, because the same implementation of _write() works in an other project (the one provided here).

I am probably missing some compiler setting but I can't for the life of mine figure out what it is.

Can someone please point me in the right direction?

Best regards.

Christoph

1 ACCEPTED SOLUTION

Accepted Solutions

Hi Christoph,

I checked your code just now and found your printf message does not contain newline "\n" so your printf doesn't hit lower implementation of __io_putchar since stdout is buffered.

Two options you can consider:

  1. Add newline ("\n") in your printf message.
  2. Use setvbuf to make stdout non-buffered as described by WereCatf in the following link: https://community.st.com/s/question/0D50X0000AuqfAaSQI/how-to-redirect-printf

Regards,

Ethan

View solution in original post

9 REPLIES 9

Which compiler? You may have to provide a different routine:

https://embedded.fm/blog/2016/12/13/discovery-uarts-part-3-the-final-step

Check what's actually getting linked. Likely pulling in the wrong library, or one you didn't expect. Check .MAP and any other linker output.

Perhaps gets a disassembly/listing and follow it down the rabbit hole.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
CKauf
Associate III

Thank you for your suggestions.

@Andrei Chichak​ I am using the default compiler and linker of the CubeIDE for both projects. Those are the GCC and G++ compilers and the G++ linker.

@Community member​ I think you might be on to something.

The .MAP of my project doesn't mention _write at all!

In the .MAP file of the working project _write appeares twice:

 .text._write   0x0000000000000000       0x38 Src/syscalls.o
[......]
 .text._write   0x000000000801ebb8       0x58 Src/main.o
                0x000000000801ebb8                _write

This seems logical - first where it was originally defined and once where I implemented my version. But why?

The linker settings are almost identical.

Non-working project:

-mcpu=cortex-m7 -T"C:\Users\user\STM32CubeIDE\workspace_1.0.0\f746g-disco-i2c_only\STM32F746NGHX_FLASH.ld" --specs=nosys.specs -Wl,-Map="${ProjName}.map" -Wl,--gc-sections -static --specs=nano.specs -mfpu=fpv5-sp-d16 -mfloat-abi=hard -mthumb -u _printf_float -Wl,--start-group -lc -lm -lstdc++ -lsupc++ -Wl,--end-group

Working project:

-mcpu=cortex-m7 -T"C:\Users\user\STM32CubeIDE\workspace_1.0.0\f746g-disco-test\STM32F746NGHX_FLASH.ld" --specs=nosys.specs -Wl,-Map="${ProjName}.map" -Wl,--gc-sections -static -L"C:\Users\user\STM32CubeIDE\workspace_1.0.0\f746g-disco-test\Middlewares\ST\TouchGFX\touchgfx\lib\core\cortex_m7\gcc" --specs=nano.specs -mfpu=fpv5-sp-d16 -mfloat-abi=hard -mthumb -u _printf_float -Wl,--start-group -lc -lm -lstdc++ -lsupc++ -Wl,--end-group

The only difference is the additional library for TouchGFX. Just to be sure I tried including this flag in my project as well but it didnt change anything.

Comparing the linker-ouputs I found a number of lines like these:

attempt to open c:/st/stm32cubeide_1.0.0/stm32cubeide/plugins/com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.7-2018-q2-update.win32_1.0.0.201904181610/tools/bin/../lib/gcc/arm-none-eabi/7.3.1/thumb/v7e-m/fpv4-sp/hard\libc_nano.a failed
attempt to open c:/st/stm32cubeide_1.0.0/stm32cubeide/plugins/com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.7-2018-q2-update.win32_1.0.0.201904181610/tools/bin/../lib/gcc/arm-none-eabi/7.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m/fpv4-sp/hard\libc_nano.a succeeded

But the exact same lines appear in the working project as well. I attached the linker output to this post.

I am not sure what I should be looking for at this point. Is there a certain line I should be looking for?

Best regard and thank you for your help.

Christoph

CKauf
Associate III

Sorry for the double post but I have some more information now.

I also tried stepping through the disassembly as Clive suggested and was able to capture the following call stacks:

Non-working project:

0690X000009ZfLDQA0.png

Working project:0690X000009ZfLXQA0.png

I am calling printf() in the code in both projects.

I assume this means printf() is being linked somewhere else in both projects (although the top of the stack looks identical).

But I am still at a loss as to why this is.

Best regards

Christoph

Hi Christoph,

I checked your code just now and found your printf message does not contain newline "\n" so your printf doesn't hit lower implementation of __io_putchar since stdout is buffered.

Two options you can consider:

  1. Add newline ("\n") in your printf message.
  2. Use setvbuf to make stdout non-buffered as described by WereCatf in the following link: https://community.st.com/s/question/0D50X0000AuqfAaSQI/how-to-redirect-printf

Regards,

Ethan

Bob S
Principal

I noticed that your stack trace that worked has "puts" in the map file, whereas the one that did not work had "printf"Also be aware that GCC **may** translate a printf() call to puts(). Specifically, a printf format string with no "%" format specifiers, like this:

printf( "Hello World\n" :(

The compiler will strip the trailing newline and make this:

puts( "Hello World" );

Address 64 bytes - is this normal?

Hi Ethan,

adding the newline did the trick. I feel so stupid now. Thank you for the explanation.

I didn't know there was the feature of stdout being buffered, showing my lack of some basic knowledge, I guess...

Thanks a lot to everyone who contributet.

Best regards,

Christoph

If you don't want the \n characters, use fflush().

A