[En-Nut-Discussion] Porting means breaking the rules?

Harald Kipp harald.kipp at egnite.de
Thu Sep 2 13:12:23 CEST 2010


On 01.09.2010 23:17, Ulrich Prinz wrote:

> The reason for having lots of #ifdef in the USART code of an AVR was, 
> that you had to do a lot of things manually like handshake and direction 
> switching of RD485 drivers.

There is one thing that is often overlooked with AVR code:

 sbi(PORTA, 1);

results in a single bitset machine instruction as long as constants are
provided as parameters. This will be no longer the case for

 sbi(base + PORTA_OFFSET, 1);

or

 sbi(PORTA, pin_info->rts_pin);

With a single character hardware FIFO only, the UART driver is most
sensitive to every single instruction that may be added to the code.

I fully agree: As a result, the code is contaminated with tons of
#ifdefs, which makes it more a less unreadable. Furthermore, in order to
avoid duplicated code, the AVR driver includes a C source file (.c
instead of .h), which sometimes confuses debugger tools and always
confuses the programmer.

OK, I'm simply repeating your concerns to underline them. :-)


> Together with the fact, that all ARM and Cortex CPU unified their 
> peripheral register layout, this means, that you have a single driver 
> and just exchange the base address of the device.

Right. The requirements of the low end 8-bit AVR do not apply to the
higher end controllers. In fact, the AVR code results in larger code for
the other CPUs.


> base_address:
...
> first_interrupt:
...
> dev_icb:
...

As suggested, you can try to re-use currently unused items as described,
but you can also add your own, using these ugly #ifdefs. IMHO, the
priority is

1. Execution speed
2. Code size
3. Code readability


> Putting these information into dev_icb enables two things at once:
> in nutconf you can select the configuration with a simple drop down list.
> Giving the right values, in a lot of CPUs pins and bits can be handled 
> by special instructions making them atomic what saves some IRQ switching.

This makes sense to me. In any case, if anyone is using an exotic board
layout, he can always modify existing driver code.


> There is a lot of troubles with the GPIO control interface.

I feel guilty. Also Michael Fischer lately criticized this while trying
to get the AVR32 boards running. As far as I understood, he made a few
changes on the AVR32 code to make it more unified. But I haven't found
the time to study his code in more detail. :-(

He also suggested to sequentially number all port bits. Let's say, port
33 will be PE1 on the AVR8 and PB1 on the ARM. After thinking about this
in more detail, I don't like it. It may confuse people even more and may
not fit to all platforms. I still recommend to divide port access into
banks and pins. This is more flexible.


> There are defines that address the physical base address of a port. Then 
> there are defines that address a logical port number.

As admitted, I did a first hack, refined it later and got confused
myself again after some more refinements. I'm not proud of this design.

Btw. although not as weird as with Nut/OS, the history of Linux GPIO
isn't that streamlined either. ;-)


> This allows bit manipulation in a single assembler instruction but the 
> need is to have the bit manipulation definitions of Nut/OS done in 
> another way.

FYI, we already have two variants in Nut/OS. One is the gpio_XXX.c
library, which is easy to port and to use. And we do have macros in
arch/porttran.h, which are a bit more difficult (based on the
pre-processor, requiring #undefs), which produce optimal code.

In summary, I welcome your ideas and your efforts in supporting the
Cortex CPUs. As a short side note: Please commit your changes divided
into comprehensible parts. Do not mix up cosmetic and logical code
changes. Going this way, there are no limits for you, because everyone
can easily follow them and they can be easily reverted, if required.


Regards,

Harald



More information about the En-Nut-Discussion mailing list