Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding C runtime environment (ARM) - where to start

Tags:

c

arm

I'am embedded developer working with ARM Cortex-M devices mainly. Recently I've switched to Linux and decided to learn more about the build/assemble/link process, how to write makefiles etc. as I was using IDEs (IAR, Keil, Eclipse etc.) where lot of stuff is automated and the user has actually no clue what is happening in the background. The target is to understand more of this low level process, how to use the tools properly and not just rely on the IDE default settings.

After writing a makefile I was able to build my application. However, I decided to perform the link process manually by invoking the linker directly (not through compiler) and surprisingly troubles showed up! Undefined references to libc, _init function in __libc_init_array, _exit etc. were the issues. After whole day of investigations I was able to include all the object files (crt0.o, crti.o) and libraries (libnosys.a) manually. Apparently the compiler is doing this stuff automatically.

After overcoming these hassles I figured out, that I've absolutely no clue about these internals. Why do I need some ctr0.o, crti.o etc. Where those come from etc. Is it linked to the compiler/linker or C runtime libraries or the system?

I would like to learn more about these internals, however, I'm not sure, what em I looking for actually. Is it a library, system, compiler all together?

I understand, that the system (MCU) need's to initialize the variables in RAM, and other stuff, however I miss the complete picture. Can you direct me to a good book/manuals, readings about these things, please? What am I looking for actually?

Edit:

After discussions here with you I most probably figured out, what I need, so I would rephrase my question following way:

1) I've received an MCU (let's say STM32F4xx) and I should create a blinking LED example. All this should be done from scratch, own startup code, no usage external libraries etc.

2) In the second step, someone told me that all this has already been done by others (GCC toolchain/standard libraries, MCU vendor startup files etc.). So I just need to understand/link my work with what was done and compare the differences, why they do it that way etc.

All this was answered by @mbjoe + I found some interesting reading: https://www.amazon.com/Embedded-Shoestring-experience-designing-software/dp/0750676094

Thank all of you for your help and directing me the right way!

like image 211
ST Renegade Avatar asked Apr 27 '17 06:04

ST Renegade


1 Answers

The modules you are referring to (ctr0.o, crti.o, _init, __libc_init_array, _exit) are prebuilt libraries/object files/functions by IAR and/or Keil. As you are saying they are needed to get the environment initialized (global variables initialization, interrupt vector table, etc.) before running your main() function.

At some point in those libraries/object files there will be a function in C or assembly like this:

void startup(void)
{ 
    ... init code ...

    main();

    while(1);   // or _exit()
}

You may look into these examples that build the startup code from scratch:

http://www.embedded.com/design/mcus-processors-and-socs/4007119/Building-Bare-Metal-ARM-Systems-with-GNU-Part-1--Getting-Started

https://github.com/payne92/bare-metal-arm

like image 117
BillyJoe Avatar answered Sep 18 '22 17:09

BillyJoe