2019-07-30 11:15 AM
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
Solved! Go to Solution.
2019-08-12 01:32 AM
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:
Regards,
Ethan
2019-07-30 03:26 PM
Which compiler? You may have to provide a different routine:
https://embedded.fm/blog/2016/12/13/discovery-uarts-part-3-the-final-step
2019-07-30 04:58 PM
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.
2019-07-31 07:39 AM
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
2019-07-31 08:09 AM
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:
Working project:
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
2019-08-12 01:32 AM
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:
Regards,
Ethan
2019-08-12 05:56 AM
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" );
2019-08-12 06:25 AM
Address 64 bytes - is this normal?
2019-08-19 06:28 AM
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
2019-08-19 04:57 PM
If you don't want the \n characters, use fflush().
A