move last content from old docs to new docs; remove old docs

This commit is contained in:
Matias N 2020-08-14 16:50:02 -03:00 committed by Brennan Ashton
parent 71021575fc
commit 6d89ae8fc7
17 changed files with 0 additions and 39299 deletions

View File

@ -1,3 +0,0 @@
/TODO.txt
/ChangeLog.txt
/NuttXConfigVariables.*

File diff suppressed because it is too large Load Diff

View File

@ -1,385 +0,0 @@
<html>
<head>
<title>NFS Client How-To</title>
</head>
<body background="backgd.gif">
<hr><hr>
<table width ="100%">
<tr align="center" bgcolor="#e4e4e4">
<td>
<h1><big><font color="#3c34ec"><i>NFS Client How-To</i></font></big></h1>
<p>Last Updated: June 18, 2012</p>
</td>
</tr>
</table>
<hr><hr>
<table width ="100%">
<tr bgcolor="#e4e4e4">
<td>
<h1>Table of Contents</h1>
</td>
</tr>
</table>
<center><table width ="80%">
<tr>
<td>
<table>
<tr>
<td valign="top" width="22"><img height="20" width="20" src="favicon.ico"></td>
<td>
<a href="#nfsconfiguration">Adding NFS to the NuttX Configuration</a>
</td>
</tr>
</table>
<table>
<tr>
<td valign="top" width="22"><img height="20" width="20" src="favicon.ico"></td>
<td>
<a href="#mountinterface">Mount Interface</a>
</td>
</tr>
</table>
<table>
<tr>
<td valign="top" width="22"><img height="20" width="20" src="favicon.ico"></td>
<td>
<a href="#nfsmount">NFS Mount Command</a>
</td>
</tr>
</table>
<table>
<tr>
<td valign="top" width="22"><img height="20" width="20" src="favicon.ico"></td>
<td>
<a href="#serverconfig">Configuring the NFS server (Ubuntu)</a>
</td>
</tr>
</table>
</td>
</tr>
</table></center>
<table width ="100%">
<tr bgcolor="#e4e4e4">
<td>
<a name="nfsconfiguration"><h1>Adding NFS to the NuttX Configuration</h1></a>
</td>
</tr>
</table>
<p>
The NFS client is easily added to your configuration:
You simply need to add <code>CONFIG_NFS</code> to your <code>nuttx/.config</code> file.
There are, however, a few dependencies on other system settings:
</p>
<ol>
<li>
First, there are things that you must configure in order to be able to use any file system:
</li>
<ul>
<li>
<code>CONFIG_DISABLE_MOUNTPOINT=n</code>. You must include support for mount points in the pseudo-file system.
</li>
</ul>
<li>
And there are several dependencies on the networking configuration.
At a minimum, you need to have the following selections:
</li>
<ul>
<li>
<code>CONFIG_NET=y</code>. General networking support.
</li>
<li>
<code>CONFIG_NET_UDP=y</code>. Support for UDP.
</li>
</ul>
</ol>
<table width ="100%">
<tr bgcolor="#e4e4e4">
<td>
<a name="mountinterface"><h1>Mount Interface</h1></a>
</td>
</tr>
</table>
<p>
A low-level, C-callable interface is provided to mount a file system.
That interface is called <code>mount()</code> and is mentioned in the <a href="NuttxPortingGuide.html#NxFileSystem"><code>porting guide</code></a> and is prototyped in the header file <code>include/sys/mount.h</code>:
</p>
<ul><pre>
int mount(const char *source, const char *target, const char *filesystemtype, unsigned long mountflags, const void *data);
</pre></ul>
<p>
<b>Synopsis</b>:
<code>mount()</code> attaches the filesystem specified by the <code>source</code> block device name into the root file system at the path specified by <code>target</code>.
</p>
<p>
<b>Input Parameters</b>:
<ul>
<li><code>source</code>. A null-terminated string providing the fill path to a block driver in the NuttX pseudo-file system.
<li><code>target</code>. The location in the NuttX pseudo-file system where the volume will be mounted.
<li><code>filesystemtype</code>. A string identifying the type of file system to use.
<li><code>mountflags</code>. Various flags that can be used to qualify how the file system is mounted.
<li><code>data</code>. Opaque data that is passed to the file system with the mount occurs.
</ul>
</p>
<p>
<b>Returned Values</b>
Zero is returned on success; -1 is returned on an error and <code>errno</code> is set appropriately:
<ul>
<li><code>EACCES</code>.
A component of a path was not searchable or mounting a read-only filesystem was attempted without giving the <code>MS_RDONLY</code> flag.
</li>
<li><code>EBUSY</code>.
<code>source</code> is already mounted.
</li>
<li><code>EFAULT</code>.
One of the pointer arguments points outside the user address space.
</li>
<li><code>EINVAL</code>.
<code>source</code> had an invalid superblock.
</li>
<li><code>ENODEV</code>.
<code>filesystemtype</code> not configured
</li>
<li><code>ENOENT</code>.
A pathname was empty or had a nonexistent component.
</li>
<li><code>ENOMEM</code>.
Could not allocate a memory to copy filenames or data into.
</li>
<li><code>ENOTBLK</code>.
<code>source</code> is not a block device
</li>
</ul>
</p>
<p>
This same interface can be used to mount a remote, NFS file system using some special parameters.
The NFS mount differs from the <i>normal</i> file system mount in that: (1) there is no block driver for the NFS file system, and (2) special parameters must be passed as <code>data</code> to describe the remote NFS server.
Thus the following code snippet might represent how an NFS file system is mounted:
</p>
<ul><pre>
#include &lt;sys/mount.h&gt;
#include &lt;nuttx/fs/nfs.h&gt;
struct nfs_args data;
char *mountpoint;
ret = mount(NULL, mountpoint, string &quot;nfs&quot;, 0, (FAR void *)&data);
</pre></ul>
<p>
NOTE that: (1) the block driver parameter is <code>NULL</code>.
The <code>mount()</code> is smart enough to know that no block driver is needed with the NFS file system.
(2) The NFS file system is identified with the simple string &quot;nfs&quot;
(3) A reference to <code>struct nfs_args</code> is passed as an NFS-specific argument.
</p>
<p>
The NFS-specific interface is described in the file <code>include/nuttx/fs/nfs.h</code>.
There you can see that <code>struct nfs_args</code> is defined as:
</p>
<ul><pre>
struct nfs_args
{
uint8_t addrlen; /* Length of address */
uint8_t sotype; /* Socket type */
uint8_t flags; /* Flags, determines if following are valid: */
uint8_t timeo; /* Time value in deciseconds (with NFSMNT_TIMEO) */
uint8_t retrans; /* Times to retry send (with NFSMNT_RETRANS) */
uint16_t wsize; /* Write size in bytes (with NFSMNT_WSIZE) */
uint16_t rsize; /* Read size in bytes (with NFSMNT_RSIZE) */
uint16_t readdirsize; /* readdir size in bytes (with NFSMNT_READDIRSIZE) */
char *path; /* Server's path of the directory being mount */
struct sockaddr_storage addr; /* File server address (requires 32-bit alignment) */
};
</pre></ul>
<table width ="100%">
<tr bgcolor="#e4e4e4">
<td>
<a name="nfsmount"><h1>NFS Mount Command</h1></a>
</td>
</tr>
</table>
<p>
The <a href="NuttShell.html">NuttShell (NSH)</a> also supports a command called <code>nfsmount</code>
that can be used to mount a remote file system via the NSH command line.
</p>
<p>
<b>Command Syntax:</b>
</p>
<ul><pre>
nfsmount &lt;server-address&gt; &lt;mount-point&gt; &lt;remote-path&gt;
</pre></ul>
<p>
<b>Synopsis</b>.
The <code>nfsmount</code> command mounts a network file system in the NuttX pseudo filesystem.
The <code>nfsmount</code> will use NFSv3 UDP protocol to mount the remote file system.
</p>
<p>
<b>Command Line Arguments</b>.
The <code>nfsmount</code> takes three arguments:
</p>
<ol>
<li>
The <code>&lt;server-address&gt;</code> is the IP address of the server exporting the file system you wish to mount.
This implementation of NFS for the NuttX RTOS is only for a local area network, so the server and client must be in the same network.
</li>
<li>
The <code>&lt;mount-point &gt;</code> is the location in the NuttX pseudo filesystem where the mounted volume will appear.
This mount point can only reside in the NuttX pseudo filesystem.
By convention, this mount point is a subdirectory under <code>/mnt</code>.
The mount command will create whatever pseudo directories that may be needed to complete the full path (but the full path must not already exist).
</li>
<li>
The <code>&lt;remote-path&gt;</code> is the file system <code>/</code> directory being exported from server.
This <code>/</code> directory must have been configured for exportation on the server before when the NFS server was set up.
</li>
</ol>
<p>
After the volume has been mounted in the NuttX pseudo filesystem, it may be access in the same way as other objects in the file system.
</p>
<p>
<b>Example</b>.
Suppose that the NFS server has been configured to export the directory <code>/export/shared</code>.
The the following command would mount that file system (assuming that the target also has privileges to mount the file system).
</p>
<ul><pre>
NuttShell (NSH)
nsh&gt; ls /mnt
/mnt:
nsh: ls: no such directory: /mnt
nsh&gt; nfsmount 10.0.0.1 /mnt/nfs /export/shared
nsh&gt; ls -l /mnt/nfs
/mnt/nfs:
drwxrwxrwx 4096 ..
drwxrwxrwx 4096 testdir/
-rw-rw-rw- 6 ctest.txt
-rw-r--r-- 15 btest.txt
drwxrwxrwx 4096 .
nsh&gt; echo &quot;This is a test&quot; &gt;/mnt/nfs/testdir/testfile.txt
nsh&gt; ls -l /mnt/nfs/testdir
/mnt/nfs/testdir:
-rw-rw-rw- 21 another.txt
drwxrwxrwx 4096 ..
drwxrwxrwx 4096 .
-rw-rw-rw- 16 testfile.txt
nsh&gt; cat /mnt/nfs/testdir/testfile.txt
This is a test
</pre></ul>
<table width ="100%">
<tr bgcolor="#e4e4e4">
<td>
<a name="serverconfig"><h1>Configuring the NFS server (Ubuntu)</h1></a>
</td>
</tr>
</table>
<p>
Setting up the server will be done in two steps:
First, setting up the configuration file for NFS, and then starting the NFS services.
But first, you need to install the nfs server on Ubuntu with these two commands:
</p>
<ul><pre>
# sudo apt-get install nfs-common</FONT>
# sudo apt-get install nfs-kernel-server</FONT>
</pre></ul>
<p>
After that, we need to make or choose the directory we want to export from the NFS server.
In our case, we are going to make a new directory called <code>/export</code>.
</p>
<ul><pre>
# sudo mkdir /export
</pre></ul>
<p>
It is important that <code>/export</code> directory allow access to everyone (777 permissions) as we will be accessing the NFS share from the client with no authentication.
</p>
<ul><pre>
# sudo chmod 777 /export
</pre></ul>
<p>
When all this is done, we will need to edit the configuration file to set up an NFS server: <code>/etc/exports</code>.
This file contains a list of entries;
each entry indicates a volume that is shared and how it is shared.
For more information for a complete description of all the setup options for this file you can check in the man pages (<code>man export</code>).</p>
An entry in <code>/etc/exports</code> will typically look like this:
</p>
<ul><pre>
directory machine1(option11,option12)
</pre></ul>
<p>
So for our example we export <code>/export</code> to the client 10.0.0.2 add the entry:
</p>
<ul><pre>
/export 10.0.0.2(rw)
</pre></ul>
<p>
In our case we are using all the default options except for the <code>ro</code> that we replaced with <code>rw</code> so that our client will have read and write access to the directory that we are exporting.
</p>
</p>
After we do all the require configurations, we are ready to start the server with the next command:
</p>
<ul><pre>
# sudo /etc/init.d/nfs-kernel-server start
</pre></ul>
</p>
Note: If you later decide to add more NFS exports to the /etc/exports file, you will need to either restart NFS daemon
or run command exportfs.
</p>
<ul><pre>
# sudo /etc/init.d/nfs-kernel-server start
</pre></ul>
<p>Or</p>
<ul><pre>
# exportfs -ra
</pre></ul>
<p>
Now we can check if the export directory and our mount point is properly set up.
</p>
<ul><pre>
# sudo showmount -e
# sudo showmount -a
</pre></ul>
<p>
And also we can verify if NFS is running in the system with:
</p>
<P STYLE="margin-left: 0.49in; margin-bottom: 0in; line-height: 100%">
<ul><pre>
# rpcinfo &ndash;p</FONT>
program vers proto port
100000 2 tcp 111 portmapper
100000 2 udp 111 portmapper
100011 1 udp 749 rquotad
100011 2 udp 749 rquotad
100005 1 udp 759 mountd
100005 1 tcp 761 mountd
100005 2 udp 764 mountd
100005 2 tcp 766 mountd
100005 3 udp 769 mountd
100005 3 tcp 771 mountd
100003 2 udp 2049 nfs
100003 3 udp 2049 nfs
300019 1 tcp 830 amd
300019 1 udp 831 amd
100024 1 udp 944 status
100024 1 tcp 946 status
100021 1 udp 1042 nlockmgr
100021 3 udp 1042 nlockmgr
100021 4 udp 1042 nlockmgr
100021 1 tcp 1629 nlockmgr
100021 3 tcp 1629 nlockmgr
100021 4 tcp 1629 nlockmgr
</pre></ul>
<p>
Now your NFS sever is sharing <code>/export</code> directory to be accessed.
</p>
</body>
</html>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,585 +0,0 @@
<html>
<head>
<title>NuttX Binary Loader</title>
<link rel="stylesheet" href="style.css">
</head>
<body background="backgd.gif">
<hr><hr>
<table width ="100%">
<tr align="center" bgcolor="#e4e4e4">
<td>
<h1><big><font color="#3c34ec"><i>NuttX Binary Loader</i></font></big></h1>
<p>Last Updated: January 26, 2019</p>
</td>
</tr>
</table>
<hr><hr>
<table width ="100%">
<tr bgcolor="#e4e4e4">
<td>
<h1>Table of Contents</h1>
</td>
</tr>
</table>
<ul>
<a href="#introduction">1.0 Introduction</a><br>
<a href="#binfmtif">2.0 Binary Loader Interface</a>
<ul>
<a href="#binfmthdr">2.1 Binary Loader Header Files</a><br>
<a href="#binfmtdata">2.2 Binary Loader Data Structures</a><br>
<a href="#binfmtfuncif">2.3 Binary Loader Function Interfaces</a>
</ul>
<a href="#symtab">3.0 Symbol Tables</a>
<ul>
<a href="#symtabhdr">3.1 Symbol Table Header Files</a><br>
<a href="#symtabdata">3.2 Symbol Table Data Structures</a><br>
<a href="#symtabfuncif">3.3 Symbol Table Function Interfaces</a>
</ul>
<a href="#configuration">4.0 Configuration Variables</a>
</ul>
<table width ="100%">
<tr bgcolor="#e4e4e4">
<td>
<h1>1.0 <a name="introduction">Introduction</a></h1>
</td>
</tr>
</table>
<p>
<b>Binary Loaders</b>.
The purpose of a <i>binary loader</i> is to load and execute modules in various <i>binary formats</i> that reside in a file system.
Loading refers instantiating the binary module in some fashion, usually copy all or some of the binary module into memory and then linking the module with other components.
In most architectures, it is the base FLASH code that is the primary component that the binary module must link with because that is where the RTOS and primary tasks reside.
Program modules can then be executed after they have been loaded.
</p>
<p>
<b>Binary Formats</b>.
The binary loader provides generic support for different binary formats.
It supports a <i>registration interface</i> that allows the number of support binary formats to be loaded at run time.
Each binary format provides a common, interface for use by the binary loader.
When asked to load a binary, the binary loader will query each registered binary format, providing it with the path of the binary object to be loaded.
The binary loader will stop when first binary format the recognizes the binary object and successfully loads it or when all registered binary formats have attempt loading the binary object and failed.
</p>
<p>
At present, the following binary formats are support by NuttX:
</p>
<ul>
<li>
<b>ELF</b>.
Standard ELF formatted files.
</li>
<li>
<b>NXFLAT</b>.
NuttX NXFLAT formatted files.
More information about the NXFLAT binary format can be found in the
<a href="NuttXNxFlat.html">NXFLAT documentation</a>.
</ul>
<p>
<b>Executables and Libraries</b>
The generic binary loader logic does not care what it is that it being loaded. It could load an executable program or a library.
There are no strict rules, but a library will tend to export symbols and a program will tend to import symbols: The program will use the symbols exported by the library.
However, at this point in time, none of the supported binary formats support exporting of symbols.
</p>
<p>
<b>binfmt</b>.
In the NuttX source code, the short name <code>binfmt</code> is used to refer to the NuttX binary loader.
This is the name of the directory containing the binary loader and the name of the header files and variables used by the binary loader.
</p>
<p>
The name <code>binfmt</code> is the same name used by the Linux binary loader.
However, the NuttX binary loader is an independent development and shares nothing with the Linux binary loader other the same name and the same basic functionality.
</p>
<table width ="100%">
<tr bgcolor="#e4e4e4">
<td>
<h1>2.0 <a name="binfmtif">Binary Loader Interface</a></h1>
</td>
</tr>
</table>
<h2>2.1 <a name="binfmthdr">Binary Loader Header Files</a></h2>
<p>
The interface to the binary loader is described in the header file
<a href="https://bitbucket.org/nuttx/nuttx/src/master/include/nuttx/binfmt/binfmt.h" target="_blank">
<code>include/nuttx/binfmt/binfmt.h</code></a>.
A brief summary of the data structurs and interfaces prototyped in that header file are listed below.
</p>
<h2>2.2 <a name="binfmtdata">Binary Loader Data Structures</a></h2>
<p>
When a binary format registers with the binary loader, it provides a pointer to a write-able instance of the following data structure:
</p>
<ul><pre>
struct binfmt_s
{
FAR struct binfmt_s *next; /* Supports a singly-linked list */
int (*load)(FAR struct binary_s *bin); /* Verify and load binary into memory */
};
</pre></ul>
<p>
The <code>load</code> method is used to load the binary format into memory.
It returns either <code>OK</code> (0) meaning that the binary object was loaded successfully, or a negated <code>errno</code> indicating why the object was not loaded.
</p>
<p>
The type <code>struct binary_s</code> is use both to (2) describe the binary object to be loaded, and if successfully loaded, (2) to provide information about where and how the binary object was loaded.
That structure is shown below:
</p>
<ul><pre>
struct symtab_s;
struct binary_s
{
/* Information provided to the loader to load and bind a module */
FAR const char *filename; /* Full path to the binary to be loaded */
FAR const char **argv; /* Argument list */
FAR const struct symtab_s *exports; /* Table of exported symbols */
int nexports; /* The number of symbols in exports[] */
/* Information provided from the loader (if successful) describing the
* resources used by the loaded module.
*/
main_t entrypt; /* Entry point into a program module */
FAR void *mapped; /* Memory-mapped, address space */
FAR void *alloc[BINFMT_NALLOC]; /* Allocated address spaces */
/* Constructors/destructors */
#ifdef CONFIG_BINFMT_CONSTRUCTORS
FAR binfmt_ctor_t *ctors; /* Pointer to a list of constructors */
FAR binfmt_dtor_t *dtors; /* Pointer to a list of destructors */
uint16_t nctors; /* Number of constructors in the list */
uint16_t ndtors; /* Number of destructors in the list */
#endif
/* Address environment.
*
* addrenv - This is the handle created by up_addrenv_create() that can be
* used to manage the tasks address space.
*/
#ifdef CONFIG_ARCH_ADDRENV
group_addrenv_t addrenv; /* Task group address environment */
#endif
size_t mapsize; /* Size of the mapped address region (needed for munmap) */
/* Start-up information that is provided by the loader, but may be modified
* by the caller between load_module() and exec_module() calls.
*/
uint8_t priority; /* Task execution priority */
size_t stacksize; /* Size of the stack in bytes (unallocated) */
};
</pre></ul>
<ul>
<p><small>
<sup>1</sup>The <code>filename</code> must be the full, absolute path to the file to be executed unless <code>CONFIG_LIB_ENVPATH</code> is defined.
In that case, <code>filename</code> may be a relative path;
a set of candidate absolute paths will be generated using the <code>PATH</code> environment variable and <a href="#load_module"><code>load_module()</code></a> will attempt to load each file that is found at those absolute paths.
</small></p>
</ul>
<p>
Where the types <code>binfmt_ctor_t</code> and <code>binfmt_dtor_t</code> define the type of one C++ constructor or destructor:
</p>
<ul><pre>
typedef FAR void (*binfmt_ctor_t)(void);
typedef FAR void (*binfmt_dtor_t)(void);
</pre></ul>
<h2>2.3 <a name="binfmtfuncif">Binary Loader Function Interfaces</a></h2>
<h3>
Binary format management:
</h3>
<ul>
<a href="#register_binfmt">2.3.1 <code>register_binfmt()</code></a><br>
<a href="#unregister_binfmt">2.3.2 <code>unregister_binfmt()</code></a>
</ul>
<h3>
Basic module management:
</h3>
<ul>
<a href="#load_module">2.3.3 <code>load_module()</code></a><br>
<a href="#unload_module">2.3.4 <code>unload_module()</code></a><br>
<a href="#exec_module">2.3.5 <code>exec_module()</code></a><br>
<a href="#exec">2.3.6 <code>exec()</code></a><br>
<a href="#exec">2.3.7 <code>exec()</code></a>
</ul>
<h3>
<code>PATH</code> traversal logic:
</h3>
<ul>
<a href="#envpath_init">2.3.8 <code>envpath_init()</code></a><br>
<a href="#envpath_next">2.3.9 <code>envpath_next()</code></a><br>
<a href="#envpath_release">2.3.10 <code>envpath_release()</code></a>
</ul>
<h3>2.3.1 <a name="register_binfmt"><code>register_binfmt()</code></a></h3>
<p><b>Function Prototype:</b></p>
<ul><pre>
#include &lt:nuttx/binfmt/binfmt.h&gt;
int register_binfmt(FAR struct binfmt_s *binfmt);
</pre></ul>
<p><b>Description:</b></p>
<ul>
Register a loader for a binary format.
</ul>
<p><b>Returned Value:</b></p>
<ul>
This is a NuttX internal function so it follows the convention that 0 (<code>OK</code>) is returned on success and a negated <code>errno</code> is returned on failure.
</ul>
<h3>2.3.2 <a name="unregister_binfmt"><code>unregister_binfmt()</code></a></h3>
<p><b>Function Prototype:</b></p>
<ul><pre>
#include &lt:nuttx/binfmt/binfmt.h&gt;
int unregister_binfmt(FAR struct binfmt_s *binfmt);
</pre></ul>
<p><b>Description:</b></p>
<ul>
Register a loader for a binary format.
</ul>
<p><b>Returned Value:</b></p>
<ul>
This is a NuttX internal function so it follows the convention that 0 (<code>OK</code>) is returned on success and a negated <code>errno</code> is returned on failure.
</ul>
<h3>2.3.3 <a name="load_module"><code>load_module()</code></a></h3>
<p><b>Function Prototype:</b></p>
<ul><pre>
#include &lt:nuttx/binfmt/binfmt.h&gt;
int load_module(FAR struct binary_s *bin);
</pre></ul>
<p><b>Description:</b></p>
<ul>
<p>
Load a module into memory, bind it to an exported symbol take, and prep the module for execution.
</p>
<p>
<code>load_module()</code> will use the <code>filename</code> field in the <a href="#binfmtdata"><code>struct binary_s</code></a> in order to locate the module to be loaded from the file system.
The <code>filename</code> must be the full, absolute path to the file to be executed unless <code>CONFIG_LIB_ENVPATH</code> is defined.
In that case, <code>filename</code> may be a relative path;
a set of candidate absolute paths will be generated using the <code>PATH</code> environment variable and <code>load_module()</code> will attempt to load each file that is found at those absolute paths.
</p>
</ul>
<p><b>Returned Value:</b></p>
<ul>
This is a NuttX internal function so it follows the convention that 0 (<code>OK</code>) is returned on success and a negated <code>errno</code> is returned on failure.
</ul>
<h3>2.3.4 <a name="unload_module"><code>unload_module()</code></a></h3>
<p><b>Function Prototype:</b></p>
<ul><pre>
#include &lt:nuttx/binfmt/binfmt.h&gt;
int unload_module(FAR struct binary_s *bin);
</pre></ul>
<p><b>Description:</b></p>
<ul>
<p>
Unload a (non-executing) module from memory.
If the module has been started (via <code>exec_module()</code>) and has not exited, calling this will be fatal.
</p>
<p>
However, this function must be called after the module exist.
How this is done is up to your logic.
Perhaps you register it to be called by <code>on_exit()</code>?
</ul>
<p><b>Returned Value:</b></p>
<ul>
This is a NuttX internal function so it follows the convention that 0 (<code>OK</code>) is returned on success and a negated <code>errno</code> is returned on failure.
</ul>
<h3>2.3.5 <a name="exec_module"><code>exec_module()</code></a></h3>
<p><b>Function Prototype:</b></p>
<ul><pre>
#include &lt:nuttx/binfmt/binfmt.h&gt;
int exec_module(FAR const struct binary_s *bin);
</pre></ul>
<p><b>Description:</b></p>
<ul>
Execute a module that has been loaded into memory by <code>load_module()</code>.
</ul>
<p><b>Returned Value:</b></p>
<ul>
This is a NuttX internal function so it follows the convention that 0 (<code>OK</code>) is returned on success and a negated <code>errno</code> is returned on failure.
</ul>
<h3>2.3.7 <a name="exec"><code>exec()</code></a></h3>
<p><b>Function Prototype:</b></p>
<ul><pre>
#include &lt:nuttx/binfmt/binfmt.h&gt;
int exec(FAR const char *filename, FAR const char **argv,
FAR const struct symtab_s *exports, int nexports);
</pre></ul>
<p><b>Description:</b></p>
<ul>
This is a convenience function that wraps <code>load_</code> and <code>exec_module()</code> into one call.
</ul>
<p><b>Input Parameters:</b></p>
<ul>
<li><code>filename</code>: Full path to the binary to be loaded.</li>
<li><code>argv</code>: Argument list.</li>
<li><code>exports</code>: Table of exported symbols.</li>
<li><code>exports</code>: The number of symbols in exports.</li>
</ul>
<p><b>Returned Value:</b></p>
<ul>
This is an end-user function, so it follows the normal convention:
Returns 0 (<code>OK</code>) on success.
On failure, it returns -1 (<code>ERROR</code>) with <code>errno</code> set appropriately.
</ul>
<h3>2.3.8 <a name="envpath_init"><code>envpath_init()</code></a></h3>
<p><b>Function Prototype:</b></p>
<ul><pre>
#include &lt:nuttx/envpath.h&gt;
#ifdef CONFIG_LIB_ENVPATH
ENVPATH_HANDLE envpath_init(void);
#endif
</pre></ul>
<p><b>Description:</b></p>
<ul>
<p>
Initialize for the traversal of each value in the <code>PATH</code> variable.
The usage is sequence is as follows:
</p>
<ol>
<li>
Call <code>envpath_init()</code> to initialize for the traversal.
<code>envpath_init()</code> will return an opaque handle that can then be provided to <code>envpath_next()</code> and <code>envpath_release()</code>.
</li>
<li>
Call <code>envpath_next()</code> repeatedly to examine every file that lies in the directories of the <code>PATH</code> variable.
</li>
<li>
Call <code>envpath_release()</code> to free resources set aside by <code>envpath_init()</code>.
</li>
</ol>
</ul>
<p><b>Input Parameters:</b> <i>None</i></p>
<p><b>Returned Value:</b></p>
<ul>
On success, <code>envpath_init()</code> return a non-<code>NULL</code>, opaque handle that may subsequently be used in calls to <code>envpath_next()</code> and <code>envpath_release()</code>.
On error, a <code>NULL</code> handle value will be returned.
The most likely cause of an error would be that there is no value associated with the <code>PATH</code> variable.
</ul>
<h3>2.3.9 <a name="envpath_next"><code>envpath_next()</code></a></h3>
<p><b>Function Prototype:</b></p>
<ul><pre>
#include &lt:nuttx/envpath.h&gt;
#ifdef CONFIG_LIB_ENVPATH
FAR char *envpath_next(ENVPATH_HANDLE handle, FAR const char *relpath);
#endif
</pre></ul>
<p><b>Description:</b></p>
<ul>
Traverse all possible values in the <code>PATH</code> variable in attempt to find the full path to an executable file when only a relative path is provided.
</ul>
<p><b>Input Parameters:</b></p>
<ul>
<li><code>handle</code>: The handle value returned by <code>envpath_init()</code>.</li>
<li><code>relpath</code>: The relative path to the file to be found.</li>
</ul>
<p><b>Returned Value:</b></p>
<ul>
<p>
On success, a non-<code>NULL</code> pointer to a null-terminated string is provided.
This is the full path to a file that exists in the file system.
This function will verify that the file exists (but will not verify that it is marked executable).
</p>
<p>
NOTE: The string pointer return in the success case points to allocated memory.
This memory must be freed by the called by calling <code>kmm_free()</code>.
</p>
<p>
<code>NULL</code is returned if no path is found to any file with the provided <code>relpath</colde> from any absolute path in the <code>PATH</code> variable.
In this case, there is no point in calling <code>envpath_next()</code> further; <code>envpath_release()</code> must be called to release resources set aside by <code>expath_init()</code>.
</p>
</ul>
<h3>2.3.10- <a name="envpath_release"><code>envpath_release()</code></a></h3>
<p><b>Function Prototype:</b></p>
<ul><pre>
#include &lt:nuttx/envpath.h&gt;
#ifdef CONFIG_LIB_ENVPATH
void envpath_release(ENVPATH_HANDLE handle);
#endif
</pre></ul>
<p><b>Description:</b></p>
<ul>
Release all resources set aside by <code>envpath_init</code> when the handle value was created.
The handle value is invalid on return from this function.
Attempts to all <code>envpath_next()</code> or <code>envpath_release()</code> with such a <i>stale</i> handle will result in undefined (i.e., not good) behavior.
</ul>
<p><b>Input Parameters:</b></p>
<ul>
<li><code>handle</code>: The handle value returned by <code>envpath_init()</code>.</li>
</ul>
<p><b>Returned Value:</b> <i>None</i></p>
<table width ="100%">
<tr bgcolor="#e4e4e4">
<td>
<h1>3.0 <a name="symtab">Symbol Tables</a></h1>
</td>
</tr>
</table>
<p>
<b>Symbol Tables</b>.
Symbol tables are lists of name value mappings:
The name is a string that identifies a symbol, and the value is an address in memory where the symbol of that name has been positioned.
In most NuttX architectures symbol tables are required, as a minimum, in order to dynamically link the loaded binary object with the base code on FLASH.
Since the binary object was separately built and separately linked, these symbols will appear as <i>undefined</i> symbols in the binary object.
The binary loader will use the symbol table to look up the symbol by its name and to provide the address associated with the symbol as needed to perform the dynamic linking of the binary object to the base FLASH code.
</p>
<h2>3.1 <a name="symtabhdr">Symbol Table Header Files</a></h2>
<p>
The interface to the symbol table logic is described in the header file
<a href="https://bitbucket.org/nuttx/nuttx/src/master/include/nuttx/binfmt/symtab.h" target="_blank">
<code>include/nuttx/binfmt/symtab.h</code></a>.
A brief summary of the data structurs and interfaces prototyped in that header file are listed below.
</p>
<h2>3.2 <a name="symtabdata">Symbol Table Data Structures</a></h2>
<p>
<code>struct symbtab_s</code> describes one entry in the symbol table.
</p>
<ul><pre>
struct symtab_s
{
FAR const char *sym_name; /* A pointer to the symbol name string */
FAR const void *sym_value; /* The value associated with the string */
};
</pre></ul>
</p>
A symbol table is a fixed size array of <code>struct symtab_s</code>.
The information is intentionally minimal and supports only:
</p>
<ol>
<li>
Function pointers as <code>sym_values</code>.
Of other kinds of values need to be supported, then typing information would also need to be included in the structure.
</li>
<li>
Fixed size arrays.
There is no explicit provisional for dynamically adding or removing entries from the symbol table (realloc might be used for that purpose if needed).
The intention is to support only fixed size arrays completely defined at compilation or link time.
</li>
</ol>
<h2>3.3 <a name="symtabfuncif">Symbol Table Function Interfaces</a></h2>
<ul>
<a href="#symtab_findbyname">3.3.1 <code>symtab_findbyname()</code></a><br>
<a href="#symtab_findorderedbyname">3.3.2 <code>symtab_findorderedbyname()</code></a><br>
<a href="#symtab_findbyvalue">3.3.3 <code>symtab_findbyvalue()</code></a><br>
</ul>
<h3>3.3.1 <a name="symtab_findbyname"><code>symtab_findbyname()</code></a></h3>
<p><b>Function Prototype:</b></p>
<ul><pre>
#include &lt:nuttx/binfmt/symtab.h&gt;
FAR const struct symtab_s *
symtab_findbyname(FAR const struct symtab_s *symtab,
FAR const char *name, int nsyms);
</pre></ul>
<p><b>Description:</b></p>
<ul>
Find the symbol in the symbol table with the matching name.
This version assumes that table is not ordered with respect to symbol name and, hence, access time will be linear with respect to <code>nsyms</code>.
</ul>
<p><b>Returned Value:</b></p>
<ul>
A reference to the symbol table entry if an entry with the matching name is found;
<code>NULL</code> is returned if the entry is not found.
</ul>
<h3>3.3.2 <a name="symtab_findorderedbyname"><code>symtab_findorderedbyname()</code></a></h3>
<p><b>Function Prototype:</b></p>
<ul><pre>
#include &lt:nuttx/binfmt/symtab.h&gt;
FAR const struct symtab_s *
symtab_findorderedbyname(FAR const struct symtab_s *symtab,
FAR const char *name, int nsyms);
</pre></ul>
<p><b>Description:</b></p>
<ul>
Find the symbol in the symbol table with the matching name.
This version assumes that table ordered with respect to symbol name.
</ul>
<p><b>Returned Value:</b></p>
<ul>
A reference to the symbol table entry if an entry with the matching name is found;
<code>NULL</code> is returned if the entry is not found.
</ul>
<h3>3.3.3 <a name="symtab_findbyvalue"><code>symtab_findbyvalue()</code></a></h3>
<p><b>Function Prototype:</b></p>
<ul><pre>
#include &lt:nuttx/binfmt/symtab.h&gt;
FAR const struct symtab_s *
symtab_findbyvalue(FAR const struct symtab_s *symtab,
FAR void *value, int nsyms);
</pre></ul>
<p><b>Description:</b></p>
<ul>
Find the symbol in the symbol table whose value closest (but not greater than), the provided value.
This version assumes that table is not ordered with respect to symbol name and, hence, access time will be linear with respect to <code>nsyms</code>.
</ul>
<p><b>Returned Value:</b></p>
<ul>
A reference to the symbol table entry if an entry with the matching name is found;
<code>NULL</code> is returned if the entry is not found.
</ul>
<table width ="100%">
<tr bgcolor="#e4e4e4">
<td>
<h1>4.0 <a name="configuration">Configuration Variables</a></h1>
</td>
</tr>
</table>
<ul>
<p>
<code>CONFIG_BINFMT_DISABLE</code>:
By default, support for loadable binary formats is built.
This logic may be suppressed be defining this setting.
</p>
<p>
<code>CONFIG_BINFMT_CONSTRUCTORS</code>:
Build in support for C++ constructors in loaded modules.
</p>
<p>
<code>CONFIG_SYMTAB_ORDEREDBYNAME</code>:
Symbol tables are order by name (rather than value).
</p>
</ul>
<p>
Additional configuration options may be required for the each enabled binary format.
</p>
</body>
</html>

