cancel
Showing results for 
Search instead for 
Did you mean: 

Does Cube MX build the libc.a printf/canf/heap/etc library?

PHolt.1
Senior III

Yesterday's post here

https://community.st.com/s/question/0D53W00002F4MHrSAN/is-there-a-bug-in-the-newlib-heap-on-the-32f417-cube-ide-library?t=1682872893044

refers.

This article

https://nadler.com/embedded/newlibAndFreeRTOS.html

suggests that the freertosconfig.h file can contain configUSE_NEWLIB_REENTRANT =1 and this causes MX to build libc.a with the proper mutex calls.

That suggests MX has the sources. But I have Cube IDE installed (been using it for a couple of years, but have never used MX) and there are no sources there for this stuff.

I find this amazing because I have never seen ST supply any sources for these parts of stdlib. And the many supplied versions of libc.a (which can be found in c:\ST - there are 66 of these) come only in a compiled form, and not "weak" so the mutex calls, which are dummy functions, cannot be fixed by making use of the "weak" override mechanism. I had to weaken the whole libc.a and then I could do it.

13 REPLIES 13
Piranha
Chief II

> I too don't use the heap in embedded, ..., but in the case of TLS there isn't much of a choice.

https://mbed-tls.readthedocs.io/en/latest/kb/how-to/using-static-memory-instead-of-the-heap/

The article suggest one can use a static buffer with buffer allocator or retarget the calloc()/free() to your own functions and, for example, use the RTOS provided heap, which is thread-safe. Therefore even with lwIP and Mbed-TLS one still can get rid of the C runtime library's heap memory code completely.

> I don't think I am using newlib-nano. I can't remember the decision chain now but it may have been to do with support for double floats, which I do want.

The printf() and scanf() in Newlib-nano supports both single and double floats, when enabled. What it doesn't support, is printing a long long (64-bit) integers. But now, when you've replaced the Newlib's printf() with a different implementation, it doesn't matter what the Newlib's printf() supports or not. Therefore now you can move to Newlib-nano and significantly reduce the bloat.

PHolt.1
Senior III

"The article suggest one can use a static buffer "

This is currently done.

It just so happens that the 48k block issued to TLS is malloc'd from the general heap. This heap works very well; I have done extensive tests on it (and found a bug which others found before)

https://www.eevblog.com/forum/programming/help-needed-with-some-heap-test-code/

This scheme was done to enable multiple RTOS tasks to invoke TLS as needed and the said block is discarded when TLS is done, so you start with a "clean TLS" each time.

"Therefore now you can move to Newlib-nano and significantly reduce the bloat."

That is useful - thanks. Maybe I went to non-nano originally to get uint64 output, and the printf replacement was done much later.

However, is there really much bloat? I did a search for a comparison between the two and came across stuff like "Values smaller code size and smaller RAM usage over performance". So with nano you get slower code.

It would be interesting to change back to Nano but it is late in the project and I have no way of knowing if I will encounter the same problems. Is the heap code in newlib-nano thread-safe without mutexes, and if not, how does it invoke the mutexes? Newlib called them via non-weak empty stubs. I have now fixed all that.

One article I found states that Nano is open source. This is not true in the Cube IDE context; no libc.a sources are supplied. There are sources online for both newlib and newlib-nano but one can't tell for sure which one ST used and what build options they used.

> One article I found states that Nano is open source. This is not true in the Cube IDE context

Correct. Newlib & nano are opensource - but the license does not enforce ST to publish their complete work based on this source (build scripts, config. options etc. that could enable us to rebuild the library).

PHolt.1
Senior III

I am happy that somebody agrees with me and doesn't call me an id1iot : - )

It is fairly easy to locate the sources (newlib libc.a dates to 1990, nano 1998, afaict) and I did that when fixing the heap mutexes.

So why didn't ST include the sources? They give you the libs in src form for everything else. This just causes grief. All those people who are posting stuff like "my malloc keeps crashing" will never find out why. AFAICT ST did sod-all with the sources. They just built them with some build options, chosen, undocumented...