Skip to content
Snippets Groups Projects
NuttxPortingGuide.html 113 KiB
Newer Older
patacongo's avatar
patacongo committed
make
</pre></ul>
<p>
  The <code>${TOPDIR}</code> directory holds:
</p>
<ul>
  <li>The top level <a href="#topmakefile"><code>Makefile</code></a> that controls the NuttX build.
</ul>
<p>
  That directory also holds:
</p>
<ul>
patacongo's avatar
patacongo committed
  <li>The makefile fragment <a href="#boardconfigsubdirs"><code>.config</code></a> that describes the current configuration.</li>
patacongo's avatar
patacongo committed
  <li>The makefile fragment <a href="#boardconfigsubdirs"><code>Make.defs</code></a> that provides customized build targets, and</li>
patacongo's avatar
patacongo committed
  <li>The shell script <a href="#boardconfigsubdirs"><code>setenv.sh</code></a> that sets up the configuration environment for the build.</li>
patacongo's avatar
patacongo committed
</ul>
<p>
patacongo's avatar
patacongo committed
The <a href="#boardconfigsubdirs"><code>setenv.sh</code></a> contains Linux/Cygwin environmental settings that are needed for the build.
The specific environmental definitions are unique for each board but should include, as a minimum, updates to the <code>PATH</code> variable to include the full path to the architecture-specific toolchain identified in <a href="#boardconfigsubdirs"><code>Make.defs</code></a>.
The <a href="#boardconfigsubdirs"><code>setenv.sh</code></a> only needs to be source'ed at the beginning of a session.
patacongo's avatar
patacongo committed
The system can be re-made subsequently by just typing <code>make</code>.
</p>
<p>
  <b>First Time Make.</b>
  Additional configuration actions will be taken the first time that system is built.
  These additional steps include:
</p>
<ul>
  <li>Auto-generating the file <code>include/nuttx/config.</code> using the <code>${TOPDIR}/.config</code> file.
  <li>Creating a link to <code>${TOPDIR}/arch/</code><i>&lt;arch-name&gt;</i><code>/include</code> at <code>${TOPDIR}/include/arch</code>.
  <li>Creating a link to <code>${TOPDIR}/configs/</code><i>&lt;board-name&gt;</i><code>/include</code> at <code>${TOPDIR}/include/arch/board</code>.
  <li>Creating a link to <code>${TOPDIR}/configs/</code><i>&lt;board-name&gt;</i><code>/src</code> at <code>${TOPDIR}/arch/</code><i>&lt;arch-name&gt;</i><code>/src/board</code>
  <li>Creating make dependencies.
</ul>
patacongo's avatar
patacongo committed

<table width ="100%">
  <tr bgcolor="#e4e4e4">
    <td>
      <h1>4.0 <a name="ArchAPIs">Architecture APIs</a></h1>
    </td>
  </tr>
</table>
patacongo's avatar
patacongo committed

<p>
  The file <code>include/nuttx/arch.h</code> identifies by prototype all of the APIs that must
  be provided by the architecture specific logic.
  The internal OS APIs that architecture-specific logic must
  interface with also also identified in <code>include/nuttx/arch.h</code> or in
  other header files.
</p>

<h2><a name="imports">4.1 APIs Exported by Architecture-Specific Logic to NuttX</a></h2>
<h3><a name="upinitialize">4.1.1 <code>up_initialize()</code></a></h3>

<p><b>Prototype</b>: <code>void up_initialize(void);</code></p>

<p><b>Description</b>.
  <code>up_initialize()</code> will be called once during OS
  initialization after the basic OS services have been
  initialized.  The architecture specific details of
  initializing the OS will be handled here.  Such things as
  setting up interrupt service routines, starting the
patacongo's avatar
patacongo committed
  clock, and registering <a href="#DeviceDrivers">device drivers</a> are some of the
patacongo's avatar
patacongo committed
  things that are different for each processor and hardware
  platform.
</p>
<p>
  <code>up_initialize()</code> is called after the OS initialized but
  before the init process has been started and before the
  libraries have been initialized.  OS services and driver
  services are available.
</p>

<h3><a name="upidle">4.1.2 <code>up_idle()</code></a></h3>
<p><b>Prototype</b>: <code>void up_idle(void);</code></p>

<p><b>Description</b>.
  <code>up_idle()</code> is the logic that will be executed
  when their is no other ready-to-run task.  This is processor
  idle time and will continue until some interrupt occurs to
  cause a context switch from the idle task.
</p>
<p>
  Processing in this state may be processor-specific. e.g.,
  this is where power management operations might be performed.
</p>

<h3><a name="upinitialstate">4.1.3 <code>up_initial_state()</code></a></h3>
<p><b>Prototype</b>: <code>void up_initial_state(FAR _TCB *tcb);</code></p>

<p><b>Description</b>.
  A new thread is being started and a new TCB
  has been created. This function is called to initialize
  the processor specific portions of the new TCB.
</p>
<p>
patacongo's avatar
patacongo committed
  This function must setup the initial architecture registers
patacongo's avatar
patacongo committed
  and/or  stack so that execution will begin at tcb->start
  on the next context switch.
</p>

<h3><a name="upcreatestack">4.1.4 <code>up_create_stack()</code></a></h3>
<p><b>Prototype</b>: <code>STATUS up_create_stack(FAR _TCB *tcb, size_t stack_size);</code></p>

<p><b>Description</b>.
  Allocate a stack for a new thread and setup
  up stack-related information in the TCB.
</p>
<p>
  The following TCB fields must be initialized:
</p>
<ul>
  <li><code>adj_stack_size</code>: Stack size after adjustment for hardware,
    processor, etc.  This value is retained only for debug
    purposes.</li>
  <li><code>stack_alloc_ptr</code>: Pointer to allocated stack</li>
  <li><code>adj_stack_ptr</code>: Adjusted <code>stack_alloc_ptr</code> for HW.  The
    initial value of the stack pointer.
</ul>
<p>
  This API is <i>NOT</i> required if <code>CONFIG_CUSTOM_STACK</code>
  is defined.
</p>

<p><b>Inputs</b>:</p?
<ul>
  <li>
    <code>tcb</code>: The TCB of new task.
  </li>
  <li>
    <code>stack_size</code>:  The requested stack size.  At least this much
    must be allocated.
  </li>
</ul>

<h3><a name="upusestack">4.1.5 <code>up_use_stack()</code></a></h3>
<p><b>Prototype</b>: 
  <code>STATUS up_use_stack(FAR _TCB *tcb, FAR void *stack, size_t stack_size);</code>
</p>

<p><b>Description</b>.
  Setup up stack-related information in the TCB
  using pre-allocated stack memory.
</p>
<p>
  The following TCB fields must be initialized:
</p>
<ul>
  <li><code>adj_stack_size</code>: Stack size after adjustment for hardware,
    processor, etc.  This value is retained only for debug
    purposes.</li>
  <li><code>stack_alloc_ptr</code>: Pointer to allocated stack</li>
  <li><code>adj_stack_ptr</code>: Adjusted <code>stack_alloc_ptr</code> for HW.  The
    initial value of the stack pointer.
</ul>
<p>
  This API is <i>NOT</i> required if <code>CONFIG_CUSTOM_STACK</code>
  is defined.
</p>

<p><b>Inputs:</b></p>
<ul>
  <li>
    <code>tcb</code>: The TCB of new task.
  </li>
  <li>
    <code>stack_size</code>:  The allocated stack size.
  </li>
</ul>

<h3><a name="upreleasestack">4.1.6 <code>up_release_stack()</code></a></h3>
<p><b>Prototype</b>: <code>void up_release_stack(FAR _TCB *dtcb);</code></p>

<p><b>Description</b>.
  A task has been stopped. Free all stack
  related resources retained int the defunct TCB.
</p>
<p>
  This API is <i>NOT</i> required if <code>CONFIG_CUSTOM_STACK</code>
  is defined.
</p>

<h3><a name="upunblocktask">4.1.7 <code>up_unblock_task()</code></a></h3>
<p><b>Prototype</b>: <code>void up_unblock_task(FAR _TCB *tcb);</code></p>

<p><b>Description</b>.
  A task is currently in an inactive task list
  but has been prepped to execute.  Move the TCB to the
  ready-to-run list, restore its context, and start execution.
</p>
<p>
  This function is called only from the NuttX scheduling
  logic.  Interrupts will always be disabled when this
  function is called.
</p>

<p><b>Inputs</b>:
<ul>
  <li><code>tcb</code>: Refers to the tcb to be unblocked.  This tcb is
    in one of the waiting tasks lists.  It must be moved to
    the ready-to-run list and, if it is the highest priority
patacongo's avatar
patacongo committed
    ready to run tasks, executed.
patacongo's avatar
patacongo committed
  </li>
</ul>

<h3><a name="upblocktask">4.1.8 <code>up_block_task()</code></a></h3>
<p><b>Prototype</b>: <code>void up_block_task(FAR _TCB *tcb, tstate_t task_state);</code></p>

<p><b>Description</b>.
  The currently executing task at the head of
  the ready to run list must be stopped.  Save its context
  and move it to the inactive list specified by task_state.

  This function is called only from the NuttX scheduling
  logic.  Interrupts will always be disabled when this
  function is called.

<p><b>Inputs:</b></p>
<ul>
  <li><code>tcb</code>: Refers to a task in the ready-to-run list (normally
    the task at the head of the list).  It most be
patacongo's avatar
patacongo committed
    stopped, its context saved and moved into one of the
    waiting task lists.  It it was the task at the head
    of the ready-to-run list, then a context to the new
    ready to run task must be performed.
  </li>
  <li><code>task_state</code>: Specifies which waiting task list should be
    hold the blocked task TCB.
  </li>
</ul>

<h3><a name="upreleasepending">4.1.9 <code>up_release_pending()</code></a></h3>
<p><b>Prototype</b>: <code>void up_release_pending(void);</code></p>

<p><b>Description</b>.
  When tasks become ready-to-run but cannot run because pre-emption
  is disabled, they are placed into a pending task list.
  This function releases and makes ready-to-run all of the tasks that have
  collected in the pending task list.  This can cause a
  context switch if a new task is placed at the head of
  the ready to run list.
</p>
<p>
  This function is called only from the NuttX scheduling logic when
  pre-emption is re-enabled.  Interrupts will always be disabled when this
  function is called.
</p>

<h3><a name="upreprioritizertr">4.1.10 <code>up_reprioritize_rtr()</code></a></h3>
<p><b>Prototype</b>: <code>void up_reprioritize_rtr(FAR _TCB *tcb, uint8_t priority);</code></p>
patacongo's avatar
patacongo committed

<p><b>Description</b>.
  Called when the priority of a running or
  ready-to-run task changes and the reprioritization will 
  cause a context switch.  Two cases:
</p>
<ol>
  <li>
    The priority of the currently running task drops and the next
    task in the ready to run list has priority.
  </li>
  <li>
    An idle, ready to run task's priority has been raised above the
    the priority of the current, running task and it now has the
    priority.
  </li>
</ol>
<p>
  This function is called only from the NuttX scheduling
  logic.  Interrupts will always be disabled when this
  function is called.
</p>

<p><b>Inputs:</b></p>
<ul>
  <li>
    <code>tcb</code>: The TCB of the task that has been reprioritized
  </li>
  <li>
    <code>priority</code>: The new task priority
  </li>
</ul>

<h3><a name="_exit">4.1.11 <code>_exit()</code></a></h3>
<p><b>Prototype</b>: <code>void _exit(int status) noreturn_function;</code></p>

<p><b>Description</b>.
  This function causes the currently executing task to cease
  to exist.  This is a special case of task_delete().
</p>
<p>
  Unlike other UP APIs, this function may be called
  directly from user programs in various states.  The
patacongo's avatar
patacongo committed
  implementation of this function should disable interrupts
patacongo's avatar
patacongo committed
  before performing scheduling operations.
</p>

<h3><a name="upassert">4.1.12 <code>up_assert()</code></a></h3>
<p><b>Prototype</b>:<br>
  <code>void up_assert(FAR const uint8_t *filename, int linenum);</code></br>
  <code>void up_assert_code(FAR const uint8_t *filename, int linenum, int error_code);</code></br>
patacongo's avatar
patacongo committed
</p>

<p><b>Description</b>.
  Assertions may be handled in an architecture-specific
  way.
</p>

<h3><a name="upschedulesigaction">4.1.13 <code>up_schedule_sigaction()</code></a></h3>
<p><b>Prototype</b>:
  <code>void up_schedule_sigaction(FAR _TCB *tcb, sig_deliver_t sigdeliver);</code>
</p>

<p><b>Description</b>.
  This function is called by the OS when one or more
  signal handling actions have been queued for execution.
  The architecture specific code must configure things so
patacongo's avatar
patacongo committed
  that the 'sigdeliver' callback is executed on the thread
patacongo's avatar
patacongo committed
  specified by 'tcb' as soon as possible.
</p>
<p>
  This function may be called from interrupt handling logic.
</p>
<p>
  This operation should not cause the task to be unblocked
  nor should it cause any immediate execution of sigdeliver.
  Typically, a few cases need to be considered:
</p>
<ol>
  <li>
    This function may be called from an interrupt handler
    During interrupt processing, all xcptcontext structures
    should be valid for all tasks.  That structure should
    be modified to invoke sigdeliver() either on return
    from (this) interrupt or on some subsequent context
    switch to the recipient task.
  </li>
  <li>
    If not in an interrupt handler and the tcb is NOT
    the currently executing task, then again just modify
    the saved xcptcontext structure for the recipient
    task so it will invoke sigdeliver when that task is
    later resumed.
  </li>
  <li>
    If not in an interrupt handler and the tcb IS the
    currently executing task -- just call the signal
    handler now.
  </li>
</ol>
<p>
  This API is <i>NOT</i> required if <code>CONFIG_DISABLE_SIGNALS</code>
  is defined.
</p>

<h3><a name="upallocateheap">4.1.14 <code>up_allocate_heap()</code></a></h3>
<p><b>Prototype</b>: <code>void up_allocate_heap(FAR void **heap_start, size_t *heap_size);</code></p>

<p><b>Description</b>.
  The heap may be statically allocated by
  defining CONFIG_HEAP_BASE and CONFIG_HEAP_SIZE.  If these
  are not defined, then this function will be called to
  dynamically set aside the heap region.
</p>
<p>
  This API is <i>NOT</i> required if <code>CONFIG_HEAP_BASE</code>
  is defined.
</p>

<h3><a name="upinterruptcontext">4.1.15 <code>up_interrupt_context()</code></a></h3>
<p><b>Prototype</b>: <code>bool up_interrupt_context(void)</code></p>
patacongo's avatar
patacongo committed

<p><b>Description</b>.
  Return true if we are currently executing in the interrupt handler context.
patacongo's avatar
patacongo committed
</p>

<h3><a name="updisableirq">4.1.16 <code>up_disable_irq()</code></a></h3>
<p><b>Prototype</b>:</p>
<ul><pre>
#ifndef CONFIG_ARCH_NOINTC
  void up_disable_irq(int irq);
patacongo's avatar
patacongo committed
#endif
</pre></ul>
patacongo's avatar
patacongo committed

<p><b>Description</b>.
  Disable the IRQ specified by 'irq'
  On many architectures, there are three levels of interrupt enabling: (1)
  at the global level, (2) at the level of the interrupt controller,
  and (3) at the device level.  In order to receive interrupts, they
  must be enabled at all three levels.
</p>
<p>
  This function implements enabling of the device specified by 'irq'
  at the interrupt controller level if supported by the architecture
  (irqsave() supports the global level, the device level is hardware
  specific).
<p>
  If the architecture does not support <code>up_disable_irq</code>,
  <code>CONFIG_ARCH_NOINTC</code> should be defined in the NuttX configuration file.
  Since this API cannot be supported on all architectures, it should be
  avoided in common implementations where possible.
patacongo's avatar
patacongo committed
</p>

<h3><a name="upenableirq">4.1.17 <code>up_enable_irq()</code></a></h3>
<p><b>Prototype</b>:</p>
<ul><pre>
#ifndef CONFIG_ARCH_NOINTC
  void up_enable_irq(int irq);
patacongo's avatar
patacongo committed
#endif
</pre></ul>

<p><b>Description</b>.
  This function implements disabling of the device specified by 'irq'
  at the interrupt controller level if supported by the architecture
  (irqrestore() supports the global level, the device level is hardware
  specific).
