75 lines
3.4 KiB
ReStructuredText
75 lines
3.4 KiB
ReStructuredText
|
==============================================
|
||
|
APIs Exported by Board-Specific Logic to NuttX
|
||
|
==============================================
|
||
|
|
||
|
Exported board-specific interfaces are prototyped in the header
|
||
|
file ``include/nuttx/board.h``. There are many interfaces exported
|
||
|
from board- to architecture-specific logic. But there are only a
|
||
|
few exported from board-specific logic to common NuttX logic.
|
||
|
Those few of those related to initialization will be discussed in
|
||
|
this paragraph. There are others, like those used by
|
||
|
```boardctl()`` <#boardctl>`__ that will be discussed in other
|
||
|
paragraphs.
|
||
|
|
||
|
All of the board-specific interfaces used by the NuttX OS logic
|
||
|
are for controlled board initialization. There are three points in
|
||
|
time where you can insert custom, board-specific initialization
|
||
|
logic:
|
||
|
|
||
|
First, ``<arch>_board_initialize()``: This function is *not*
|
||
|
called from the common OS logic, but rather from the
|
||
|
architecture-specific power on reset logic. This is used only for
|
||
|
initialization of very low-level things like configuration of GPIO
|
||
|
pins, power settings, DRAM initialization, etc. The OS has not
|
||
|
been initialized at this point, so you cannot allocate memory or
|
||
|
initialize device drivers.
|
||
|
|
||
|
The other two board initialization *hooks* are called from the OS
|
||
|
start-up logic and are described in the following paragraphs:
|
||
|
|
||
|
.. c:function:: void board_early_initialize(void)
|
||
|
|
||
|
The next level of initialization is performed by a call to
|
||
|
``up_initialize()`` (in
|
||
|
``arch/<arch>/src/common/up_initialize.c``). The OS has been
|
||
|
initialized at this point and it is okay to initialize drivers in
|
||
|
this phase. ``up_initialize()`` is *not* a board-specific
|
||
|
interface, but rather an architecture-specific, board-independent
|
||
|
interface.
|
||
|
|
||
|
But at this same point in time, the OS will also call a
|
||
|
board-specific initialization function named
|
||
|
``board_early_initialize()`` if
|
||
|
``CONFIG_BOARD_EARLY_INITIALIZE=y`` is selected in the
|
||
|
configuration. The context in which ``board_early_initialize()``
|
||
|
executes is suitable for early initialization of most, simple
|
||
|
device drivers and is a logical, board-specific extension of
|
||
|
up_initialize().
|
||
|
|
||
|
``board_early_initialize()`` runs on the startup, initialization
|
||
|
thread. Some initialization operations cannot be performed on the
|
||
|
start-up, initialization thread. That is because the
|
||
|
initialization thread cannot wait for event. Waiting may be
|
||
|
required, for example, to mount a file system or or initialize a
|
||
|
device such as an SD card. For this reason, such driver initialize
|
||
|
must be deferred to ``board_late_initialize()``.
|
||
|
|
||
|
.. c:function:: void board_late_initialize(void)
|
||
|
|
||
|
And, finally, just before the user application code starts. If
|
||
|
``CONFIG_BOARD_LATE_INITIALIZE=y`` is selected in the
|
||
|
configuration, then an final, additional initialization call will
|
||
|
be performed in the boot-up sequence to a function called
|
||
|
``board_late_initialize()``. ``board_late_initialize()`` will be
|
||
|
called well after ``up_initialize()`` and
|
||
|
``board_early_initialize()`` are called.
|
||
|
``board_late_initialize()`` will be called just before the main
|
||
|
application task is started. This additional initialization phase
|
||
|
may be used, for example, to initialize more complex,
|
||
|
board-specific device drivers.
|
||
|
|
||
|
Waiting for events, use of I2C, SPI, etc are permissible in the
|
||
|
context of board_late_initialize(). That is because
|
||
|
``board_late_initialize()`` will run on a temporary, internal
|
||
|
kernel thread.
|