View File

@ -1,672 +0,0 @@
<html>
<head>
<title>On-Demand Paging</title>
<link rel="stylesheet" href="style.css">
</head>
<body background="backgd.gif">
<hr><hr>
<table width ="100%">
<tr align="center" bgcolor="#e4e4e4">
<td>
<h1><big><font color="#3c34ec"><i>On-Demand Paging</i></font></big></h1>
<p>Last Updated: February 4, 2019</p>
</td>
</tr>
</table>
<hr><hr>
<table width ="100%">
<tr bgcolor="#e4e4e4">
<td>
<h1>Table of Contents</h1>
</td>
</tr>
</table>
<center><table width ="80%">
<tr>
<td>
<table>
<tr>
<td valign="top" width="22"><img height="20" width="20" src="favicon.ico"></td>
<td>
<a href="#Introduction">Introduction</a>
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>
<a href="#Overview">Overview</a>
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>
<a href="#Terminology">Terminology</a>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>
<table>
<tr>
<td valign="top" width="22"><img height="20" width="20" src="favicon.ico"></td>
<td>
<a href="#NuttXDesign">NuttX Common Logic Design Description</a>
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>
<a href="#Initialization">Initialization</a>
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>
<a href="#PageFaults">Page Faults</a>
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>
<a href="#FillInitiation">Fill Initiation</a>
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>
<a href="#FillComplete">Fill Complete</a>
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>
<a href="#TaskResumption">Task Resumption</a>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>
<table>
<tr>
<td valign="top" width="22"><img height="20" width="20" src="favicon.ico"></td>
<td>
<a href="#ArchSupport">Architecture-Specific Support Requirements</a>
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>
<a href="#MemoryOrg">Memory Organization</a>
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>
<a href="#ArchFuncs">Architecture-Specific Functions</a>
</td>
</tr>
</table>
</td>
</tr>
</table></center>
<table width ="100%">
<tr bgcolor="#e4e4e4">
<td>
<a name="Introduction"><h1>Introduction</h1></a>
</td>
</tr>
</table>
<a name="Overview"><h2>Overview</h2></a>
<p>
This document summarizes the design of NuttX on-demand paging.
This feature permits embedded MCUs with some limited RAM space to execute large programs from some non-random access media.
</p>
<p>
What kind of platforms can support NuttX on-demang paging?
<ol>
<li>
The MCU should have some large, probably low-cost non-volatile storage such as serial FLASH or an SD card.
This storage probably does not support non-random access (otherwise, why not just execute the program directly on the storage media).
SD and serial FLASH are inexpensive and do not require very many pins and SPI support is prevalent in just about all MCUs.
This large serial FLASH would contain a big program. Perhaps a program of several megabytes in size.
</li>
<li>
The MCU must have a (relatively) small block of fast SRAM from which it can execute code.
A size of, say 256K (or 192K as in the NXP LPC3131) would be sufficient for many applications.
</li>
<li>
The MCU has an MMU (again like the NXP LPC3131).
</li>
</ol>
</p>
<p>
If the platform meets these requirement, then NuttX can provide on-demand paging:
It can copy .text from the large program in non-volatile media into RAM as needed to execute a huge program from the small RAM.
</p>
<a name="Terminology"><h2>Terminology</h2></a>
<dl>
<dt><code>g_waitingforfill</code></dt>
<dd>An OS list that is used to hold the TCBs of tasks that are waiting for a page fill.</dd>
<dt><code>g_pftcb</code></dt>
<dd>A variable that holds a reference to the TCB of the thread that is currently be re-filled.</dd>
<dt><code>g_pgworker</code></dt>
<dd>The <i>process</i> ID of the thread that will perform the page fills.</dd>
<dt><code>pg_callback()</code></dt>
<dd>The callback function that is invoked from a driver when the fill is complete.</dd>
<dt><code>pg_miss()</code></dt>
<dd>The function that is called from architecture-specific code to handle a page fault.</dd>
<dt><code>TCB</code></dt>
<dd>Task Control Block</dd>
</dl>
<table width ="100%">
<tr bgcolor="#e4e4e4">
<td>
<a name="NuttXDesign"><h1>NuttX Common Logic Design Description</h1></a>
</td>
</tr>
</table>
<a name="Initialization"><h2>Initialization</h2></a>
<p>
The following declarations will be added.
<ul>
<li>
<b><code>g_waitingforfill</code></b>.
A doubly linked list that will be used to implement a prioritized list of the TCBs of tasks that are waiting for a page fill.
</li>
<li>
<b><code>g_pgworker</code></b>.
The <i>process</i> ID of the thread that will perform the page fills
</li>
</ul>
</p>
<p>
During OS initialization in <code>sched/init/nx_start.c</code>, the following steps
will be performed:
<ul>
<li>
The <code>g_waitingforfill</code> queue will be initialized.
</li>
<li>
The special, page fill worker thread, will be started.
The <code>pid</code> of the page will worker thread will be saved in <code>g_pgworker</code>.
Note that we need a special worker thread to perform fills;
we cannot use the &quot;generic&quot; worker thread facility because we cannot be
assured that all actions called by that worker thread will always be resident in memory.
</li>
</ul>
</p>
<p>
Declarations for <code>g_waitingforfill</code>, <code>g_pgworker</code>, and other
internal, private definitions will be provided in <code>sched/paging/paging.h</code>.
All public definitions that should be used by the architecture-specific code will be available
in <code>include/nuttx/page.h</code>.
Most architecture-specific functions are declared in <code>include/nuttx/arch.h</code>,
but for the case of this paging logic, those architecture specific functions are instead declared in <code>include/nuttx/page.h</code>.
</p>
<a name="PageFaults"><h2>Page Faults</h2></a>
<p>
<b>Page fault exception handling</b>.
Page fault handling is performed by the function <code>pg_miss()</code>.
This function is called from architecture-specific memory segmentation
fault handling logic. This function will perform the following
operations:
<ol>
<li>
<b>Sanity checking</b>.
This function will ASSERT if the currently executing task is the page fill worker thread.
The page fill worker thread is how the page fault is resolved and all logic associated with the page fill worker
must be &quot;<a href="#MemoryOrg">locked</a>&quot; and always present in memory.
</li>
<li>
<b>Block the currently executing task</b>.
This function will call <code>up_block_task()</code> to block the task at the head of the ready-to-run list.
This should cause an interrupt level context switch to the next highest priority task.
The blocked task will be marked with state <code>TSTATE_WAIT_PAGEFILL</code> and will be retained in the <code>g_waitingforfill</code> prioritized task list.
</li>
<li>
<b>Boost the page fill worker thread priority</b>.
Check the priority of the task at the head of the <code>g_waitingforfill</code> list.
If the priority of that task is higher than the current priority of the page fill worker thread, then boost the priority of the page fill worker thread to that priority.
Thus, the page fill worker thread will always run at the priority of the highest priority task that is waiting for a fill.
</li>
<li>
<b>Signal the page fill worker thread</b>.
Is there a page already being filled?
If not then signal the page fill worker thread to start working on the queued page fill requests.
</li>
</ol>
</p>
<p>
When signaled from <code>pg_miss()</code>, the page fill worker thread will be awakenend and will initiate the fill operation.
</p>
<p>
<b>Input Parameters.</b>
None -- The head of the ready-to-run list is assumed to be that task that caused the exception.
The current task context should already be saved in the TCB of that task.
No additional inputs are required.
</p>
<p>
<b>Assumptions</b>.
<ul>
<li>
It is assumed that this function is called from the level of an exception handler and that all interrupts are disabled.
</li>
<li>
The <code>pg_miss()</code> must be &quot;<a href="#MemoryOrg">locked</a>&quot; in memory.
Calling <code>pg_miss()</code> cannot cause a nested page fault.
</li>
<li>
It is assumed that currently executing task (the one at the head of the ready-to-run list) is the one that cause the fault.
This will always be true unless the page fault occurred in an interrupt handler.
Interrupt handling logic must always be available and &quot;<a href="#MemoryOrg">locked</a>&quot; into memory so that page faults never come from interrupt handling.
</li>
<li>
The architecture-specific page fault exception handling has already verified that the exception did not occur from interrupt/exception handling logic.
</li>
<li>
As mentioned above, the task causing the page fault must not be the page fill worker thread because that is the only way to complete the page fill.
</li>
</ul>
</p>
<a name="FillInitiation"><h2>Fill Initiation</h2></a>
<p>
The page fill worker thread will be awakened on one of three conditions:
<ul>
<li>
When signaled by <code>pg_miss()</code>, the page fill worker thread will be awakenend (see above),
</li>
<li>
From <code>pg_callback()</code> after completing last fill (when <code>CONFIG_PAGING_BLOCKINGFILL</code> is defined... see below), or
</li>
<li>
A configurable timeout expires with no activity.
This timeout can be used to detect failure conditions such things as fills that never complete.
</li>
</ul>
</p>
<p>
The page fill worker thread will maintain a static variable called <code>struct tcb_s *g_pftcb</code>.
If no fill is in progress, <code>g_pftcb</code> will be NULL.
Otherwise, it will point to the TCB of the task which is receiving the fill that is in progress.
</p>
<ul><small>
<b>NOTE</b>:
I think that this is the only state in which a TCB does not reside in some list.
Here is it in limbo, outside of the normally queuing while the page file is in progress.
While here, it will be marked with TSTATE_TASK_INVALID.
</small></ul>
<p>
When awakened from <code>pg_miss()</code>, no fill will be in progress and <code>g_pftcb</code> will be NULL.
In this case, the page fill worker thread will call <code>pg_startfill()</code>.
That function will perform the following operations:
<ul>
<li>
Call the architecture-specific function <code>up_checkmapping()</code> to see if the page fill
still needs to be performed.
In certain conditions, the page fault may occur on several threads and be queued multiple times.
In this corner case, the blocked task will simply be restarted (see the logic below for the
case of normal completion of the fill operation).
</li>
<li>
Call <code>up_allocpage(tcb, &vpage)</code>.
This architecture-specific function will set aside page in memory and map to virtual address (vpage).
If all available pages are in-use (the typical case),
this function will select a page in-use, un-map it, and make it available.
</li>
<li>
Call the architecture-specific function <code>up_fillpage()</code>.
Two versions of the up_fillpage function are supported -- a blocking and a non-blocking version based upon the configuration setting <code>CONFIG_PAGING_BLOCKINGFILL</code>.
<ul>
<li>
If <code>CONFIG_PAGING_BLOCKINGFILL</code> is defined, then up_fillpage is blocking call.
In this case, <code>up_fillpage()</code> will accept only (1) a reference to the TCB that requires the fill.
Architecture-specific context information within the TCB will be sufficient to perform the fill.
And (2) the (virtual) address of the allocated page to be filled.
The resulting status of the fill will be provided by return value from <code>up_fillpage()</code>.
</li>
<li>
If <code>CONFIG_PAGING_BLOCKINGFILL</code> is defined, then up_fillpage is non-blocking call.
In this case <code>up_fillpage()</code> will accept an additional argument:
The page fill worker thread will provide a callback function, <code>pg_callback</code>.
This function is non-blocking, it will start an asynchronous page fill.
After calling the non-blocking <code>up_fillpage()</code>, the page fill worker thread will wait to be signaled for the next event -- the fill completion event.
The callback function will be called when the page fill is finished (or an error occurs).
The resulting status of the fill will be providing as an argument to the callback functions.
This callback will probably occur from interrupt level.
</ul>
</li>
</ul>
</p>
<p>
In any case, while the fill is in progress, other tasks may execute.
If another page fault occurs during this time, the faulting task will be blocked, its TCB will be added (in priority order) to <code>g_waitingforfill</code>, and the priority of the page worker task may be boosted.
But no action will be taken until the current page fill completes.
NOTE: The IDLE task must also be fully <a href="#MemoryOrg">locked</a> in memory.
The IDLE task cannot be blocked.
It the case where all tasks are blocked waiting for a page fill, the IDLE task must still be available to run.
<p>
The architecture-specific functions, <code>up_checkmapping()</code>, <code>up_allocpage(tcb, &vpage)</code> and <code>up_fillpage(page, pg_callback)</code>
will be prototyped in <code>include/nuttx/arch.h</code>
</p>
<a name="FillComplete"><h2>Fill Complete</h2></a>
<p>
For the blocking <code>up_fillpage()</code>, the result of the fill will be returned directly from the call to <code>up_fillpage</code>.
</p>
<p>
For the non-blocking <code>up_fillpage()</code>, the architecture-specific driver call the <code>pg_callback()</code> that was provided to <code>up_fillpage()</code> when the fill completes.
In this case, the <code>pg_callback()</code> will probably be called from driver interrupt-level logic.
The driver will provide the result of the fill as an argument to the callback function.
NOTE: <code>pg_callback()</code> must also be <a href="#MemoryOrg">locked</a> in memory.
</p>
<p>
In this non-blocking case, the callback <code>pg_callback()</code> will perform the following operations when it is notified that the fill has completed:
<ul>
<li>
Verify that <code>g_pftcb</code> is non-NULL.
</li>
<li>
Find the higher priority between the task waiting for the fill to complete in <code>g_pftcb</code> and the task waiting at the head of the <code>g_waitingforfill</code> list.
That will be the priority of he highest priority task waiting for a fill.
</li>
<li>
If this higher priority is higher than current page fill worker thread, then boost worker thread's priority to that level.
Thus, the page fill worker thread will always run at the priority of the highest priority task that is waiting for a fill.
</li>
<li>
Save the result of the fill operation.
</li>
<li>
Signal the page fill worker thread.
</li>
</ul>
</p>
<a name="TaskResumption"><h2>Task Resumption</h2></a>
<p>
For the non-blocking <code>up_fillpage()</code>, the page fill worker thread will detect that the page fill is complete when it is awakened with <code>g_pftcb</code> non-NULL and fill completion status from <code>pg_callback</code>.
In the non-blocking case, the page fill worker thread will know that the page fill is complete when <code>up_fillpage()</code> returns.
</p>
<p>
In this either, the page fill worker thread will:
<ul>
<li>
Verify consistency of state information and <code>g_pftcb</code>.
</li>
<li>
Verify that the page fill completed successfully, and if so,
</li>
<li>
Call <code>up_unblocktask(g_pftcb)</code> to make the task that just received the fill ready-to-run.
</li>
<li>
Check if the <code>g_waitingforfill</code> list is empty.
If not:
<ul>
<li>
Remove the highest priority task waiting for a page fill from <code>g_waitingforfill</code>,
</li>
<li>
Save the task's TCB in <code>g_pftcb</code>,
</li>
<li>
If the priority of the thread in <code>g_pftcb</code>, is higher in priority than the default priority of the page fill worker thread, then set the priority of the page fill worker thread to that priority.
</li>
<li>
Call <code>pg_startfill()</code> which will start the next fill (as described above).
</li>
</ul>
</li>
<li>
Otherwise,
<ul>
<li>
Set <code>g_pftcb</code> to NULL.
</li>
<li>
Restore the default priority of the page fill worker thread.
</li>
<li>
Wait for the next fill related event (a new page fault).
</li>
</ul>
</li>
</ul>
</p>
<table width ="100%">
<tr bgcolor="#e4e4e4">
<td>
<a name="ArchSupport"><h1>Architecture-Specific Support Requirements</h1></a>
</td>
</tr>
</table>
<a name="MemoryOrg"><h2>Memory Organization</h2></a>
<p>
<b>Memory Regions</b>.
Chip specific logic will map the virtual and physical address spaces into three general regions:
<ol>
<li>
A .text region containing &quot;<a href="#MemoryOrg">locked-in-memory</a>&quot; code that is always available and will never cause a page fault.
This locked memory is loaded at boot time and remains resident for all time.
This memory regions must include:
<ul>
<li>
All logic for all interrupt paths.
All interrupt logic must be locked in memory because the design present here will not support page faults from interrupt handlers.
This includes the page fault handling logic and <a href="#PageFaults"><code>pg_miss()</code></a> that is called from the page fault handler.
It also includes the <a href="#FillComplete"><code>pg_callback()</code></a> function that wakes up the page fill worker thread
and whatever architecture-specific logic that calls <code>pg_callback()</code>.
</li>
<li>
All logic for the IDLE thread.
The IDLE thread must always be ready to run and cannot be blocked for any reason.
</li>
<li>
All of the page fill worker thread must be locked in memory.
This thread must execute in order to unblock any thread waiting for a fill.
It this thread were to block, there would be no way to complete the fills!
</ul>
</li>
<li>
A .text region containing pages that can be assigned allocated, mapped to various virtual addresses, and filled from some mass storage medium.
</li>
<li>
And a fixed RAM space for .bss, .text, and .heap.
</li>
</ol>
</p>
<p>
This memory organization is illustrated in the following table.
Notice that:
<ul>
<li>
There is a one-to-one relationship between pages in the virtual address space and between pages of .text in the non-volatile mass storage device.
</li>
<li>
There are, however, far fewer physical pages available than virtual pages.
Only a subset of physical pages will be mapped to virtual pages at any given time.
This mapping will be performed on-demand as needed for program execution.
</ul>
</p>
<center><table width="80%">
<tr>
<th width="33%">SRAM</th>
<th width="33%">Virtual Address Space</th>
<th width="34%">Non-Volatile Storage</th>
</tr>
<tr>
<td>&nbsp;</td>
<td bgcolor="lightslategray">DATA</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>&nbsp;</td>
<td bgcolor="lightskyblue">Virtual Page <i>n</i> (<i>n</i> > <i>m</i>)</td>
<td bgcolor="lightskyblue">Stored Page <i>n</i></td>
</tr>
<tr>
<td>&nbsp;</td>
<td bgcolor="lightskyblue">Virtual Page <i>n-1</i></td>
<td bgcolor="lightskyblue">Stored Page <i>n-1</i></td>
</tr>
<tr>
<td bgcolor="lightslategray">DATA</td>
<td bgcolor="lightskyblue">...</td>
<td bgcolor="lightskyblue">...</td>
</tr>
<tr>
<td bgcolor="lightskyblue">Physical Page <i>m</i> (<i>m</i> < <i>n</i>)</td>
<td bgcolor="lightskyblue">...</td>
<td bgcolor="lightskyblue">...</td>
</tr>
<tr>
<td bgcolor="lightskyblue">Physical Page <i>m-1</i></td>
<td bgcolor="lightskyblue">...</td>
<td bgcolor="lightskyblue">...</td>
</tr>
<tr>
<td bgcolor="lightskyblue">...</td>
<td bgcolor="lightskyblue">...</td>
<td bgcolor="lightskyblue">...</td>
</tr>
<tr>
<td bgcolor="lightskyblue">Physical Page <i>1</i></td>
<td bgcolor="lightskyblue">Virtual Page <i>1</i></td>
<td bgcolor="lightskyblue">Stored Page <i>1</i></td>
</tr>
<tr>
<td bgcolor="slategray">Locked Memory</td>
<td bgcolor="slategray">Locked Memory</td>
<td bgcolor="slategray">Memory Resident</td>
</tr>
</table></center>
<p>
<b>Example</b>.
As an example, suppose that the size of the SRAM is 192K (as in the NXP LPC3131). And suppose further that:
<ul>
<li>
The size of the locked, memory resident .text area is 32K, and
</li>
<li>
The size of the DATA area is 64K.
</li>
<li>
The size of one, managed page is 1K.
</li>
<li>
The size of the whole .text image on the non-volatile, mass storage device is 1024K.
</li>
</ul>
<p>
Then, the size of the locked, memory resident code is 32K (<i>m</i>=32 pages).
The size of the physical page region is 96K (96 pages), and the
size of the data region is 64 pages.
And the size of the virtual paged region must then be greater than or equal to (1024-32) or 992 pages (<i>n</i>).
</p>
<p>
<b>Building the Locked, In-Memory Image</b>.
One way to accomplish this would be a two phase link:
<ul>
<li>
In the first phase, create a partially linked objected containing all interrupt/exception handling logic, the page fill worker thread plus all parts of the IDLE thread (which must always be available for execution).
</li>
<li>
All of the <code>.text</code> and <code>.rodata</code> sections of this partial link should be collected into a single section.
</li>
<li>
The second link would link the partially linked object along with the remaining object to produce the final binary.
The linker script should position the &quot;special&quot; section so that it lies in a reserved, &quot;non-swappable&quot; region.
</ul>
</p>
<a name="ArchFuncs"><h2>Architecture-Specific Functions</h2></a>
<p>
Most standard, architecture-specific functions are declared in <code>include/nuttx/arch.h</code>.
However, for the case of this paging logic, the architecture specific functions are declared in <code>include/nuttx/page.h</code>.
Standard, architecture-specific functions that should already be provided in the architecture port.
The following are used by the common paging logic:
</p>
<ul><dl>
<dt>
<code>void up_block_task(FAR struct tcb_s *tcb, tstate_t task_state);</code>
</dt>
<dd>
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 by the on-demand paging logic in order to block the task that requires the
page fill, and to
</dd>
<dt>
<code>void up_unblock_task(FAR struct tcb_s *tcb);</code>
</dt>
<dd>
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.
This function will be called
</dd>
</dl></ul>
<p>
New, additional functions that must be implemented just for on-demand paging support:
</p>
<ul><dl>
<dt>
<code>int up_checkmapping(FAR struct tcb_s *tcb);</code>
</dt>
<dd>
The function <code>up_checkmapping()</code> returns an indication if the page fill still needs to performed or not.
In certain conditions, the page fault may occur on several threads and be queued multiple times.
This function will prevent the same page from be filled multiple times.
</dd>
<dt>
<code>int up_allocpage(FAR struct tcb_s *tcb, FAR void *vpage);</code>
</dt>
<dd>
This architecture-specific function will set aside page in memory and map to its correct virtual address.
Architecture-specific context information saved within the TCB will provide the function with the information needed to identify the virtual miss address.
This function will return the allocated physical page address in <code>vpage</code>.
The size of the underlying physical page is determined by the configuration setting <code>CONFIG_PAGING_PAGESIZE</code>.
NOTE: This function must <i>always</i> return a page allocation.
If all available pages are in-use (the typical case), then this function will select a page in-use, un-map it, and make it available.
</dd>
<dt><code>int up_fillpage(FAR struct tcb_s *tcb, FAR const void *vpage, void (*pg_callback)(FAR struct tcb_s *tcb, int result));</code>
</dt>
The actual filling of the page with data from the non-volatile, must be performed by a separate call to the architecture-specific function, <code>up_fillpage()</code>.
This will start asynchronous page fill.
The common paging logic will provide a callback function, <code>pg_callback</code>, that will be called when the page fill is finished (or an error occurs).
This callback is assumed to occur from an interrupt level when the device driver completes the fill operation.
</dt>
</dl></ul>
</body>
</html>

View File

@ -1,765 +0,0 @@
<html>
<head>
<title>NXFLAT</title>
<link rel="stylesheet" href="style.css">
</head>
<body background="backgd.gif">
<hr><hr>
<table width ="100%">
<tr align="center" bgcolor="#e4e4e4">
<td>
<h1><big><font color="#3c34ec"><i>NXFLAT</i></font></big></h1>
<p>Last Updated: October 1, 2017</p>
</td>
</tr>
</table>
<hr><hr>
<table width ="100%">
<tr bgcolor="#e4e4e4">
<td>
<h1>Table of Contents</h1>
</td>
</tr>
</table>
<center><table width ="80%">
<tr>
<td>
<table>
<tr>
<td valign="top" width="22"><img height="20" width="20" src="favicon.ico"></td>
<td>
<a href="#overview">1.0 Overview</a>
</td>
</tr>
<tr>
<td><br></td>
<td>
<a href="#functionality">1.1 Functionality</a>
</td>
</tr>
<tr>
<td><br></td>
<td>
<a href="#background">1.2 Background</a>
</td>
</tr>
<tr>
<td><br></td>
<td>
<a href="#limitations">1.3 Limitations</a>
</td>
</tr>
<tr>
<td><br></td>
<td>
<a href="#supported">1.4 Supported Processors</a>
</td>
</tr>
<tr>
<td><br></td>
<td>
<a href="#status">1.5 Development Status</a>
</td>
</tr>
<tr>
<td valign="top" width="22"><img height="20" width="20" src="favicon.ico"></td>
<td>
<a href="#toolchain">2.0 NXFLAT Toolchain</a>
</td>
</tr>
<tr>
<td><br></td>
<td>
<a href="#building">1.2 Building the NXFLAT Toolchain</a>
</td>
</tr>
<tr>
<td><br></td>
<td>
<a href="#mknxflat">1.2 mknxflat</a>
</td>
</tr>
<tr>
<td><br></td>
<td>
<a href="#ldnxflat">1.3 ldnxflat</a>
</td>
</tr>
<tr>
<td><br></td>
<td>
<a href="#mksymtab">1.4 mksymtab</a>
</td>
</tr>
<tr>
<td><br></td>
<td>
<a href="#making">1.5 Making an NXFLAT module</a>
</td>
</tr>
<tr>
<td valign="top" width="22"><img height="20" width="20" src="favicon.ico"></td>
<td>
<a href="#binfmt">3.0. Binary Loader APIs</a>
</td>
</tr>
<tr>
<td valign="top" width="22"><img height="20" width="20" src="favicon.ico"></td>
<td>
<a href="#nogot">Appendix A. No GOT Operation</a>
</td>
</tr>
<tr>
<td valign="top" width="22"><img height="20" width="20" src="favicon.ico"></td>
<td>
<a href="#pictext">Appendix B. PIC Text Workaround</a>
</td>
</tr>
</table>
</td>
</tr>
</table></center>
<table width ="100%">
<tr bgcolor="#e4e4e4">
<td>
<a name="overview"><h1>1.0 Overview</h1></a>
</td>
</tr>
</table>
<a name="functionality"><h2>1.1 Functionality</h2></a>
<p>
NXFLAT is a customized and simplified version of binary format implemented a few years ago called
<a HREF="http://xflat.sourceforge.net/">XFLAT</A>
With the NXFLAT binary format you will be able to do the following:
</p>
<ul>
<li>Place separately linked programs in a file system, and</li>
<li>Execute those programs by dynamically linking them to the base NuttX code.</li>
</ul>
<p>
This allows you to extend the NuttX base code after it has been written into FLASH.
One motivation for implementing NXFLAT is support clean CGI under an HTTPD server.
</p>
<p>
This feature is especially attractive when combined with the NuttX ROMFS support:
ROMFS allows you to execute programs in place (XIP) in flash without copying anything
other than the .data section to RAM.
In fact, the initial NXFLAT release only worked on ROMFS.
Later extensions also support execution NXFLAT binaries from an SRAM copy as well.
</p>
<p>
This NuttX feature includes:
</p>
<ul>
<li>
A dynamic loader that is built into the NuttX core
(See <a href="https://bitbucket.org/nuttx/nuttx/src/master/binfmt/" target="_blank">GIT</a>).
</li>
<li>
Minor changes to RTOS to support position independent code, and
</li>
<li>
A linker to bind ELF binaries to produce the NXFLAT binary format
(See <a href="https://bitbucket.org/nuttx/buildroot/src/master/toolchain/nxflat/" target="_blank">GIT).
</li>
</ul>
<a name="background"><h2>1.2 Background</h2></a>
<p>
NXFLAT is derived from <a href="http://xflat.sourceforge.net/">XFLAT</a>.
XFLAT is a toolchain add that provides full shared library and XIP executable
support for processors that have no Memory Management Unit (MMU<sup>1</sup>).
NXFLAT is greatly simplified for the deeply embedded environment targeted by Nuttx:
</p>
<ul>
<li>NXFLAT does not support shared libraries, because</li>
<li>NXFLAT does not support <i>exportation</i> of symbol values from a module</li>
</ul>
<p>
Rather, the NXFLAT module only <i>imports</i> symbol values.
In the NXFLAT model, the (PIC<sup>2</sup>) NXFLAT module resides in a FLASH file system and
when it is loaded at run time, it is dynamically linked only to the (non-PIC) base NuttX
code:
The base NuttX <i>exports</i> a symbol table; the NXFLAT module <i>imports</i> those symbol value
to dynamically bind the module to the base code.
</p>
<ul>
<p>
<sup>1</sup><small>MMU: &quot;Memory Management Unit&quot;</small><br>
<sup>2</sup><small>PIC: &quot;Position Independent Code&quot;</small>
</p>
</ul>
<a name="limitations"><h2>1.3 Limitations</h2></a>
<ul>
<li><b>ROMFS (or RAM mapping) Only</b>
<ul>
<p>
The current NXFLAT release will work only with either (1) NXFLAT executable modules residing on a ROMFS file system, or (2) executables residing on other file systems provided that <code>CONFIG_FS_RAMMAP</code> is defined.
This limitation is because the loader depends on the capability to <code>mmap()</code> the code segment.
See the <a href="NuttxUserGuide.html#mmapxip">NuttX User Guide</a> for further information.
</p>
<p>
NUTTX does not provide any general kind of file mapping capability.
In fact, <i>true</i> file mapping is only possible with MCUs that provide an MMU<sup>1</sup>.
Without an MMU, file system may support eXecution In Place (XIP) to mimic file mapping.
Only the ROMFS file system supports that kind of XIP execution need by NXFLAT.
</p>
<p>
It is also possible to <i>simulate</i> file mapping by allocating memory, copying the NXFLAT binary file into memory, and executing from the copy of the executable file in RAM.
That capability can be enabled with the <code>CONFIG_FS_RAMMAP</code> configuration option.
With that option enabled, NXFLAT will work that kind of file system but will require copying of all NXFLAT executables to RAM.
</p>
</ul>
</li>
<li><b>GCC/ARM/Cortex-M3/4 Only</b>
<ul>
<p>
At present, the NXFLAT toolchain is only available for ARM and Cortex-M3/4 (thumb2) targets.
</p>
</ul>
</li>
<li><b>Read-Only Data in RAM</b>
<ul>
<p>
With older GCC compilers (at least up to 4.3.3), read-only data must reside in RAM.
In code generated by GCC, all data references are indexed by the PIC<sup>2</sup> base register (that is usually R10 or <i>sl</i> for the ARM processors).
The includes read-only data (<code>.rodata</code>).
Embedded firmware developers normally like to keep <code>.rodata</code> in FLASH with the code sections.
But because all data is referenced with the PIC base register, all of that data must lie in RAM.
A NXFLAT change to work around this is under investigation<sup>3</sup>.
</p>
<p>
Newer GCC compilers (at least from 4.6.3), read-only data is no long GOT-relative, but is now accessed PC-relative. With PC relative addressing, read-only data <i>must</i> reside in the I-Space.
</p>
</ul>
</li>
<li><b>Globally Scoped Function Function Pointers</b>
<ul>
<p>
If a function pointer is taken to a statically defined function, then (at least for ARM) GCC will generate a relocation that NXFLAT cannot handle.
The workaround is make all such functions global in scope.
A fix would involve a change to the GCC compiler as described in <a href="#pictext">Appendix B</a>.
</p>
</ul>
</li>
<li><b>Special Handling of Callbacks</b>
<ul>
<p>
Callbacks through function pointers must be avoided or, when then cannot be avoided, handled very specially.
The reason for this is that the PIC module requires setting of a special value in a PIC register.
If the callback does not set the PIC register, then the called back function will fail because it will be unable to correctly access data memory.
Special logic is in place to handle some NuttX callbacks: Signal callbacks and watchdog timer callbacks.
But other callbacks (like those used with <code>qsort()</code> must be avoided in an NXFLAT module.
</p>
</ul>
</li>
</ul>
<ul><p>
<sup>1</sup><small>MMU: &quot;Memory Management Unit&quot;</small><br>
<sup>2</sup><small>PIC: &quot;Position Independent Code&quot;</small><br>
<sup>3</sup><small>A work around is under consideration:
At run time, the <code>.rodata</code> offsets will be indexed by a RAM address.
If the dynamic loader were to offset those <code>.rodata</code> offsets properly, it
still might be possible to reference <code>.rodata</code> in ROM.
That work around is still a topic of investigation at this time.</small>
</p></ul>
<a name="supported"><h2>1.4 Supported Processors</h2></a>
<p>
As mentioned <a href="#limitations">above</a>, the NXFLAT toolchain is only available for ARM and
Cortex-M3 (thumb2) targets.
Furthermore, NXFLAT has only been tested on the Eagle-100 LMS6918 Cortex-M3 board.
</p>
<a name="status"><h2>1.5 Development Status</h2></a>
<p>
The initial release of NXFLAT was made in NuttX version 0.4.9.
Testing is limited to the tests found under <code>apps/examples/nxflat</code> in the source tree.
Some known problems exist
(see the <a href="https://bitbucket.org/nuttx/nuttx/src/master/TODO" target="_blank">TODO</a> list).
As such, NXFLAT is currently in an early alpha phase.
</p>
<table width ="100%">
<tr bgcolor="#e4e4e4">
<td>
<a name="toolchain"><h1>2.0 NXFLAT Toolchain</h1></a>
</td>
</tr>
</table>
<a name="building"><h2>1.2 Building the NXFLAT Toolchain</h2></a>
<p>
In order to use NXFLAT, you must use special NXFLAT tools to create the binary module in FLASH.
To do this, you will need to download the buildroot package and build it on your Linux or Cygwin machine.
The buildroot can be downloaded from
<a href="https://bitbucket.org/nuttx/buildroot/downloads">Bitbucket.org</a>.
You will need version 0.1.7 or later.
</p>
<p>
Here are some general build instructions:
</p>
<ul>
<li>
You must have already configured Nuttx in <code>&lt;some-dir&gt;/nuttx</code>
</li>
<li>
Download the buildroot package <code>buildroot-0.x.y</code> into <code>&lt;some-dir&gt;</code>
<li>
</li>
Unpack <code>&lt;some-dir&gt;/buildroot-0.x.y.tar.gz</code> using a command like <code>tar zxf buildroot-0.x.y</code>.
This will result in a new directory like <code>&lt;some-dir&gt;/buildroot-0.x.y</code>
</li>
<li>
Move this into position: <code>mv &lt;some-dir&gt;/buildroot-0.x.y</code>&lt;some-dir&gt;/buildroot</code>
</li>
<li>
<code>cd </code>&lt;some-dir&gt;/buildroot</code>
</li>
<li>
Copy a configuration file into the top buildroot directory: <code>cp boards/abc-defconfig-x.y.z .config</code>.
</li>
<li>
Enable building of the NXFLAT tools by <code>make menuconfig</code>.
Select to build the NXFLAT toolchain with GCC (you can also select omit building GCC with and only build the
NXFLAT toolchain for use with your own GCC toolchain).
</li>
<li>
Make the toolchain: <code>make</code>.
When the make completes, the tool binaries will be available under
<code>&lt;some-dir&gt;/buildroot/build_abc/staging_dir/bin</code>
</li>
</ul>
<a name="mknxflat"><h2>1.2 mknxflat</h2></a>
<p>
<code>mknxflat</code> is used to build a <i>thunk</i> file.
See <a href="#making">below</a> for usage.
<ul><pre>
Usage: mknxflat [options] &lt;bfd-filename&gt;
Where options are one or more of the following. Note
that a space is always required between the option and
any following arguments.
-d Use dynamic symbol table. [symtab]
-f &lt;cmd-filename&gt;
Take next commands from &lt;cmd-filename&gt; [cmd-line]
-o &lt;out-filename&gt;
Output to <out-filename> [stdout]
-v Verbose output [no output]
-w Import weakly declared functions, i.e., weakly
declared functions are expected to be provided at
load-time [not imported]
</pre></ul>
<a name="ldnxflat"><h2>1.3 ldnxflat</h2></a>
<p>
<code>ldnxflat</code> is use to link your object files along with the <i>thunk</i> file
generated by <a href="#mknxflat"><code>mknxflat</code></a> to produce the NXFLAT binary module.
See <a href="#making">below</a> for usage.
</p>
<ul><pre>
Usage: ldnxflat [options] &lt;bfd-filename&gt;
Where options are one or more of the following. Note
that a space is always required between the option and
any following arguments.
-d Use dynamic symbol table [Default: symtab]
-e &lt;entry-point&gt;
Entry point to module [Default: _start]
-o &lt;out-filename&gt;
Output to &lt;out-filename&gt; [Default: &lt;bfd-filename&gt;.nxf]
-s &lt;stack-size&gt;
Set stack size to &lt;stack-size&gt; [Default: 4096]
-v Verbose output. If -v is applied twice, additional
debug output is enabled [Default: no verbose output].
</pre></ul>
<a name="mksymtab"><h2>1.4 mksymtab</h2></a>
<p>
There is a small helper program available in <code>nuttx/tools</code> call <code>mksymtab</code>.
<code>mksymtab</code> can be sued to generate symbol tables for the NuttX base code that would be usable by the typical NXFLAT application.
<code>mksymtab</code> builds symbol tables from common-separated value (CSV) files.
In particular, the CSV files:
</p>
<ol>
<li>
<code>nuttx/syscall/syscall.csv</code> that describes the NuttX RTOS interface, and
</li>
<li>
<code>nuttx/libc/libc.csv</code> that describes the NuttX C library interface.
</li>
<li>
<code>nuttx/libc/math.cvs</code> that descirbes any math library.
</li>
</ol>
<ul><pre>
USAGE: ./mksymtab &lt;cvs-file&gt; &lt;symtab-file&gt;
Where:
&lt;cvs-file&gt; : The path to the input CSV file
&lt;symtab-file&gt;: The path to the output symbol table file
-d : Enable debug output
</pre></ul>
<p>
For example,
</p>
<ul><pre>
cd nuttx/tools
cat ../syscall/syscall.csv ../libc/libc.csv | sort >tmp.csv
./mksymtab.exe tmp.csv tmp.c
</pre></ul>
<a name="making"><h2>1.5 Making an NXFLAT module</h2></a>
<p>
Below is a snippet from an NXFLAT make file (simplified from NuttX
<a href="https://bitbucket.org/nuttx/apps/src/master/apps/examples/nxflat/tests/hello/Makefile" target="_blank">
Hello, World!</a> example.
<p>
<ul><table width="50%">
<ul><table>
<tr>
<th>Target 1</th>
<td><code>hello.r1:</code></td>
<td><code>hello.o</code></td>
</tr>
<tr>
<td><br></td>
<td><br></td>
<td><code>abc-nuttx-elf-ld -r -d -warn-common -o $@ $^</code></td>
</tr>
<tr>
<th>Target 2</th>
<td><code>hello-thunk.S:</code></td>
<td><code>hello.r1</code></td>
</tr>
<tr>
<td><br></td>
<td><br></td>
<td><code>mknxflat -o $@ $^</code></td>
</tr>
<tr>
<th>Target 3</th>
<td><code>hello.r2:</code></td>
<td><code>hello-thunk.S</code></td>
</tr>
<tr>
<td><br></td>
<td><br></td>
<td>
<code>abc-nuttx-elf-ld -r -d -warn-common -T binfmt/libnxflat/gnu-nxflat-gotoff.ld -no-check-sections -o $@ hello.o hello-thunk.o</code>
</td>
</tr>
<tr>
<th>Target 4</th>
<td><code>hello:</code></td>
<td><code>hello.r2</code></td>
</tr>
<tr>
<td><br></td>
<td><br></td>
<td><code>ldnxflat -e main -s 2048 -o $@ $^</code></td>
</tr>
<tr>
</table></ul>
<p><b>Target 1</b>.
This target links all of the module's object files together into one relocatable object.
Two relocatable objects will be generated; this is the first one (hence, the suffic <code>.r1</code>).
In this &quot;Hello, World!&quot; case, there is only a single object file, <code>hello.o</code>,
that is linked to produce the <code>hello.r1</code> object.
</p>
<p>
When the module's object files are compiled, some special compiler CFLAGS must be provided.
First, the option <code>-fpic</code> is required to tell the compiler to generate position independent code (other
GCC options, like <code>-fno-jump-tables</code> might also be desirable).
For ARM compilers, two additional compilation options are required: <code>-msingle-pic-base</code>
and <code>-mpic-register=r10</code>.
</p>
<p><b>Target 2</b>.
Given the <code>hello.r1</code> relocatable object, this target will invoke
<a href="#mknxflat"><code>mknxflat</code></a>
to make the <i>thunk</i> file, <code>hello-thunk.S</code>.
This <i>thunk</i> file contains all of the information needed to create the imported function list.
</p>
<p><b>Target 3</b>
This target is similar to <b>Target 1</b>.
In this case, it will link together the module's object files (only <code>hello.o</code> here)
along with the assembled <i>thunk</i> file, <code>hello-thunk.o</code> to create the second relocatable object,
<code>hello.r2</code>.
The linker script, <code>gnu-nxflat-gotoff.ld</code> is required at this point to correctly position the sections.
This linker script produces two segments:
An <i>I-Space</i> (Instruction Space) segment containing mostly <code>.text</code> and a <i>D-Space</i> (Data Space) segment
containing <code>.got</code>, <code>.data</code>, and <code>.bss</code> sections.
The I-Space section must be origined at address 0 (so that the segment's addresses are really offsets into
the I-Space segment)
and the D-Space section must also be origined at address 0 (so that segment's addresses are really offsets into
the I-Space segment).
The option <code>-no-check-sections</code> is required to prevent the linker from failing because these segments overlap.
</p>
<p><b>NOTE:</b>
There are two linker scripts located at <code>binfmt/libnxflat/</code>.
</p>
<ol>
<li>
<b><code>binfmt/libnxflat/gnu-nxflat-gotoff.ld</code></b>.
Older versions of GCC (at least up to GCC 4.3.3), use GOT-relative addressing to access RO data.
In that case, read-only data (.rodata) must reside in D-Space and this linker script should be used.
</li>
<li>
<b><code>binfmt/libnxflat/gnu-nxflat-pcrel.ld</code></b>.
Newer versions of GCC (at least as of GCC 4.6.3), use PC-relative addressing to access RO data.
In that case, read-only data (.rodata) must reside in I-Space and this linker script should be used.
</li>
</ol>
<p><b>Target 4</b>.
Finally, this target will use the <code>hello.r2</code> relocatable object to create the final, NXFLAT module
<code>hello</code> by executing <a href="#ldnxflat"><code>ldnxflat</code></a>.
</p>
<table width ="100%">
<tr bgcolor="#e4e4e4">
<td>
<a name="binfmt"><h1>3.0 Binary Loader APIs</h1></a>
</td>
</tr>
</table>
<p><b>Relevant Header Files:</b></p>
<ul>
<li>
The interface to the binary loader is described in the header file
<a href="https://bitbucket.org/nuttx/nuttx/src/master/include/nuttx/binfmt/binfmt.h" target="_blank">
<code>include/nuttx/binfmt/binfmt.h</code></a>.
A brief summary of the APIs prototyped in that header file are listed below.
</li>
<li>
NXFLAT APIs needed to register NXFLAT as a binary loader appear in the header file
<a href="https://bitbucket.org/nuttx/nuttx/src/master/include/nuttx/binfmt/nxflat.h" target="_blank">
<code>include/nuttx/binfmt/nxflat.h</code></a>.
</li>
<li>
The format of an NXFLAT object itself is described in the header file:
<a href="https://bitbucket.org/nuttx/nuttx/src/master/include/nuttx/binfmt/nxflat.h" target="_blank">
<code>include/nuttx/binfmt/nxflat.h</code></a>.
</li>
</ul>
<p><b>binfmt Registration</b>
These first interfaces are used only by a binary loader module, such as NXFLAT itself.
NXFLAT (or any future binary loader) calls <code>register_binfmt()</code> to incorporate
itself into the system.
In this way, the binary loader logic is dynamically extensible to support any kind of loader.
Normal application code should not be concerned with these interfaces.
</p>
<ul>
<p><b><code>int register_binfmt(FAR struct binfmt_s *binfmt)</code></b>
<ul>
<p><b>Description:</b>
Register a loader for a binary format
</p>
<p><b>Returned Value:</b>
This is a NuttX internal function so it follows the convention that
0 (<code>OK</code>) is returned on success and a negated errno is returned on
failure.
</p>
</ul>
<p><b><code>int unregister_binfmt(FAR struct binfmt_s *binfmt)</code></b>
<ul>
<p><b>Description:</b>
Register a loader for a binary format
</p>
<p><b>Returned Value:</b>
This is a NuttX internal function so it follows the convention that
0 (<code>OK</code>) is returned on success and a negated errno is returned on
failure.
</p>
</ul>
</ul>
<p><b>Binary Loader Interfaces</b>.
The remaining APIs are called by user applications to maintain modules in the file system.
</p>
<ul>
<p><b><code>int load_module(FAR struct binary_s *bin)</code></b>
<ul>
<p><b>Description:</b>
Load a module into memory, bind it to an exported symbol take, and
prep the module for execution.
</p>
<p><b>Returned Value:</b>
This is a NuttX internal function so it follows the convention that 0 (<code>OK</code>) is returned on success and a negated <code>errno</code> is returned on failure.
</p>
</ul>
<p><b><code>int unload_module(FAR struct binary_s *bin)</code></b>
<ul>
<p><b>Description:</b>
Unload a (non-executing) module from memory. If the module has
been started (via <code>exec_module()</code>), calling this will be fatal.
</p>
<p><b>Returned Value:</b>
This is a NuttX internal function so it follows the convention that 0 (<code>OK</code>) is returned on success and a negated <code>errno</code> is returned on failure.
</p>
</ul>
<p><b><code>int exec_module(FAR const struct binary_s *bin)</code></b>
<ul>
<p><b>Description:</b>
Execute a module that has been loaded into memory by load_module().
</p>
<p><b>Returned Value:</b>
This is a NuttX internal function so it follows the convention that 0 (<code>OK</code>) is returned on success and a negated <code>errno</code> is returned on failure.
</p>
</ul>
</ul>
<table width ="100%">
<tr bgcolor="#e4e4e4">
<td>
<a name="nogot"><h1>Appendix A. No GOT Operation</h1></a>
</td>
</tr>
</table>
<p>
When GCC generate position independent code, new code sections will appear in your programs.
One of these is the GOT (Global Offset Table) and, in ELF environments, another is the PLT (Procedure
Lookup Table.
For example, if your C code generated (ARM) assembly language like this without PIC:
<p>
<ul><pre>
ldr r1, .L0 <-- Fetch the offset to 'x'
ldr r0, [r10, r1] <-- Load the value of 'x' with PIC offset`
...
.L0: .word x <-- Offset to 'x'
</pre></ul>
<p>
Then when PIC is enabled (say with the -fpic compiler option), it will generate code like
this:
</p>
<ul><pre>
ldr r1, .L0 <-- Fetch the offset to the GOT entry
ldr r1, [r10,r1] <-- Fetch the (relocated) address of 'x' from the GOT
ldr r0, [r1, #0] <-- Fetch the value of 'x'
...
.L1 .word x(GOT) <-- Offset to entry in the GOT
</pre></ul>
<p>See <a href="http://xflat.sourceforge.net/NoMMUSharedLibs.html#shlibsgot">reference</a></p>
<p>
Notice that the generates an extra level of indirection through the GOT.
This indirection is not needed by NXFLAT and only adds more RAM usage and
execution time.
</p>
<p>
NXFLAT (like <a href="http://xflat.sourceforge.net/">XFLAT</a>) can work even better without
the GOT.
Patches against older version of GCC exist to eliminate the GOT indirections.
Several are available <a href="http://xflat.cvs.sourceforge.net/viewvc/xflat/xflat/gcc/">here</a>
if you are inspired to port them to a new GCC version.
</p>
<table width ="100%">
<tr bgcolor="#e4e4e4">
<td>
<a name="pictext"><h1>Appendix B. PIC Text Workaround</h1></a>
</td>
</tr>
</table>
<p>
There is a problem with the memory model in GCC that prevents it from
being used as you need to use it in the NXFLAT context.
The problem is that GCC PIC model assumes that the executable lies in a flat, contiguous (virtual) address space like:
<p>
<ul><table width="15%">
<tr><th>Virtual</th></td>
<tr>
<td align="center" bgcolor="#e4e4e4"><code>.text</code></td>
</tr>
<tr>
<td align="center" bgcolor="#e4e4e4"><code>.got</code></td>
</tr>
<tr>
<td align="center" bgcolor="#e4e4e4"><code>.data</code></td>
</tr>
<tr>
<td align="center" bgcolor="#e4e4e4"><code>.bss</code></td>
</tr>
</table></ul>
<p>
It assumes that the PIC base register (usually r10 for ARM) points to the base of <code>.text</code>
so that any address in <code>.text</code>, <code>.got</code>, <code>.data</code>, <code>.bss</code>
can be found with an offset from the same base address.
But that is not the memory arrangement that we need in the XIP embedded environment.
We need two memory regions, one in FLASH containing shared code and on per task in RAM containing task-specific data:
</p>
<ul><table width="30%">
<tr><th>Flash</th><th>RAM</th></td>
<tr>
<td align="center" bgcolor="#e4e4e4"><code>.text</code></td>
<td align="center" bgcolor="#e4e4e4"><code>.got</code></td>
</tr>
<tr>
<td bgcolor="#e4e4e4"><br></td>
<td align="center" bgcolor="#e4e4e4"><code>.data</code></td>
</tr>
<tr>
<td bgcolor="#e4e4e4"><br></td>
<td align="center" bgcolor="#e4e4e4"><code>.bss</code></td>
</tr>
</table></ul>
<p>
The PIC base register needs to point to the base of the <code>.got</code> and only
addresses in the <code>.got</code>, <code>.data</code>, and <code>.bss</code>
sections can be accessed as an offset from the PIC base register.
See also this
<a href="http://xflat.cvs.sourceforge.net/viewvc/*checkout*/xflat/xflat/gcc/README?revision=1.1.1.1">XFLAT discussion</a>.
</p>
<p>
Patches against older version of GCC exist to correct this GCC behavior.
Several are available <a href="http://xflat.cvs.sourceforge.net/viewvc/xflat/xflat/gcc/">here</a>
if you are inspired to port them to a new GCC version.
</p>
</body>
</html>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,76 +0,0 @@
<html>
<head>
<title>NxWidgets</title>
<link rel="stylesheet" href="style.css">
</head>
<body background="backgd.gif">
<hr><hr>
<table width ="100%">
<tr align="center" bgcolor="#e4e4e4">
<td>
<h1><big><font color="#3c34ec"><i>NxWidgets</i></font></big></h1>
<p>Last Updated: November 7, 2017</p>
</td>
</tr>
</table>
<h1>NxWidgets</h1>
<p>
In order to better support NuttX based platforms, a special graphical userinterface has been created called NXWidgets.
NXWidgets is written in C++ and integrates seamlessly with the NuttX <a href="NXGraphicsSubsystem.html">NX graphics subsystem</a> in order to provide graphic objects, or &quot;widgets,&quot; in the NX Graphics Subsystem
</p>
<p>
Some of the features of NXWidgets include:
</p>
<ul>
<li><b>Conservative C++</b>.
NXWidgets is written entirely in C++ but using only selected &quot;embedded friendly&quot; C++ constructs that are fully supported under NuttX.
No additional C++ support libraries are required.
</li>
<li><b>NX Integration</b>.
NXWidgets integrate seamlessly with the <a href="NXGraphicsSubsystem.html">NX graphics subsystem</a>.
Think of the X server under Linux … the NX graphics system is like a tiny X server that provides windowing under NuttX.
By adding NXWidgets, you can support graphics objects like buttons and text boxes in the NX windows and toolbars.
</li>
<li><b>Small Footprint</b>.
NXWidgets is tailored for use MCUs in embedded applications.
It is ideally suited for mid- and upper-range of most MCU families.
A complete NXWidgets is possible in as little as 40K of FLASH and maybe 4K of SRAM.
</li>
<li><b>Output Devices</b>.
NXWidgets will work on the high-end frame buffer devices as well as on LCDs connected via serial or parallel ports to a small MCU.
</li>
<li><b>Input Devices</b>.
NXWidgets will accept position and selection inputs from a mouse or a touchscreen.
It will also support character input from a keyboard such as a USB keyboard.
NXWidgets supports on very special widget called CKeypad that will provide keyboard input via an on-screen keypad that can be operated via mouse or touchscreen inputs.
</li>
<li><b>Many Graphic Objects</b>.
Some of the graphic objects supported by NXWidgets include labels, buttons, text boxes, button arrays, check boxes, cycle buttons, images, sliders, scrollable list boxes, progress bars, and more.
</li>
<li><b>DOxygen Documentation</b>
DOxygen documentation is available.
</li>
</ul>
<p>
Note: Many of the fundamental classed in NxWidgets derive from the Antony
Dzeryn's &quot;Woopsi&quot; project: http://woopsi.org/ which also has a BSD style
license. See the COPYING file for details.
</p>
<h1>NXWidgets DOxygen Documentation</h1>
<p>
Release notes, DOxygen documentation, as well as downloads for the latest NxWidgets releases are available online:
</p>
<ul>
<li>
<b>NxWidgets-1.19</b>:
<a href="http://nuttx.org/nxwidgets_v1_19/html/index.html">Documentation</a>,
<a href="http://sourceforge.net/projects/nuttx/files/NxWidgets/NxWidgets-1.19/">Release notes</a>, and
<a href="http://sourceforge.net/projects/nuttx/files/NxWidgets/NxWidgets-1.19/">Downloads</a>
</li>
</p>
<p>
Thanks go to Jose Pablo Carballo for contributing this!
</p>
</p>
</body>
</html>

View File

@ -1,453 +0,0 @@
<html>
<head>
<title>NuttX USB Trace Capability</title>
<link rel="stylesheet" href="style.css">
</head>
<body background="backgd.gif">
<hr><hr>
<table width ="100%">
<tr align="center" bgcolor="#e4e4e4">
<td>
<h1><big><font color="#3c34ec"><i>NuttX USB Device Trace</i></font></big></h1>
<p>Last Updated: March 20, 2011</p>
</td>
</tr>
</table>
<hr><hr>
<p><b>USB Device Tracing Controls</b>.
The NuttX USB device subsystem supports a fairly sophisticated tracing facility.
The basic trace cabability is controlled by these NuttX configuration settings:
</p>
<ul>
<li><code>CONFIG_USBDEV_TRACE</code>: Enables USB tracing</li>
<li><code>CONFIG_USBDEV_TRACE_NRECORDS</code>: Number of trace entries to remember</li>
</ul>
<p><b>Trace IDs</b>.
The trace facility works like this:
When enabled, USB events that occur in either the USB device driver or in the USB class driver are logged.
These events are described in <code>include/nuttx/usb/usbdev_trace.h</code>.
The logged events are identified by a set of event IDs:
</p>
<ul><table>
<tr>
<td><code>TRACE_INIT_ID</code></td>
<td>Initialization events</td>
</tr>
<tr>
<td><code>TRACE_EP_ID</code></td>
<td>Endpoint API calls</td>
</tr>
<tr>
<td><code>TRACE_DEV_ID</code></td>
<td>USB device API calls</td>
</tr>
<tr>
<td><code>TRACE_CLASS_ID</code></td>
<td>USB class driver API calls</td>
</tr>
<tr>
<td><code>TRACE_CLASSAPI_ID</code></td>
<td>Other class driver system API calls</td>
</tr>
<tr>
<td><code>TRACE_CLASSSTATE_ID</code></td>
<td>Track class driver state changes</td>
</tr>
<tr>
<td><code>TRACE_INTENTRY_ID</code></td>
<td>Interrupt handler entry</td>
</tr>
<tr>
<td><code>TRACE_INTDECODE_ID</code></td>
<td>Decoded interrupt event</td>
</tr>
<tr>
<td><code>TRACE_INTEXIT_ID</code></td>
<td>Interrupt handler exit</td>
</tr>
<tr>
<td><code>TRACE_OUTREQQUEUED_ID</code></td>
<td>Request queued for OUT endpoint</td>
</tr>
<tr>
<td><code>TRACE_INREQQUEUED_ID</code></td>
<td>Request queued for IN endpoint</td>
</tr>
<tr>
<td><code>TRACE_READ_ID</code></td>
<td>Read (OUT) action</td>
</tr>
<tr>
<td><code>TRACE_WRITE_ID</code></td>
<td>Write (IN) action</td>
</tr>
<tr>
<td><code>TRACE_COMPLETE_ID</code></td>
<td>Request completed</td>
</tr>
<tr>
<td><code>TRACE_DEVERROR_ID</code></td>
<td>USB controller driver error event</td>
</tr>
<tr>
<td><code>TRACE_CLSERROR_ID</code></td>
<td>USB class driver error event</td>
</tr>
</table></ul>
<p><b>Logged Events</b>.
Each logged event is 32-bits in size and includes
</p>
<ol>
<li>8-bits of the trace ID (values associated with the above)</li>
<li>8-bits of additional trace ID data, and</li>
<li>16-bits of additional data.</li>
</ol>
<p><b>8-bit Trace Data</b>
The 8-bit trace data depends on the specific event ID. As examples,
</p>
<ul>
<li>
For the USB serial and mass storage class, the 8-bit event data is provided in <code>include/nuttx/usb/usbdev_trace.h</code>.
</li>
<li>
For the USB device driver, that 8-bit event data is provided within the USB device driver itself.
So, for example, the 8-bit event data for the LPC1768 USB device driver is found in <code>arch/arm/src/lpc17xx_40xx/lpc17_40_usbdev.c</code>.
</li>
</ul>
<p><b>16-bit Trace Data</b>.
The 16-bit trace data provided additional context data relevant to the specific logged event.
</p>
<p><b>Trace Control Interfaces</b>.
Logging of each of these kinds events can be enabled or disabled using the interfaces described in <code>include/nuttx/usb/usbdev_trace.h</code>.
</p>
<p><b>Enabling USB Device Tracing</b>.
USB device tracing will be configured if <code>CONFIG_USBDEV</code> and either of the following are set in the NuttX configuration file:
</p>
<ul>
<li><code>CONFIG_USBDEV_TRACE</code>, or</li>
<li><code>CONFIG_DEBUG_FEATURES and CONFIG_DEBUG_USB</code></li>
</ul>
<p><b>Log Data Sink</b>.
The logged data itself may go to either (1) an internal circular buffer, or (2) may be provided on the console.
If <code>CONFIG_USBDEV_TRACE</code> is defined, then the trace data will go to the circular buffer.
The size of the circular buffer is determined by <code>CONFIG_USBDEV_TRACE_NRECORDS</code>.
Otherwise, the trace data goes to console.
<p>
<p><b>Example</b>.
Here is an example of USB trace output using <code>apps/examples/usbserial</code> for an LPC1768 platform with the following NuttX configuration settings:
</p>
<ul>
<li><code>CONFIG_DEBUG_FEATURES</code>, <code>CONFIG_DEBUG_INFO</code>, <code>CONFIG_USB</code>
<li><code>CONFIG_EXAMPLES_USBSERIAL_TRACEINIT</code>, <code>CONFIG_EXAMPLES_USBSERIAL_TRACECLASS</code>,
<code>CONFIG_EXAMPLES_USBSERIAL_TRACETRANSFERS</code>, <code>CONFIG_EXAMPLES_USBSERIAL_TRACECONTROLLER</code>,
<code>CONFIG_EXAMPLES_USBSERIAL_TRACEINTERRUPTS</code>
</ul>
<p>Console Output:</p>
<ul><table>
<tr>
<td align="center">&nbsp;</td>
<td align="left"><code>ABDE</code></td>
</tr>
<tr>
<td align="center">&nbsp;</td>
<td align="left"><code>usbserial_main: Registering USB serial driver</code></td>
</tr>
<tr>
<td align="center">&nbsp;</td>
<td align="left"><code>uart_register: Registering /dev/ttyUSB0</code></td>
</tr>
<tr>
<td align="center">&nbsp;</td>
<td align="left"><code>usbserial_main: Successfully registered the serial driver</code></td>
</tr>
<tr>
<td align="center">1</td>
<td align="left"><code>Class API call 1: 0000</code></td>
</tr>
<tr>
<td align="center">2</td>
<td align="left"><code>Class error: 19:0000</code></td>
</tr>
<tr>
<td align="center">&nbsp;</td>
<td align="left"><code>usbserial_main: ERROR: Failed to open /dev/ttyUSB0 for reading: 107</code></td>
</tr>
<tr>
<td align="center">&nbsp;</td>
<td align="left"><code>usbserial_main: Not connected. Wait and try again.</code></td>
</tr>
<tr>
<td align="center">3</td>
<td align="left"><code>Interrupt 1 entry: 0039</code></td>
</tr>
<tr>
<td align="center">4</td>
<td align="left"><code>Interrupt decode 7: 0019</code></td>
</tr>
<tr>
<td align="center">5</td>
<td align="left"><code>Interrupt decode 32: 0019</code></td>
</tr>
<tr>
<td align="center">6</td>
<td align="left"><code>Interrupt decode 6: 0019</code></td>
</tr>
<tr>
<td align="center">7</td>
<td align="left"><code>Class disconnect(): 0000</code></td>
</tr>
<tr>
<td align="center">8</td>
<td align="left"><code>Device pullup(): 0001</code></td>
</tr>
<tr>
<td align="center">9</td>
<td align="left"><code>Interrupt 1 exit: 0000</code></td>
</tr>
</table></ul>
<p>
The numbered items are USB USB trace output.
You can look in the file <code>drivers/usbdev/usbdev_trprintf.c</code> to see examctly how each output line is formatted.
Here is how each line should be interpreted:
</p>
<ul><table>
<tr>
<th align="center">&nbsp</th>
<td align="left">USB EVENT ID</td>
<td align="right">8-bit<br>EVENT<br>DATA</td>
<td align="left">MEANING</td>
<td align="left">16-bit<br>EVENT<br>DATA</td>
</tr>
<tr>
<td align="center">1</td>
<td align="left"><code>TRACE_CLASSAPI_ID</code><sup>1</sup></td>
<td align="right">1</td>
<td align="left"><code>USBSER_TRACECLASSAPI_SETUP</code><sup>1</sup></td>
<td align="left">0000</td>
</tr>
<tr>
<td align="center">2</td>
<td align="left"><code>TRACE_CLSERROR_ID</code><sup>1</sup></td>
<td align="right">19</td>
<td align="left"><code>USBSER_TRACEERR_SETUPNOTCONNECTED</code><sup>1</sup></td>
<td align="left">0000</td>
</tr>
<tr>
<td align="center">3</td>
<td align="left"><code>TRACE_INTENTRY_ID</code><sup>1</sup></td>
<td align="right">1</td>
<td align="left"><code>LPC17_40_TRACEINTID_USB</code><sup>2</sup></td>
<td align="left">0039</td>
</tr>
<tr>
<td align="center">4</td>
<td align="left"><code>TRACE_INTDECODE_ID</code><sup>2</sup></td>
<td align="right">7</td>
<td align="left"><code>LPC17_40_TRACEINTID_DEVSTAT</code><sup>2</sup></td>
<td align="left">0019</td>
</tr>
<tr>
<td align="center">5</td>
<td align="left"><code>TRACE_INTDECODE_ID</code><sup>2</sup></td>
<td align="right">32</td>
<td align="left"><code>LPC17_40_TRACEINTID_SUSPENDCHG</code><sup>2</sup></td>
<td align="left">0019</td>
</tr>
<tr>
<td align="center">6</td>
<td align="left"><code>TRACE_INTDECODE_ID</code><sup>2</sup></td>
<td align="right">6</td>
<td align="left"><code>LPC17_40_TRACEINTID_DEVRESET</code><sup>2</sup></td>
<td align="left">0019</td>
</tr>
<tr>
<td align="center">7</td>
<td align="left"><code>TRACE_CLASS_ID</code><sup>1</sup></td>
<td align="right">3</td>
<td align="left"><code>(See TRACE_CLASSDISCONNECT</code><sup>1</sup>)</td>
<td align="left">0000</td>
</tr>
<tr>
<td align="center">8</td>
<td align="left"><code>TRACE_DEV_ID</code><sup>1</sup></td>
<td align="right">6</td>
<td align="left"><code>(See TRACE_DEVPULLUP</code><sup>1</sup>)</td>
<td align="left">0001</td>
</tr>
<tr>
<td align="center">9</td>
<td align="left"><code>TRACE_INTEXIT_ID</code><sup>1</sup></td>
<td align="right">1</td>
<td align="left"><code>LPC17_40_TRACEINTID_USB</code><sup>2</sup></td>
<td align="left">0000</td>
</tr>
</table>
<p><small><b>NOTES</b>:<br>
<sup>1</sup>See <code>include/nuttx/usb/usbdev_trace.h</code><br>
<sup>2</sup><code>See arch/arm/src/lpc17xx_40xx/lpc17_40_usbdev.c</code>
</small></p>
</ul>
<p>
In the above example you can see that:
</p>
<ul>
<li><b>1</b>.
The serial class USB setup method was called for the USB serial class.
This is the corresponds to the following logic in <code>drivers/usbdev/pl2303.c</code>:
<ul><pre>
static int pl2303_setup(FAR struct uart_dev_s *dev)
{
...
usbtrace(PL2303_CLASSAPI_SETUP, 0);
...
</pre></ul>
</li>
<li><b>2</b>.
An error occurred while processing the setup command because no configuration has yet been selected by the host.
This corresponds to the following logic in <code>drivers/usbdev/pl2303.c</code>:
<ul><pre>
static int pl2303_setup(FAR struct uart_dev_s *dev)
{
...
/* Check if we have been configured */
if (priv->config == PL2303_CONFIGIDNONE)
{
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_SETUPNOTCONNECTED), 0);
return -ENOTCONN;
}
...
</pre></ul>
<li><b>3-6</b>.
Here is a USB interrupt that suspends and resets the device.
</li>
<li><b>7-8</b>.
During the interrupt processing the serial class is disconnected
</li>
<li><b>9</b>.
And the interrupt returns
</li>
</ul>
<p><b>USB Monitor</b>.
The <i>USB monitor</i> is an application in the <code>apps/system/usbmonitor</code> that provides a convenient way to get debug trace output.
If tracing is enabled, the USB device will save encoded trace output in in-memory buffer;
if the USB monitor is also enabled, that trace buffer will be periodically emptied and dumped to the
system logging device (the serial console in most configurations).
The following are some of the relevant configuration options:
</p>
<ul>
<table width="100%">
<tr>
<td colspan="2" align="left" valign="top" bgcolor="#e4e4e4">
<i>Device Drivers -&gt; USB Device Driver Support</i>
</td>
</tr>
<tr>
<td width="30%" align="left" valign="top">
<code>CONFIG_USBDEV_TRACE=y</code>
</td>
<td align="left" valign="top">
Enable USB trace feature
</td>
</tr>
<tr>
<td width="30%" align="left" valign="top">
<code>CONFIG_USBDEV_TRACE_NRECORDS=<i>nnnn</i></code>
</td>
<td align="left" valign="top">
Buffer <i>nnnn</i> records in memory.
If you lose trace data, then you will need to increase the size of this buffer
(or increase the rate at which the trace buffer is emptied).
</td>
</tr>
<td width="30%" align="left" valign="top">
<code>CONFIG_USBDEV_TRACE_STRINGS=y</code>
</td>
<td align="left" valign="top">
Optionally, convert trace ID numbers to strings.
This feature may not be supported by all drivers.
</td>
<tr>
<td colspan="2" align="left" valign="top" bgcolor="#e4e4e4">
<i>Application Configuration -&gt; NSH LIbrary</i>
</td>
</tr>
<tr>
<td width="30%" align="left" valign="top">
<code>CONFIG_NSH_USBDEV_TRACE=n</code>
</td>
<td align="left" valign="top">
Make sure that any built-in tracing from NSH is disabled.
</td>
</tr>
<tr>
<td width="30%" align="left" valign="top">
<code>CONFIG_NSH_ARCHINIT=y</code>
</td>
<td align="left" valign="top">
Enable this option <i>only</i> if your board-specific logic has logic to automatically start the USB monitor.
Otherwise the USB monitor can be started or stopped with the <code>usbmon_start</code> and <code>usbmon_stop</code> commands from the NSH console.
</td>
</tr>
<tr>
<td colspan="2" align="left" valign="top" bgcolor="#e4e4e4">
<i>Application Configuration -&gt; System NSH Add-Ons</i>
</td>
</tr>
<tr>
<td width="30%" align="left" valign="top">
<code>CONFIG_USBMONITOR=y</code>
</td>
<td align="left" valign="top">
Enable the USB monitor daemon
</td>
</tr>
<tr>
<td width="30%" align="left" valign="top">
<code>CONFIG_USBMONITOR_STACKSIZE=<i>nnnn</i></code>
</td>
<td align="left" valign="top">
Sets the USB monitor daemon stack size to <i>nnnn</i>.
The default is 2KiB.
</td>
</tr>
<tr>
<td width="30%" align="left" valign="top">
<code>CONFIG_USBMONITOR_PRIORITY=50</code>
</td>
<td align="left" valign="top">
Sets the USB monitor daemon priority to <i>nnnn</i>.
This priority should be low so that it does not interfere with other operations, but not so low that you cannot dump the buffered USB data sufficiently rapidly.
The default is 50.
</td>
</tr>
<tr>
<td width="30%" align="left" valign="top">
<code>CONFIG_USBMONITOR_INTERVAL=<i>nnnn</i></code>
</td>
<td align="left" valign="top">
Dump the buffered USB data every <i>nnnn</i> seconds.
If you lose buffered USB trace data, then dropping this value will help by increasing the rate at which the USB trace buffer is emptied.
</td>
</tr>
<tr>
<td width="30%" align="left" valign="top">
<code>CONFIG_USBMONITOR_TRACEINIT=y</code><br>
<code>CONFIG_USBMONITOR_TRACECLASS=y</code><br>
<code>CONFIG_USBMONITOR_TRACETRANSFERS=y</code><br>
<code>CONFIG_USBMONITOR_TRACECONTROLLER=y</code><br>
<code>CONFIG_USBMONITOR_TRACEINTERRUPTS=y</code><br>
</td>
<td align="left" valign="top">
Selects which USB event(s) that you want to be traced.
</td>
</tr>
</table>
</ul>
<p>
NOTE: If USB debug output is also enabled, both outputs will appear on the serial console.
However, the debug output will be asynchronous with the trace output and, hence, difficult to interpret.
</p>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -1,84 +0,0 @@
body
{
background: none;
font-family: sans-serif;
height: 100%;
}
a
{
color: #dd2f2f;
text-decoration: none;
}
a:hover
{
text-decoration: underline;
}
code
{
font-family: "courier";
color: #2b4893;
background: #f4f4f4;
padding-left: 0.25em;
padding-right: 0.25em;
}
pre
{
font-family: "courier";
background: #f4f4f4;
padding: 1em;
}
.container
{
overflow-x: hidden;
}
.toc
{
top: 0;
left: 0;
float: left;
width: 22%;
font-size: 80%;
overflow-y: scroll;
height: 100%;
position: fixed;
}
.toc tbody
{
font-size: 80%;
}
.toc .toc_table
{
margin-left: 1em;
}
.toc ul
{
padding-left: 1.5em;
}
.toc > ul
{
padding-left: 1.0em;
}
.toc h1
{
padding-left: 0.5em;
padding-top: 0.5em;
}
.main
{
padding-left: 1em;
padding-right: 1em;
width: 75%;
float: right;
}

View File

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB