[ECOS] bit band macro names from Cortex-M3

Bernard Fouché bernard.fouche@kuantic.com
Fri Dec 9 14:09:00 GMT 2011


Le 08/12/2011 16:10, Nick Garnett a écrit :
> On 08/12/11 08:53, Bernard Fouché wrote:
>> Hi.
>>
>> I'd like to be get suggestions about suitable macro names for bit band
>> operations on the Cortex-M3.
>>
>> [snip]
> [ I intended this to be a short response, but it seems to have turned
> into an essay. I apologise for the length, I didn't have time to make it
> shorter. ]
Thanks for the detailed answer!
> [snip]
>
> The issue of portability is important. You suggest replacing the bit
> banding macros on platforms that don't have it with work-alike macros.
> This means that these macros would need to do individual
> read-modify-write cycles on such targets, which are much more expensive.
If someone is already doing bit test/set/read-modify-write at 
application level, then this person probably uses stuff like _BV(bit) . 
And since eCos does not provide its own set of such macros, everybody 
has to setup its own set. BTW looking at the GPIO block of the LPC17XX, 
bit-banding greatly simplifies single pin accesses.
> One of the common idioms for updating a register is to read it, set and
> clear a number of bits in the local copy, maybe over a substantial piece
> of code, and write it back at the end. It would be much less efficient
> to do this bit-by-bit. And there is the possibility of putting the
> device into an inconsistent state by changing individual bits that the
> final write-back commit does not.
The opposite is true. For instance the power control register of the 
LPC17XX is a 32 bits field accessed by hal_lpc_set_power(). This is a 
particular design choice from NXP to have different peripherals all 
depending on a single register but unless the function accessing this 
register locks interrupts, different parts of the application, ISR and 
drivers modifying this register would trigger bugs if using 
read-modify-write. In that particular case bit-banding is very handy and 
maybe the only reasonable solution. Of course, in a more general manner, 
as soon as more than a single bit access is required, bit-banding does 
not bring any advantage.
> Another idiom is used to test status registers, These are usually read
> into a local copy and then single or groups of bits can be tested. There
> are usually several such tests sequentially, and having a copy of the
> status register in a CPU register makes this fast and efficient.
>
> In my experience, the number of times we need to explicitly set or clear
> a single bit in a register is relatively rare. Testing single bits is
> slightly more frequent, but I don't see bit banding saving very much
> there; runtime calculation of the banding address might even make it
> more expensive.
IMHO bit-banding is mostly useful for drivers accessing peripheral 
registers and such accesses are generally done using constant addresses. 
Being able to shorten an ISR often triggered by using bit banding seems 
efficient to me, the question is not to replace existing efficient code 
and macros by moving everything to bit-band accesses for the fun of it, 
but just to have a supplementary tool at hand when coding for a platform 
that supports it and for a target that can take advantage of it.
> ...
>
> We could have defined bit set/test macros long ago but decided not to
> for many of the above reasons. In fact, I seem to recall making a
> conscious decision early in eCos' life to not define such macros to
> actively discourage their use. The same thinking led me to not defining
> such macros for bit banding.
Well the choice of MCU evolved, they have more features than before, my 
wish is just to have official eCos macro names if someone wants to use 
this particular feature instead of having different macros defined, and 
not to make advertisement about how bit-banding is fantastic.
> You mention that you are writing drivers for the LPC1XXX family. These
> are a good example to use. Most of the devices on these parts are shared
> with the LPC2XXX family. We should be sharing drivers between these
> families. In the public repository, the lpc1766stk target already uses
> the LPC2XXX wallclock, serial and ethernet drivers; in eCosPro we
> additionally share the SPI, I2C, flash and watchdog drivers. Your
> example seems to be for an ADC driver, however, there is already an
> LPC2XXX ADC driver that should probably be adapted to work for the LPC1XXX.

This triggers another discussion ;-)

I've first made a port of the LPC24XX ADC driver and while doing this I 
realized this driver let run the 200KHz ADC all the time, even if you 
need a few samples per second. If you stop needing samples, it continues 
to run forever, the same for the timer.

We are serving markets which need aggressive power management and I had 
to make a different version. Overall all of my arguments are driven 
because of power efficiency: I don't use bit-band or power control for 
the fun of it, it's just because my power budget has similarities to 
France's financial situation while my customers want all the possible 
bells and whistles requiring a MCU like the LPC.

The ADC driver I have is now able to keep the same interface with the 
upper ADC API but runs the ADC hardware for the exact amount of samples 
you want: if the sampling rate is defined at 1KHz at the upper layer, 
there are 1 000 samples taken per second, no more. It also 
connects/disconnects the ADC (and the used timer) using the power 
control register. If the ADC runs, the timer is stopped. When the ADC is 
done, it starts the timer (it would have been fine if the upper layer 
supported an amount of required samples instead of only a sampling rate 
;-)).

> Adding bit banding support to these drivers would render the LPC2XXX
> versions less efficient. I also expect that if a new LPC1XXX driver were
> written using bit banding macros, then it would get rewritten to use the
> traditional method once it was ported to the LPC2XXX family.
In my case the problem is not portability or software reuse of drivers 
across a MCU familly. It's to be able to have the MCU we have chosen to 
provide all the features we need (and that triggered the decision to 
consider this particular MCU) while keeping the power cost at the 
minimum level. We don't use the PLL0 for instance, we clock directly 
from the xtal, we have no external memory, the whole system is tight on 
resources, so I have to review all the drivers and eventually rewrite if 
I consider that there is some power to be saved.

BTW I've also a problem with the way _init()/_lookup() works: eCos 
assumes that because a driver appears in DEVTAB_ENTRY(), the underlying 
hardware must be completely setup (but for a few details eventually 
configured later) from _init(). The problem is I need nearly no driver 
but SYSTICK and the GPIO block (eventually the RTC) at boot time, until 
some event triggers processing that requires one or more particular 
drivers. It's only at this time that I wish to power a peripheral and 
then configure it. And I soon as I don't need a peripheral, I have to 
stop powering it... Too bad there is not _uninit()/_unlookup() :-), the 
current boot organization can't benefit from per-peripheral power control.

> I can imagine that there are situations where bit banding is useful. For
> example high speed signalling on GPIO lines, or doing certain classes of
> encryption or compression in on-chip RAM; but those would all need very
> application specific code. I find it difficult to see that it will be
> any significant advantage to handling the control and status registers
> of conventional devices.
It's just a part of the toolset for the power stingy !

     Bernard

-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss



More information about the Ecos-discuss mailing list