</p>
<p>
  If the architecture does not support <code>up_disable_irq</code>,
  <code>CONFIG_ARCH_NOINTC</code> should be defined in the NuttX configuration file.
  Since this API cannot be supported on all architectures, it should be
  avoided in common implementations where possible.
</p>
patacongo's avatar
patacongo committed

<h3><a name="upprioritizeirq">4.1.18 <code>up_prioritize_irq()</code></a></h3>
<p><b>Prototype</b>:</p>
<ul><pre>
#ifdef CONFIG_ARCH_IRQPRIO
  void up_enable_irq(int irq);
patacongo's avatar
patacongo committed
#endif
</pre></ul>
patacongo's avatar
patacongo committed
<p><b>Description</b>.
  Set the priority of an IRQ.
</p>
<p>
  If the architecture supports <code>up_enable_irq</code>,
  <code>CONFIG_ARCH_IRQPRIO</code> should be defined in the NuttX configuration file.
  Since this API cannot be supported on all architectures, it should be
  avoided in common implementations where possible.
patacongo's avatar
patacongo committed
</p>

<h3><a name="upputc">4.1.19 <code>up_putc()</code></a></h3>
patacongo's avatar
patacongo committed

<p><b>Prototype</b>: <code>int up_putc(int ch);</code></p>
<p><b>Description</b>.
  This is a debug interface exported by the architecture-specific logic.
  Output one character on the console
</p>

<h2><a name="exports">4.2 APIs Exported by NuttX to Architecture-Specific Logic</a></h2>
<p>
  These are standard interfaces that are exported by the OS
  for use by the architecture specific logic.
</p>

<h3><a name="osstart">4.2.1 <code>os_start()</code></a></h3>
<p>
  <b><i>To be provided</i></b>
</p>

<h3><a name="listmgmt">4.2.2 OS List Management APIs</a></h3></h3>
<p>
  <b><i>To be provided</i></b>
</p>

<h3><a name="schedprocesstimer">4.2.3 <code>sched_process_timer()</code></a></h3>
<p><b>Prototype</b>: <code>void sched_process_timer(void);</code></p>

<p><b>Description</b>.
  This function handles system timer events.
  The timer interrupt logic itself is implemented in the
  architecture specific code, but must call the following OS
  function periodically -- the calling interval must be
  <code>MSEC_PER_TICK</code>.
</p>

<h3><a name="irqdispatch">4.2.4 <code>irq_dispatch()</code></a></h3>
<p><b>Prototype</b>: <code>void irq_dispatch(int irq, FAR void *context);</code></p>

<p><b>Description</b>.
patacongo's avatar
patacongo committed
  This function must be called from the architecture-
  specific logic in order to display an interrupt to
patacongo's avatar
patacongo committed
  the appropriate, registered handling logic.
</p>

<h2><a name="ledsupport">4.3 LED Support</a></h2>

<p>
  A board architecture may or may not have LEDs.
  If the board does have LEDs, then most architectures provide similar LED support that is enabled when <code>CONFIG_ARCH_LEDS</code>
  is selected in the NuttX configuration file.
  This LED support is part of architecture-specific logic and is not managed by the core NuttX logic.
  However, the support provided by each architecture is sufficiently similar that it can be documented here.
</p>

<h3><a name="ledheaders">4.3.1 Header Files</a></h3>

<p>
  LED-related definitions are provided in two header files:
  <ul>
    <li>
       LED definitions are provided for each board in the <code>board.h</code> that resides
       in the <code><i>&lt;board-name&gt;</i>/include/board.h</code> file (which is also
       linked to <code>include/arch/board/board.h</code> when the RTOS is configured).
       Those definitions are discussed <a href="#leddefinitions">below</a>.
    </li>
    <li>
       The board-specific logic provides unique instances of the LED interfaces.
       This is because the implementation of LED support may be very different
       on different boards.
       Prototypes for these board-specific implementations are, however, provided
       in architecture-common header files.
       That header file is usually at <code><i>&lt;arch-name&gt;</i>/src/common/up_internal.h</code>,
       but could be at other locations in particular architectures.
       These prototypes are discussed <a href="#ledapis">below</a>.
    </li>
  </ul>
</p>

<h3><a name="leddefinitions">4.3.2 LED Definitions</a></h3>

<p>
   The implementation of LED support is very specific to a board architecture. 
   Some boards have several LEDS, others have only one or two. 
   Some have none. 
patacongo's avatar
patacongo committed
   Others LED matrices and show alphanumeric data, etc.
   The NuttX logic does not refer to specific LEDS, rather, it refers to an event to be shown on the LEDS
   in whatever manner is appropriate for the board;
   the way that this event is presented depends upon the hardware available on the board.
</p>
<p>
   The model used by NuttX is that the board can show 8 events defined as follows in <code><i>&lt;board-name&gt;</i>/include/board.h</code>:
</p>
<ul><pre>
#define LED_STARTED       ??
#define LED_HEAPALLOCATE  ??
#define LED_IRQSENABLED   ??
#define LED_STACKCREATED  ??
#define LED_INIRQ         ??
#define LED_SIGNAL        ??
#define LED_ASSERTION     ??
#define LED_PANIC         ??
</pre></ul>
<p>
  The specific value assigned to each pre-processor variable can be whatever makes the implementation easiest for the board logic.
  The <i>meaning</i> associated with each definition is as follows:
</p>
<ul>
  <li>
    <code>LED_STARTED</code> is the value that describes the setting of the LEDs when the LED logic is first initialized.
    This LED value is set but never cleared.
  </li>
  <li>
    <code>LED_HEAPALLOCATE</code> indicates that the NuttX heap has been configured.
    This is an important place in the boot sequence because if the memory is configured wrong, it will probably crash leaving this LED setting.
    This LED value is set but never cleared.
  </li>
  <li>
    <code>LED_IRQSENABLED</code> indicates that interrupts have been enabled.
    Again, during bring-up (or if there are hardware problems), it is very likely that the system may crash just when interrupts are enabled, leaving this setting on the LEDs.
    This LED value is set but never cleared.
  </li>
  <li>
    <code>LED_STACKCREATED</code> is set each time a new stack is created.
    If set, it means that the system attempted to start at least one new thread.
    This LED value is set but never cleared.
  </li>
  <li>
    <code>LED_INIRQ</code> is set and cleared on entry and exit from each interrupt.
    If interrupts are working okay, this LED will have a dull glow.
  </li>
  <li>
    <code>LED_SIGNAL</code> is set and cleared on entry and exit from a signal handler.
    Signal handlers are tricky so this is especially useful during bring-up or a new architecture.
  </li>
  <li>
    <code>LED_ASSERTION</code> is set if an assertion occurs.
  </li>
  <li>
    <code>LED_PANIC</code> will blink at around 1Hz if the system panics and hangs.
  </li>
</ul>

<h3><a name="ledapis">4.3.3 Common LED interfaces</a></h3>

<p>
  The <code><i>&lt;arch-name&gt;</i>/src/common/up_internal.h</code> probably has definitions
  like:
</p>
<ul><pre>
/* Defined in board/up_leds.c */

#ifdef CONFIG_ARCH_LEDS
extern void up_ledinit(void);
extern void up_ledon(int led);
extern void up_ledoff(int led);
#else
# define up_ledinit()
# define up_ledon(led)
# define up_ledoff(led)
#endif
</pre></ul>
<p>
   Where:
<p>
<ul>
  <li>
    <code>void up_ledinit(void)</code> is called early in power-up initialization to initialize the LED hardware.
  </li>
  <li>
    <code>up_ledon(int led)</code> is called to instantiate the LED presentation of the event.
    The <code>led</code> argument is one of the definitions provided in <code><i>&lt;board-name&gt;</i>/include/board.h</code>.
  </li>
  <li>
    <code>up_ledoff(int led</code>is called to terminate the LED presentation of the event.
    The <code>led</code> argument is one of the definitions provided in <code><i>&lt;board-name&gt;</i>/include/board.h</code>.
    Note that only <code>LED_INIRQ</code>, <code>LED_SIGNAL</code>, <code>LED_ASSERTION</code>, and <code>LED_PANIC</code>
    indications are terminated.
  </li>
</ul>

<table width ="100%">
  <tr bgcolor="#e4e4e4">
    <td>
      <h1><a name="NxFileSystem">5.0 NuttX File System</a></h1>
    </td>
  </tr>
</table>
patacongo's avatar
patacongo committed

<p><b>Overview</b>.
  NuttX includes an optional, scalable file system.
patacongo's avatar
patacongo committed
  This file-system may be omitted altogether; NuttX does not depend on the presence
patacongo's avatar
patacongo committed
  of any file system.
</p>

<p><b>Pseudo Root File System</b>.
patacongo's avatar
patacongo committed
  Or, a simple <i>in-memory</i>, <i>pseudo</i> file system can be enabled.
patacongo's avatar
patacongo committed
  This simple file system can be enabled setting the CONFIG_NFILE_DESCRIPTORS
  option to a non-zero value (see <a href="#apndxconfigs">Appendix A</a>).
  This is an <i>in-memory</i> file system because it does not require any
  storage medium or block driver support.
  Rather, file system contents are generated on-the-fly as referenced via
  standard file system operations (open, close, read, write, etc.).
patacongo's avatar
patacongo committed
  In this sense, the file system is <i>pseudo</i> file system (in the
patacongo's avatar
patacongo committed
  same sense that the Linux <code>/proc</code> file system is also
patacongo's avatar
patacongo committed
  referred to as a pseudo file system).
patacongo's avatar
patacongo committed
</p>

<p>
patacongo's avatar
patacongo committed
  Any user supplied data or logic can be accessed via the pseudo-file system.
patacongo's avatar
patacongo committed
  Built in support is provided for character and block <a href="#DeviceDrivers">drivers</a> in the
patacongo's avatar
patacongo committed
  <code>/dev</code> pseudo file system directory.
patacongo's avatar
patacongo committed
</p>

<p><b>Mounted File Systems</b>
  The simple in-memory file system can be extended my mounting block
  devices that provide access to true file systems backed up via some
  mass storage device.
  NuttX supports the standard <code>mount()</code> command that allows
patacongo's avatar
patacongo committed
  a block driver to be bound to a mountpoint within the pseudo file system
patacongo's avatar
patacongo committed
  and to a file system.
patacongo's avatar
patacongo committed
  At present, NuttX supports only the VFAT file system.
</p>

<p><b>Comparison to Linux</b>
  From a programming perspective, the NuttX file system appears very similar
  to a Linux file system.
  However, there is a fundamental difference:
patacongo's avatar
patacongo committed
  The NuttX root file system is a pseudo file system and true file systems may be
  mounted in the pseudo file system.
patacongo's avatar
patacongo committed
  In the typical Linux installation by comparison, the Linux root file system
patacongo's avatar
patacongo committed
  is a true file system and pseudo file systems may be mounted in the true,
patacongo's avatar
patacongo committed
  root file system.
  The approach selected by NuttX is intended to support greater scalability
  from the very tiny platform to the moderate platform.
</p>

<table width ="100%">
  <tr bgcolor="#e4e4e4">
    <td>
      <h1><a name="DeviceDrivers">6.0 NuttX Device Drivers</a></h1>
    </td>
  </tr>
</table>

<p>
  NuttX supports a variety of device drivers including:
  <ul>
    <li><i>Character</i> Device Drivers,</li>
    <li><i>Block</i> Device Drivers, and</li>
    <li>Other <i>Specialized</i> Drivers.</li>
  </ul>
patacongo's avatar
patacongo committed
  These different device driver types are discussed in the following paragraphs.
patacongo's avatar
patacongo committed
  Note: device driver support requires that the <i>in-memory</i>, <i>pseudo</i> file system
patacongo's avatar
patacongo committed
  is enabled by setting the CONFIG_NFILE_DESCRIPTORS in the NuttX configuration file to a 
  non-zero value.
</p>

<h2><a name="chardrivers">6.1 Character Device Drivers</a></h2>

<p>
  Character device drivers have these properties:
</p>
<ul>
  <li>
    <b><code>include/nuttx/fs.h</code></b>.
    All structures and APIs needed to work with character drivers are provided in this header file.
  </li>
  <li>
    <b><code>struct file_operations</code></b>.
    Each character device driver must implement an instance of <code>struct file_operations</code>.
    That structure defines a call table with the following methods:
    <ul>
patacongo's avatar
patacongo committed
     <p><code>int open(FAR struct file *filp);</code><br>
     <code>int close(FAR struct file *filp);</code><br>
     <code>ssize_t read(FAR struct file *filp, FAR char *buffer, size_t buflen);</code><br>
     <code>ssize_t write(FAR struct file *filp, FAR const char *buffer, size_t buflen);</code><br>
     <code>off_t seek(FAR struct file *filp, off_t offset, int whence);</code><br>
     <code>int ioctl(FAR struct file *filp, int cmd, unsigned long arg);</code><br>
     <code>int poll(FAR struct file *filp, struct pollfd *fds, bool setup);</code></p>
    </ul>
  </li>
  <li>
    <b><code>int register_driver(const char *path, const struct file_operations *fops, mode_t mode, void *priv);</code></b>.
    Each character driver registers itself by calling <code>register_driver()</code>, passing it the
    <code>path</code> where it will appear in the <a href="#NxFileSystem">pseudo-file-system</a> and it's
    initialized instance of <code>struct file_operations</code>.
  </li>
  <li>
    <b>User Access</b>.
patacongo's avatar
patacongo committed
    After it has been registered, the character driver can be accessed by user code using the standard
    <a href="NuttxUserGuide.html#driveroperations">driver operations</a> including
    <code>open()</code>, <code>close()</code>, <code>read()</code>, <code>write()</code>, etc.
patacongo's avatar
patacongo committed
    <b>Examples</b>:
    <code>drivers/dev_null.c</code>, <code>drivers/fifo.c</code>, <code>drivers/serial.c</code>, etc.
  </li>
</ul>

<h2><a name="blockdrivers">6.2 Block Device Drivers</a></h2>

<p>
  Block device drivers have these properties:
</p>
<ul>
  <li>
    <b><code>include/nuttx/fs.h</code></b>.
    All structures and APIs needed to work with block drivers are provided in this header file.
  </li>
  <li>
    <b><code>struct block_operations</code></b>.
    Each block device driver must implement an instance of <code>struct block_operations</code>.
    That structure defines a call table with the following methods:
    <ul>
patacongo's avatar
patacongo committed
     <p><code>int open(FAR struct inode *inode);</code><br>
     <code>int close(FAR struct inode *inode);</code><br>
     <code>ssize_t read(FAR struct inode *inode, FAR unsigned char *buffer, size_t start_sector, unsigned int nsectors);</code><br>
     <code>ssize_t write(FAR struct inode *inode, FAR const unsigned char *buffer, size_t start_sector, unsigned int nsectors);</code><br>
     <code>int geometry(FAR struct inode *inode, FAR struct geometry *geometry);</code><br>
     <code>int ioctl(FAR struct inode *inode, int cmd, unsigned long arg);</code></p>
    </ul>
  </li>
  <li>
    <b><code>int register_blockdriver(const char *path, const struct block_operations *bops, mode_t mode, void *priv);</code></b>.
    Each block driver registers itself by calling <code>register_blockdriver()</code>, passing it the
    <code>path</code> where it will appear in the <a href="#NxFileSystem">pseudo-file-system</a> and it's
    initialized instance of <code>struct block_operations</code>.
  </li>
  <li>
    <b>User Access</b>.
    Users do not normally access block drivers directly, rather, they access block drivers
    indirectly through the <code>mount()</code> API.
    The <code>mount()</code> API binds a block driver instance with a file system and with a mountpoint.
    Then the user may use the block driver to access the file system on the underlying media.
patacongo's avatar
patacongo committed
    <i>Example</i>: See the <code>cmd_mount()</code> implementation in <code>examples/nsh/nsh_fscmds.c</code>.
  </li>
  <li>
    <b>Accessing a Character Driver as a Block Device</b>.
    See the loop device at <code>drivers/loop.c</code>.
patacongo's avatar
patacongo committed
    <i>Example</i>: See the <code>cmd_losetup()</code> implementation in <code>examples/nsh/nsh_fscmds.c</code>.
  </li>
  <li>
    <b>Accessing a Block Driver as Character Device</b>.
    See the Block-to-Character (BCH) conversion logic in <code>drivers/bch/</code>.
patacongo's avatar
patacongo committed
    <i>Example</i>: See the <code>cmd_dd()</code> implementation in <code>examples/nsh/nsh_ddcmd.c</code>.
  </li>
  <li>
    <b>Examples</b>.
patacongo's avatar
patacongo committed
    <code>drivers/loop.c</code>, <code>drivers/mmcsd/mmcsd_spi.c</code>, <code>drivers/ramdisk.c</code>, etc.
  </li>
</ul>

<h2><a name="blockdrivers">6.3 Specialized Device Drivers</a></h2>

<h3><a name="ethdrivers">6.3.1 Ethernet Device Drivers</a></h3>

<ul>
  <li>
    <b><code>include/net/uip/uip-arch.h</code></b>.
    All structures and APIs needed to work with Ethernet drivers are provided in this header file.
    The structure <code>struct uip_driver_s</code> defines the interface and is passed to uIP via
    <code>netdev_register()</code>.
  </li>
  <li>
    <b><code>int netdev_register(FAR struct uip_driver_s *dev);</code></b>.
patacongo's avatar
patacongo committed
    Each Ethernet driver registers itself by calling <code>netdev_register()</code>.
patacongo's avatar
patacongo committed
    <b>Examples</b>:
    <code>drivers/net/dm90x0.c</code>, <code>arch/drivers/arm/src/c5471/c5471_ethernet.c</code>, <code>arch/z80/src/ez80/ez80_emac.c</code>, etc.
  </li>
</ul>

<h3><a name="spidrivers">6.3.2 SPI Device Drivers</a></h3>

<ul>
  <li>
    <b><code>include/nuttx/spi.h</code></b>.
    All structures and APIs needed to work with SPI drivers are provided in this header file.
  </li>
  <li>
    <b><code>struct spi_ops_s</code></b>.
    Each SPI device driver must implement an instance of <code>struct spi_ops_s</code>.
    That structure defines a call table with the following methods:
    <ul>
     <p><code>void lock(FAR struct spi_dev_s *dev);</code></p>
     <p><code>void select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool selected);</code><br>
     <code>uint32_t setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency);</code><br>
patacongo's avatar
patacongo committed
     <code>void setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode);</code><br>
     <code>void setbits(FAR struct spi_dev_s *dev, int nbits);</code><br>
     <code>uint8_t status(FAR struct spi_dev_s *dev, enum spi_dev_e devid);</code><br>
     <code>uint16_t send(FAR struct spi_dev_s *dev, uint16_t wd);</code><br>
patacongo's avatar
patacongo committed
     <code>void exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer, FAR void *rxbuffer, size_t nwords);</code><br>
patacongo's avatar
patacongo committed
     <p><code>int registercallback(FAR struct spi_dev_s *dev, mediachange_t callback, void *arg);</code></p>
  </ul>
  <li>
    <b>Binding SPI Drivers</b>.
    SPI drivers are not normally directly accessed by user code, but are usually bound to another,
    higher level device driver.
    See for example, <code>int mmcsd_spislotinitialize(int minor, int slotno, FAR struct spi_dev_s *spi)</code> in <code>drivers/mmcsd/mmcsd_spi.c</code>.
patacongo's avatar
patacongo committed
    In general, the binding sequence is:
    <ul>
      <li>Get an instance of <code>struct spi_dev_s</code> from the hardware-specific SPI device driver, and </li>
      <li>Provide that instance to the initialization method of the higher level device driver.</li>
    </ul>
patacongo's avatar
patacongo committed
    <b>Examples</b>:
patacongo's avatar
patacongo committed
    <code>drivers/loop.c</code>, <code>drivers/mmcsd/mmcsd_spi.c</code>, <code>drivers/ramdisk.c</code>, etc.
  </li>
</ul>

<h3><a name="i2cdrivers">6.3.3 I2C Device Drivers</a></h3>

<ul>
  <li>
    <b><code>include/nuttx/i2c.h</code></b>.
    All structures and APIs needed to work with I2C drivers are provided in this header file.
  </li>
  <li>
    <b><code>struct i2c_ops_s</code></b>.
    Each I2C device driver must implement an instance of <code>struct i2c_ops_s</code>.
    That structure defines a call table with the following methods:
    <ul>
     <p><code>uint32_t setfrequency(FAR struct i2c_dev_s *dev, uint32_t frequency);</code><br>
patacongo's avatar
patacongo committed
     <code>int setaddress(FAR struct i2c_dev_s *dev, int addr, int nbits);</code><br>
     <code>int write(FAR struct i2c_dev_s *dev, const uint8_t *buffer, int buflen);</code><br>
     <code>int read(FAR struct i2c_dev_s *dev, uint8_t *buffer, int buflen);</code></p>
  </ul>
  <li>
    <b>Binding I2C Drivers</b>.
patacongo's avatar
patacongo committed
    I2C drivers are not normally directly accessed by user code, but are usually bound to another,
    higher level device driver.
patacongo's avatar
patacongo committed
    In general, the binding sequence is:
    <ul>
      <li>Get an instance of <code>struct i2c_dev_s</code> from the hardware-specific I2C device driver, and </li>
      <li>Provide that instance to the initialization method of the higher level device driver.</li>
    </ul>
patacongo's avatar
patacongo committed
    <b>Examples</b>:
    <code>arch/z80/src/ez80/ez80_i2c.c</code>, <code>arch/z80/src/z8/z8_i2c.c</code>, etc.
  </li>
</ul>

<h3><a name="serialdrivers">6.3.4 Serial Device Drivers</a></h3>

<ul>
  <li>
    <b><code>include/nuttx/serial.h</code></b>.
    All structures and APIs needed to work with serial drivers are provided in this header file.
  </li>
  <li>
    <b><code>struct uart_ops_s</code></b>.
    Each serial device driver must implement an instance of <code>struct uart_ops_s</code>.
    That structure defines a call table with the following methods:
    <ul>
patacongo's avatar
patacongo committed
     <p><code>int setup(FAR struct uart_dev_s *dev);</code><br>
     <code>void shutdown(FAR struct uart_dev_s *dev);</code><br>
     <code>int attach(FAR struct uart_dev_s *dev);</code><br>
     <code>void detach(FAR struct uart_dev_s *dev);</code><br>
     <code>int ioctl(FAR struct file *filep, int cmd, unsigned long arg);</code><br>
     <code>int receive(FAR struct uart_dev_s *dev, unsigned int *status);</code><br>
     <code>void rxint(FAR struct uart_dev_s *dev, bool enable);</code><br>
     <code>bool rxavailable(FAR struct uart_dev_s *dev);</code><br>
patacongo's avatar
patacongo committed
     <code>void send(FAR struct uart_dev_s *dev, int ch);</code><br>
     <code>void txint(FAR struct uart_dev_s *dev, bool enable);</code><br>
     <code>bool txready(FAR struct uart_dev_s *dev);</code><br>
     <code>bool txempty(FAR struct uart_dev_s *dev);</code></p>
    </ul>
  </li>
  <li>
    <b><code>int uart_register(FAR const char *path, FAR uart_dev_t *dev);</code></b>.
    A serial driver may register itself by calling <code>uart_register()</code>, passing it the
    <code>path</code> where it will appear in the <a href="#NxFileSystem">pseudo-file-system</a> and it's
    initialized instance of <code>struct uart_ops_s</code>.
patacongo's avatar
patacongo committed
    By convention, serial device drivers are registered at paths like <code>/dev/ttyS0</code>, <code>/dev/ttyS1</code>, etc.
    See the <code>uart_register()</code> implementation in <code>drivers/serial.c</code>.
  </li>
  <li>
    <b>User Access</b>.
    Serial drivers are, ultimately, normal <a href="#chardrivers">character drivers</a> and are accessed as other character drivers.
  </li>
  <li>
patacongo's avatar
patacongo committed
    <b>Examples</b>:
    <code>arch/arm/src/chip/lm3s_serial.c</code>, <code>arch/arm/src/lpc214x/lpc214x_serial.c</code>, <code>arch/z16/src/z16f/z16f_serial.c</code>, etc.
  </li>
</ul>

patacongo's avatar
patacongo committed
<h3><a name="fbdrivers">6.3.5 Frame Buffer Drivers</a></h3>

<ul>
  <li>
    <b><code>include/nuttx/fb.h</code></b>.
    All structures and APIs needed to work with serial drivers are provided in this header file.
  </li>
  <li>
    <b><code>struct fb_vtable_s</code></b>.
    Each frame buffer device driver must implement an instance of <code>struct fb_vtable_s</code>.
    That structure defines a call table with the following methods:
    <p>
      Get information about the video controller configuration and the configuration of each color plane.
    </p>
    <ul>
     <p><code>int (*getvideoinfo)(FAR struct fb_vtable_s *vtable, FAR struct fb_videoinfo_s *vinfo);</code><br>
     <code>int (*getplaneinfo)(FAR struct fb_vtable_s *vtable, int planeno, FAR struct fb_planeinfo_s *pinfo);</code></p>
    </ul>
    <p>
      The following are provided only if the video hardware supports RGB color mapping:
    </p?
    <ul>
     <p><code>int (*getcmap)(FAR struct fb_vtable_s *vtable, FAR struct fb_cmap_s *cmap);</code><br>
     <code>int (*putcmap)(FAR struct fb_vtable_s *vtable, FAR const struct fb_cmap_s *cmap);</code></p>
    </ul>
    <p>
      The following are provided only if the video hardware supports a hardware cursor:
    </p>
    <ul>
     <p><code>int (*getcursor)(FAR struct fb_vtable_s *vtable, FAR struct fb_cursorattrib_s *attrib);</code><br>
     <code>int (*setcursor)(FAR struct fb_vtable_s *vtable, FAR struct fb_setcursor_s *settings);</code></p>
    </ul>
  </li>
  <li>
    <b>Binding Frame Buffer Drivers</b>.
    Frame buffer drivers are not normally directly accessed by user code, but are usually bound to another,
    higher level device driver.
    In general, the binding sequence is:
    <ul>
      <li>Get an instance of <code>struct fb_vtable_s</code> from the hardware-specific frame buffer device driver, and </li>
      <li>Provide that instance to the initialization method of the higher level device driver.</li>
    </ul>
  </li>
  <li>
    <b>Examples</b>:
    <code>arch/sim/src/up_framebuffer.c</code>.
    See also the usage of the frame buffer driver in the <code>graphics/</code> directory.
  </li>
</ul>

<h3><a name="mtddrivers">6.3.6 Memory Technology Device Drivers</a></h3>

<ul>
  <li>
    <b><code>include/nuttx/mtd.h</code></b>.
    All structures and APIs needed to work with serial drivers are provided in this header file.
  </li>
  <li>
    <b><code>struct mtd_dev_s</code></b>.
    Each MTD device driver must implement an instance of <code>struct mtd_dev_s</code>.
    That structure defines a call table with the following methods:
    <p>
      Erase the specified erase blocks (units are erase blocks):
    </p>
    <ul>
     <p><code>int (*erase)(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks);</code></p>
    </ul>
    <p>
      Read/write from the specified read/write blocks:
    </p?