Skip to main content
CKauf
Associate II
July 30, 2019
Solved

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

  • July 30, 2019
  • 5 replies
  • 12044 views

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

This topic has been closed for replies.
Best answer by Ethan HUANG

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

5 replies

Andrei Chichak
Lead
July 30, 2019

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

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

Tesla DeLorean
Guru
July 30, 2019

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 VenmoUp vote any posts that you find helpful, it shows what's working..
CKauf
CKaufAuthor
Associate II
July 31, 2019

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

AVI-crak
Senior
August 12, 2019

Address 64 bytes - is this normal?

CKauf
CKaufAuthor
Associate II
July 31, 2019

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

Ethan HUANG
ST Employee
August 12, 2019

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

CKauf
CKaufAuthor
Associate II
August 19, 2019

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

Bob S
Super User
August 12, 2019

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