[ell-i-developers] Re: Linker non used peripheral removal

  • From: Pekka Nikander <pekka.nikander@xxxxxx>
  • To: ell-i-developers@xxxxxxxxxxxxx
  • Date: Thu, 23 Jan 2014 21:37:16 +0200


> I read this piece of comment about the removal of unused peripherals, in 
> particular the timers.
> @wiring_analog.h
>  * With the current Arduino API, it is not possible to reliably
>  * determine at compile time which PWM ports are used and which are
>  * not.  Hence, the only viable option at the moment is to explicitly
>  * refer to the TIMER system init records, by creating explicit
>  * references to them.  With the -fdata-sections gcc options, the
>  * __TIMERx names below will be deleted during link time, leaving only
>  * the referenced and explicitly kept TIMERx_INIT records into the
>  * linked code (due to the corresponding linker KEEP directive.)
> @flash.ld
> KEEP (*(.peripheral.*)) /* Read-only peripheral initialisation data */
> I don't know how to track if those unused elements should be removed by the 
> linker or not, and then not activated during the initialization of the system.
> The point is that right now all the peripherals are activated, regardless of 
> their use or not. In particular, all the timers are registered.

You are right.  The comment is misleading; please propose how to rephrase it 
more accurately.  If you find a good wording, simply implement it, commit, and 
create a pull request.  If you want to discuss the wording, feel free to do it 

The primary goal of the peripheral initialisation system is to automatically 
initialise only those peripherals that are used.  That would save same energy 
and memory.  (The saved energy might be a considerable amount if we end up 
having hundred of millions ELL-i nodes around there, in which case even one 
saved mA is hundreds of thousands of amperes / kilowatts globally.)

As far as I can see, such automatic usage detection should be possible with the 
serial ports, which will be represented as statically allocated C++ objects in 
our runtime; I'm working on that right now.  However, with the GPIO pins and 
the associated timers that seems to be pretty impossible, since at the Arduino 
API they are referred to through the Arduino pin numbers only.  Hence, at the 
moment we just cannot keep track of which GPIO ports and which timers are used 
by a particular Arduino sketch and which are not, and simply have to compile in 
all of the required initialisation code, and initialise them all.

I considered making the pin_t type a C++ class, when compiling C++.  Currently 
it simply is an uint32_t, IIRC.  However, that would require either quite big 
changes to the compilation or a very careful usage of C++ POD types.  That is, 
if the pin_t was a POD object type, it might be possible to use the linker to 
keep track of which GPIO ports are used and which are not.  However, I haven't 
tried that so I don't know -- my C++ fu is still clearly weaker than my C fu, 
there are many C++11 features that I'm unfamiliar with.

Another optimisation that I'm planning that we could do later is a separate 
linker pass that combines a number of peripheral init records.  For example, it 
could take all changes to the RCC->ABHENR and create just a single record out 
of them.  However, creating such passes is much easier with LLVM than with GCC; 
hence I'm postponing even thinking (much) about that until after having moved 
to LLVM.


Other related posts: