Here is my platformio.ini:
- I use Standard peripheral library with bluepill.
- I don’t use any framework .
- I use
-std=c99
build flag
I was wondering why __cplusplus is defined in system headers - for example in .platformio\packages\toolchain-gccarmnoneeabi\arm-none-eabi\include\assert.h
- Intellisense shows __cplusplus 201402L
.
But not in the main.c (greyed out):
I was able to circumvent this behaviour with build_unflags = __cplusplus
, but still am wondering why it is inconsistent and where those flags are defined.
This unfortunately doesn’t fix the problem that I am getting single letter per line when printing asserts, but I guess that’s a different issue:…
That’s a phantom. During compilation, __cplusplus
will be automatically defined by the compiler (to the given -std=c++/gnu++YY
version or the standard fallback version) when a .cpp
file is compiled and in all subsequent headers it includes. Meaning, if you have a main.c
and it #include <assert.h>
, then __cplusplus
would not be defined in that compiled run, but a main.cpp
doing the same would include the header with __cplusplus
defined.
What VSCode shows you (and this can be different from what’s happening during compilation) is dependent on whether you let it interpret the header as “included from a C file” or “included from a C++” file. As documtend here, that is depending on the “file association setting” (and not e.g. the “C/C++” button in the VSCode taskbar).
And hence, it becomes clear that when looking at assert.h
with the default .h
→ .cpp
association, it looks like
and when I go into the .vscode/settings.json
and add the appropriate “interprete every header file in C mode” setting
then it immediately looks like
and now __cplusplus
is not defined, but __STDC_VERSION
is. As expected, to January 1999.

Again, this had 0 effect on the actual compilation, it’s just a visual thing with the VSCode intellisense.
It also follows that you do not want to manually define or undefine the __cplusplus
macro. You only control that
- it is activated in a compilation unit at all if its a
.cpp
file or a header included from such a file
- you control the value of it by controlling the value of
-std=c++/gnu++<version>
setting, e.g., via advanced scripting (env["CXXFLAGS"]
, env["CFLAGS"
] for C++ and C respectively) if it needs changing from the default.
1 Like
My guess on that is that the computer is too fast / the microcontroller to slow, and when with --specs=rdimon
it prints a character, OpenOCD immediately pushes it to GDB (with the “to be output text” packet containing only one char) which outputs it to its stdout (not sure if with or without line ending) and then also in VSCode. That happens for every char then. The interpretation might be different if you started OpenOCD and GDB on a commandline alone and connected them to each other, the line endings may be correct then.
I.e., in one terminal
cd C:\Users\<user>\.platformio\packages\tool-openocd
bin\openocd.exe -d2 -s scripts -f interface/stlink.cfg -c "transport select hla_swd" -f target/stm32f1x.cfg
and in another one
cd C:\Users\<user>\.platformio\packages\toolchain-gccarmnoneeabi\bin
arm-none-eabi-gdb -ex "target extended-remote :3333" -ex "monitor reset run"
Thank you for these answers.
This gave me insights into what is going on many levels.
As for the assert,
OpenOCD printed assert horizontally:
assertion "0" failed: file "src\APP\main.c", line 247, function: main
semihosting: application exception 0x20004fb0
target halted due to breakpoint, current mode: Thread
xPSR: 0x61000000 pc: 0x0800845e msp: 0x20004fb0, semihosting
, however, unlike usual printf(), it was printed out like a smooth animation. I.e. unbuffered - character by character.
Looking into newlib-nano, I can see the printing is done to stderr
. If I redefine the __assert_func
and use ‘stdout’ instead the line is buffered, and debug console prints it all at once.
(void) printf("\nAssertion \"%s\" failed: file \"%s\", line %d%s%s\n",
failedexpr, file, line,
func ? ", function: " : "", func ? func : "");
I prefer to redefine __assert_func
anyway, since I’d rather stop on breakpoint (__asm__("BKPT");
), than hardfault with newlib’s abort()
.
Thanks
You might be able to leave the __assert_func
alone and give the stderr a buffer, similiar for how this disabled the buffer, with setvbuf()
.
1 Like
I tried and it worked.
#ifdef DEBUG
volatile char stderrBuff[100]; //used by assert
#endif
int main (void)
{
#ifdef DEBUG
if(setvbuf(stderr, stderrBuff, _IOLBF, sizeof(stderrBuff))){
__ASM("BKPT");
}
#endif
~But I am still going to redefine it __assert_func
because having __asm__("BKPT")
instead of abort()
makes debugging a better experience in practice.~
void __assert_func(const char *file, int line, const char *func, const char *failedexpr) {
(void) printf("\nAssertion \"%s\" failed: file \"%s\", line %d%s%s\n",
failedexpr, file, line,
func ? ", function: " : "", func ? func : "");
__ASM("bkpt 3");
}
Edit: redefined function needs to be non-return type, per the non-return attribute in assert.h. If it returns, the behavior is undefined and in my case it was making a parent function not returning immediately. So that’s defets the purpose and separate debug_assert() should be defined or simply __ASM(“bkpt 3”); used.