Difference between revisions of "Using dev/board.h"

From Nutwiki
Jump to: navigation, search
(New page: == Purpose == The header file dev/board.h contains a number of definitions, which help to write portable applications. When using these definitions, your code will be compilable for diffe...)
 
m (1 revision imported)
 
(No difference)

Latest revision as of 17:03, 27 October 2016

Purpose

The header file dev/board.h contains a number of definitions, which help to write portable applications. When using these definitions, your code will be compilable for different targets without change.

Drivers and device names

Nut/OS doesn't initialize any drivers by default. It's up to the application programmer to select the right drivers and register them by calling NutRegisterDevice. However, different targets use different drivers. To register the USART0 driver for the 8-bit AVR, you may use

<source lang="c"> NutRegisterDevice(&devUsartAvr0, 0, 0); </source>

while the USART0 registration for the 32-bit AT91 family is

<source lang="c"> NutRegisterDevice(&devUsartAt910, 0, 0); </source>

When building system libraries and applications, Nut/OS provides a predefined platform macro for the configured target board. This could be used to include or exclude target specific parts of your code. For example, when building for the AVR based Ethernut 1.3 the macro ETHERNUT1 will be defined. When building for the ARM7 based Ethernut 3.1 the macro ETHERNUT3 will be defined instead.

An application may use this to register the right USART driver:

<source lang="c">

  1. if defined(ETHERNUT1)

NutRegisterDevice(&devUsartAvr0, 0, 0);

  1. elif defined(ETHERNUT3)

NutRegisterDevice(&devUsartAt910, 0, 0);

  1. endif

</source>

As the number of supported platforms grows, this will result in many additional lines and the code will become less readable. The solution is to include dev/board.h:

<source lang="c">

  1. include <dev/board.h>

NutRegisterDevice(&DEV_UART0, 0, 0); </source>

A similar problem is solved by dev/board.h with higher level I/O functions. To open a device, you must pass the symbolic name of the driver. In many cases, UART drivers use the same name for all targets, e.g. "uart0" for the USART0 driver. Therefore the following line will work on almost any target. It opens the USART device to be used for stdout.

<source lang="c"> freopen("uart0", "w", stdout); </source>

At least during development you'll prefer the debug device for stdout, because it is unbuffered, giving immediate output, and it can be used inside interrupt handlers. While AT91 targets do have a specific DBGU interface, this is not available on the 8-bit AVRs, where the USART0 interface is used instead. Note the difference between the software driver and the hardware interface: Both, the devDebug0 driver and the devUsartAvr0 driver for the AVR use the USART0 interface. Thus, only one of them can be registered and that's the reason why they use the same symbolic name. If two registered drivers have the same symbolic name, the previous registration will be overridden by the last. On the AT91, where the debug driver uses a dedicated interface, the symbolic names of the debug and USART drivers differs.

Again, dev/board.h allows to transfer the following portable code

<source lang="c">

  1. if defined(ETHERNUT1)

NutRegisterDevice(&devDebug0, 0, 0); freopen("uart0", "w", stdout);

  1. elif defined(ETHERNUT3)

NutRegisterDevice(&devDebug, 0, 0); freopen("dbgu", "w", stdout);

  1. endif

</source>

into a simpler version

<source lang="c">

  1. include <dev/board.h>

NutRegisterDevice(&DEV_DEBUG, 0, 0); freopen(DEV_DEBUG_NAME, "w", stdout); </source>