Electronic – Lightweight (subset) of standard C library (ANSI C library)

armgccstm32

I'm porting standard C library for bare metal "OS" (ARM Cortex-M4, ARM GCC). I want to have functions like strlen, sprintf, (and memory allocator, maybe), etc.

I've ported PDCLib and Newlib.
Newlib isn't lightweight (and try to implement files operations, etc.).
PDCLib is not in active development.

So, I want Microlib exactly. But it's not for GCC and closed source.

Are there some alternatives for this? And are there some "bare metal subsets" of standard C library?

Best Answer

When I want a truly light-weight (and/or one that is thread-safe) library I usually write my own. It's not hard to do.

Since you discuss a "memory allocator," let me suggest that a malloc()/free pair is trivial to write -- perhaps a few dozen lines:

#define STATUSFREE 0
#define STATUSUSED 1
struct tag {
    struct tag * next;
    int status;
};
struct tag * heap;
void free( void * p ) {
    struct tag * ptag= ((struct tag *)p) - 1;
        ptag->status= STATUSFREE;
}
void * malloc( size_t s ) {
    struct tag *ptag, *pnext;
        for ( ptag= heap; ptag != NULL; ptag= ptag->next )
            if (ptag->status == STATUSFREE) {
                for ( pnext= ptag->next; pnext->status == STATUSFREE; pnext= pnext->next )
                    ;
                if ( s <= (size_t) (((char *) pnext) - (char *) (ptag+1)) ) {
                    if ( s <= (size_t) (((char *) pnext) - (char *) (ptag+2)) ) {
                        ptag->next= (struct tag *) (s + (char *) (ptag+1));
                        ptag->next->status= STATUSFREE;
                        ptag->next->next= pnext;
                    } else
                        ptag->next= pnext;
                    ptag->status= STATUSUSED;
                    return ptag+1;
                }
                ptag->next= pnext;
            }
    return NULL;
}

You initialize it the following way. First, set up a fixed block of memory using a standard array allocation like this:

static char mspace[1000];

That can be placed into some module you write. It should be allocated as static lifetime, of course.

Then, somewhere else (like in main()), you do the following:

((struct tag *) &mspace[0])->status= STATUSFREE;
((struct tag *) &mspace[0])->next= &((struct tag *) &mspace[sizeof(mspace)])[-1];
((struct tag *) &mspace[sizeof(mspace)])[-1].status= STATUSUSED;
((struct tag *) &mspace[sizeof(mspace)])[-1].next= NULL;
heap= (struct tag *) &mspace[0];

It's very fast and very easy.

strlen() is, of course, much easier and you can find all manner of implementation on the web for that.

The rest? I'd recommend that you write those, too. A very, very helpful book here is P. J. Plauger's (one of the founders of Whitesmiths LTD -- compiler company) "The Standard C Library." Just get a copy. You won't be sorry. It covers things like sprintf() for you, which is much more complicated and may involve treating with floating point values when converting for output. (When you re-create sprintf(), you will haul in lots of code as a result of that -- but it's just needed if you want such a powerful library function.)