[ell-i-developers] About peripheral initialisation and "anomalies" wrt it

  • From: Pekka Nikander <pekka.nikander@xxxxxx>
  • To: ell-i-developers@xxxxxxxxxxxxx
  • Date: Wed, 29 Jan 2014 21:36:08 +0200

All,

In the new ELL-i runtime we have a completely new peripheral initialisation 
approach, which I have never tried in this format before.  The basic idea 
behind this structure is to use the compiler and linker to initialise only 
those peripherals that are actually used by an Arduino sketch.  Unfortunately 
the Arduino API has a number of nasty features that prevent us from getting 
there, at least immediately.  But I think it is still worth trying and taking 
steps towards that direction.  

A central feature of this new peripheral initialisation system is a completely 
new linker section, which is used to collect peripheral initialisation records. 
 The idea is that if the source code touches only the initialisation records 
for those peripherals that it uses, only those records will be placed in the 
section, and therefore only those peripherals will get initialised.  Apparently 
that does not work as intended, at least not yet, as Ivan has painstakingly 
notices.  (My apologies Ivan for throwing you out to the cold water without 
first even putting my toe there.  I'm apparently growing too self-confident. :-)

As a temporary (but probably long living) stop gag for this, the 
variants/ellduino/ellduino.cpp file explicitly refers to the GPIO and TIMer 
initialisation records, and it is explicitly listed on the linker command line, 
not pulled from the library.  (It wouldn't get pulled from the library.)

I was hoping that with the Serial objects we could do better, and get the USART 
initialisation records linked in by demand.  Apparently that doesn't succeed 
easily.  Ivan, I surmise it is not very useful for you to try out various 
tricks, I'll need to return to this, but it is not very high priority at the 
moment.  So, let's let it be for now, and simply add the USART init records to 
elluino.cpp as IIRC you have already done in your local copy.

Now, putting this in a larger context there are a few things we need to do now 
soon, and then some more that we should try later.

First, we should split the initialisation linker section into three 
subsections: one for RCC records for activating the peripherals, one for the 
"normal" peripheral initialisations, and the last for the "secondary" 
peripheral initialisations that are used with some peripherals to actually 
activate them.  Then, we put these into the linker script in the right order, 
and make sure that each record goes to the right section.  This should fix the 
ordering problem that you've been facing, Ivan.

Second, we should further explore how the compiler behaves when we have 
references to the initialisation sections in static const objects that get 
optimised away.  You tried that already somewhat, with the initial result that 
at least sometimes the compiler also optimises away the reference to the extern 
initialisation record, so that it doesn't get included.  But this we can do 
with time.

Then, probably later, we should implement a late compiler/linker pass (in LLVM) 
that scans the initialisation records and optimises them.  This should be quite 
trivial for the RCC section, for the other sections it maybe somewhat more 
involved.  One more option is to create another, much earlier compiler pass 
that would take care of recording the references so that we would really get 
the peripherals that are used.  However, that would be much more involved and 
would still fail for sketches that use dynamic runtime computed references to 
pins or peripherals.  Fortunately those are rare.

--Pekka






Other related posts: