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


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.
> 
> Since this is a MCU option, they should be defined per MCU.
> 
> Actually working on the LPC17XX, I have defined:
> 
> //=============================================================================
> // LPC17XX supports CORTEX-M3 bit banding option
> #define CYGHWR_HAL_LPC17XX_BITBAND_SRAM_PHY             0x20000000  // 
> to 0x200FFFFF (1 meg)
> #define CYGHWR_HAL_LPC17XX_BITBAND_SRAM_BB              0x22000000
> // Convert SRAM address
> #define CYGHWR_HAL_LPC17XX_BITBAND_SRAM(address,bit)\
>    ((CYGHWR_HAL_LPC17XX_BITBAND_SRAM_BB +\
>      (address-CYGHWR_HAL_LPC17XX_BITBAND_SRAM_PHY)*32 +\
>      (bit*4)))
> 
> #define CYGHWR_HAL_LPC17XX_BITBAND_PERI_PHY             0x40000000  // 
> to 0x400FFFFF
> #define CYGHWR_HAL_LPC17XX_BITBAND_PERI_BB              0x42000000
> // Convert PERIPHERAL address
> #define CYGHWR_HAL_LPC17XX_BITBAND_PERI(address,bit)\
>    ((CYGHWR_HAL_LPC17XX_BITBAND_PERI_BB +\
>      (address-CYGHWR_HAL_LPC17XX_BITBAND_PERI_PHY)*32 +\
>      (bit*4)))
> 
> Use case:
> 
>      // add channel to pool
>      *(volatile cyg_uint32 
> *)CYGHWR_HAL_LPC17XX_BITBAND_PERI(ADC_CR,1<<chan->channel)=1;
> 
> Another possibility would be to provide higher level macros for bit 
> set/test/read-modify-write operations and have these macros to use bit 
> band if the targets support them. However bit band operations will 
> probably be used only in driver code specific to a MCU familly and the 
> driver designer may prefer to explicitly states when a bit band 
> operation is used.
> 
> Since I'll provide some drivers in the next weeks, it would be nice if 
> these drivers already use macro names acceptable for eCos maintainers.

[ 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. ]

I looked at the bit-banding support in the Cortex-M architecture when I
originally started the architecture port. I also considered adding some
defines and macros to make use of it. In the end I decided not to for
several reasons:

It is at odds with the common way of doing device access in eCos by
using the HAL_[READ|WRITE]_UINT* macros. These make all accesses to
device registers very explicit, and the order of access clear. Allowing
register accesses to look like assignments means that they can get lost
or overlooked. The macros also mean that the accesses are correctly
sized and the necessary attributes, such as volatile, are applied.

Most eCos drivers use these macros, and over time a number of idioms
have been established which make such drivers easier to read and modify.
We do have a few drivers that use the deprecated approach of mapping a
struct over the registers, and these are harder to read and work on.

The example you show above looks to me long and rather messy. So your
suggestion of wrapping these accesses in macros would have to be
adopted. This approach answers some of the issues raised above.

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.

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.

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.

Bit banding also doesn't really work for multi-bit fields, which have to
be updated in the traditional manner.

Our current register definitions tend to be in terms of bit masks, while
the bit banding macros would need bit offsets. The masks are still
needed for traditional register access, and offset versions would have
to be added for the banding macros. This raises problems of divergence
in the definitions, and the prospect of using the wrong version of the
definition.

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.


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.

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.


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.

In general, the small advantages that bit banding gives doesn't seem
worth the loss of portability, readability and simplicity.

Of course you can do what you want in writing device drivers. You can
even propose a set of bit banding macros to go into the HAL headers for
specialized use. However, I remain unconvinced that they should be used
for writing device drivers.

-- 
Nick Garnett                                      eCos Kernel Architect
eCosCentric Limited    http://www.eCosCentric.com      The eCos experts
Barnwell House, Barnwell Drive, Cambridge, UK.     Tel: +44 1223 245571
Registered in England and Wales:                        Reg No: 4422071

--
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]