This is the mail archive of the ecos-discuss@sourceware.org mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: bit band macro names from Cortex-M3



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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]