diff options
-rw-r--r-- | nuttx/ChangeLog | 10 | ||||
-rw-r--r-- | nuttx/Documentation/NuttShell.html | 8 | ||||
-rw-r--r-- | nuttx/Documentation/NuttX.html | 14 | ||||
-rw-r--r-- | nuttx/Documentation/NuttXDemandPaging.html | 1350 | ||||
-rw-r--r-- | nuttx/Documentation/NuttxPortingGuide.html | 4 | ||||
-rwxr-xr-x | nuttx/Documentation/NxWidgets.html | 2 | ||||
-rw-r--r-- | nuttx/ReleaseNotes | 14 | ||||
-rw-r--r-- | nuttx/TODO | 2 | ||||
-rw-r--r-- | nuttx/arch/arm/src/lpc43xx/lpc43_usb0dev.c | 4 | ||||
-rw-r--r-- | nuttx/arch/arm/src/lpc43xx/lpc43_usb0dev.h | 98 |
10 files changed, 801 insertions, 705 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index 614381c90..107a426d6 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -816,7 +816,7 @@ and (2) it requires symbol table arguments. * lib/: Add fileno() * examples/ostest: Several of the tests used a big, hard-coded stack size - when creating test threads (16Kb stacksize). The stack size should + when creating test threads (16K stacksize). The stack size should be controlled by the .config file or the OSTest won't work on platforms with memory constraints. * netutils/thttpd: An initial port of Jeff Poskanzer's THTTPD HTTP server. @@ -1369,10 +1369,10 @@ out instead. This improves behavior, for example, on the first GET request from a browser. * arch/arm/src/lpc17xx/lpc17_emacram.h and lpc17_allocateheap.c: The Ethernet - logic was using all of AHB SRAM Bank0 for Ethernet packet buffers (16Kb). An + logic was using all of AHB SRAM Bank0 for Ethernet packet buffers (16K). An option was added to limit the amount of SRAM used for packet buffering and to re-use any extra Bank0 memory for heap. configs/olimex-lpc1766stk/nettest - now uses only 8Kb at the beginning of Bank0; the 8Kb at the end of Bank0 is + now uses only 8K at the beginning of Bank0; the 8K at the end of Bank0 is included in the heap * arch/arm/src/lpc17xx/lpc17_ssp.c: Fix compilation errors when SSP1 is selected. @@ -1785,7 +1785,7 @@ that support 16-bit addressability have smaller overhead than devices that support 32-bit addressability. However, there are many MCUs that support 32-bit addressability *but* have internal SRAM of size - less than or equal to 64Kb. In this case, CONFIG_MM_SMALL can be + less than or equal to 64K. In this case, CONFIG_MM_SMALL can be defined so that those MCUs will also benefit from the smaller, 16- bit-based allocation overhead. * lib/string/lib_strndup.c: Add standard strndup() library function. @@ -1846,7 +1846,7 @@ * arch/sim/src/up_romgetc.c: Used to test the basic logic to access strings without directly de-referencing a string pointer. * arch/avr/src/avr/up_romget.c: Used to access strings that lie in the first - 64Kb of FLASH (But I still haven't figured out how to get strings to reside in + 64K of FLASH (But I still haven't figured out how to get strings to reside in FLASH without using the PROGMEM attribute). * configs/teensy/src/up_spi.c: Correct reading of SD CD and WP pins (was reading the wrong register. AVR SPI now appears to be functional. diff --git a/nuttx/Documentation/NuttShell.html b/nuttx/Documentation/NuttShell.html index a92cbadd8..ca7e82627 100644 --- a/nuttx/Documentation/NuttShell.html +++ b/nuttx/Documentation/NuttShell.html @@ -8,7 +8,7 @@ <tr align="center" bgcolor="#e4e4e4"> <td> <h1><big><font color="#3c34ec"><i>NuttShell (NSH)</i></font></big></h1> - <p>Last Updated: August 3, 2012</p> + <p>Last Updated: August 7, 2012</p> </td> </tr> </table> @@ -1210,7 +1210,7 @@ losetup [-o <offset>] [-r] <dev-path> <file-path> <p> <b>Synopsis</b>. Setup the loop device at <dev-path> to access the file at <file-path> as a block device. - In the following example a 256Kb file is created (<code>dd</code>) and <code>losetup</code> is + In the following example a 256K file is created (<code>dd</code>) and <code>losetup</code> is used to make the file accessible as a block device. A FAT file system is created (<code>mkfatfs</code>) and mounted (<code>mount</code>). Files can then be managed on the loop-mounted file. @@ -3148,7 +3148,7 @@ endef </p> <li> <p> - The make file then defines the application name (<code>hello</code>), the task priority (default), and the stack size that will be allocated in the task runs (2Kb). + The make file then defines the application name (<code>hello</code>), the task priority (default), and the stack size that will be allocated in the task runs (2K). </p> <ul><pre> APPNAME = hello @@ -3160,7 +3160,7 @@ STACKSIZE = 2048 <p> And finally, the <code>Makefile</code> invokes the <code>REGISTER</code> macro to added the <code>hello_main()</code> named application. Then, when the system build completes, the <code>hello</code> command can be executed from the NSH command line. - When the <code>hello</code> command is executed, it will start the task with entry point <code>hello_main()</code> with the default priority and with a stack size of 2Kb. + When the <code>hello</code> command is executed, it will start the task with entry point <code>hello_main()</code> with the default priority and with a stack size of 2K. </p> <ul><pre> .context: diff --git a/nuttx/Documentation/NuttX.html b/nuttx/Documentation/NuttX.html index ed994d69b..b7026f896 100644 --- a/nuttx/Documentation/NuttX.html +++ b/nuttx/Documentation/NuttX.html @@ -858,9 +858,9 @@ <p> Using a variety of technologies, NuttX can scale from the very tiny to the moderate-size system. I have executed NuttX with some simple applications - in as little as 32Kb <i>total</i> memory (code and data). - On the other hand, typical, richly featured NuttX builds require more like 64Kb - (and if all of the features are used, this can push 100Kb). + in as little as 32K <i>total</i> memory (code and data). + On the other hand, typical, richly featured NuttX builds require more like 64K + (and if all of the features are used, this can push 100K). </p> </td> </tr> @@ -2028,8 +2028,8 @@ <b>Micropendous 3 AT9USB64x</b> and <b>AT9USB6128x</b>. This port of NuttX to the Opendous Micropendous 3 board. The Micropendous3 is may be populated with an AT90USB646, 647, 1286, or 1287. I have only the AT90USB647 - version for testing. This version have very limited memory resources: 64Kb of - FLASH and 4Kb of SRAM. + version for testing. This version have very limited memory resources: 64K of + FLASH and 4K of SRAM. </p> <ul> <p> @@ -2085,7 +2085,7 @@ </p> <p> Most NuttX test applications are console-oriented with lots of strings used for printf and debug output. - These strings are all stored in SRAM now due to these data accessing issues and even the smallest console-oriented applications can quickly fill a 4-8Kb memory. + These strings are all stored in SRAM now due to these data accessing issues and even the smallest console-oriented applications can quickly fill a 4-8K memory. So, in order for the AVR port to be useful, one of two things would need to be done: </p> <ol> @@ -2917,7 +2917,7 @@ if [ -x "$WINELOADER" ]; then exec "$WINELOADER" "$appname" "$@"; fi </pre> <p><b>87C52</b> A reduced functionality OS test for the 8052 target requires only - about 18-19Kb: + about 18-19K: </p> <pre> Stack starts at: 0x21 (sp set to 0x20) with 223 bytes available. diff --git a/nuttx/Documentation/NuttXDemandPaging.html b/nuttx/Documentation/NuttXDemandPaging.html index 3246e070d..c238161a8 100644 --- a/nuttx/Documentation/NuttXDemandPaging.html +++ b/nuttx/Documentation/NuttXDemandPaging.html @@ -1,675 +1,675 @@ -<html>
-<head>
-<title>On-Demand Paging</title>
-</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>
- <h2><font color="#dc143c">>>> Under Construction <<<</font></h2>
- <p>Last Updated: August 12, 2010</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> </td>
- <td>
- <a href="#Overview">Overview</a>
- </td>
- </tr>
- <tr>
- <td> </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> </td>
- <td>
- <a href="#Initialization">Initialization</a>
- </td>
- </tr>
- <tr>
- <td> </td>
- <td>
- <a href="#PageFaults">Page Faults</a>
- </td>
- </tr>
- <tr>
- <td> </td>
- <td>
- <a href="#FillInitiation">Fill Initiation</a>
- </td>
- </tr>
- <tr>
- <td> </td>
- <td>
- <a href="#FillComplete">Fill Complete</a>
- </td>
- </tr>
- <tr>
- <td> </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> </td>
- <td>
- <a href="#MemoryOrg">Memory Organization</a>
- </td>
- </tr>
- <tr>
- <td> </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.
- This feature was first discussed in this email thread:
- <a href="http://tech.groups.yahoo.com/group/nuttx/message/213">http://tech.groups.yahoo.com/group/nuttx/message/213</a>.
-</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 256Kb (or 192Kb 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 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 of the thread that will perform the page fills
- </li>
- </ul>
-</p>
-<p>
- During OS initialization in <code>sched/os_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 "generic" 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/pg_internal.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 the page fault is resolved and all logic associated with the page fill worker
- must be "<a href="#MemoryOrg">locked</a>" 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 "<a href="#MemoryOrg">locked</a>" 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 "<a href="#MemoryOrg">locked</a>" 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>_TCB *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 progess.
-</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 configuratin 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 "<a href="#MemoryOrg">locked-in-memory</a>" code that is always avaialable 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 pathes.
- 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> </td>
- <td bgcolor="lightslategray">DATA</td>
- <td> </td>
-</tr>
-<tr>
- <td> </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> </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 192Kb (as in the NXP LPC3131). And suppose further that:
- <ul>
- <li>
- The size of the locked, memory resident .text area is 32Kb, and
- </li>
- <li>
- The size of the DATA area is 64Kb.
- </li>
- <li>
- The size of one, managed page is 1Kb.
- </li>
- <li>
- The size of the whole .text image on the non-volatile, mass storage device is 1024Kb.
- </li>
- </ul>
-<p>
- Then, the size of the locked, memory resident code is 32Kb (<i>m</i>=32 pages).
- The size of the physical page region is 96Kb (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 "special" section so that it lies in a reserved, "non-swappable" 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 _TCB *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 _TCB *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 _TCB *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 _TCB *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 _TCB *tcb, FAR const void *vpage, void (*pg_callback)(FAR _TCB *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>
-
+<html> +<head> +<title>On-Demand Paging</title> +</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> + <h2><font color="#dc143c">>>> Under Construction <<<</font></h2> + <p>Last Updated: August 12, 2010</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> </td> + <td> + <a href="#Overview">Overview</a> + </td> + </tr> + <tr> + <td> </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> </td> + <td> + <a href="#Initialization">Initialization</a> + </td> + </tr> + <tr> + <td> </td> + <td> + <a href="#PageFaults">Page Faults</a> + </td> + </tr> + <tr> + <td> </td> + <td> + <a href="#FillInitiation">Fill Initiation</a> + </td> + </tr> + <tr> + <td> </td> + <td> + <a href="#FillComplete">Fill Complete</a> + </td> + </tr> + <tr> + <td> </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> </td> + <td> + <a href="#MemoryOrg">Memory Organization</a> + </td> + </tr> + <tr> + <td> </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. + This feature was first discussed in this email thread: + <a href="http://tech.groups.yahoo.com/group/nuttx/message/213">http://tech.groups.yahoo.com/group/nuttx/message/213</a>. +</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 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 of the thread that will perform the page fills + </li> + </ul> +</p> +<p> + During OS initialization in <code>sched/os_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 "generic" 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/pg_internal.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 the page fault is resolved and all logic associated with the page fill worker + must be "<a href="#MemoryOrg">locked</a>" 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 "<a href="#MemoryOrg">locked</a>" 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 "<a href="#MemoryOrg">locked</a>" 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>_TCB *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 progess. +</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 configuratin 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 "<a href="#MemoryOrg">locked-in-memory</a>" code that is always avaialable 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> </td> + <td bgcolor="lightslategray">DATA</td> + <td> </td> +</tr> +<tr> + <td> </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> </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 "special" section so that it lies in a reserved, "non-swappable" 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 _TCB *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 _TCB *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 _TCB *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 _TCB *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 _TCB *tcb, FAR const void *vpage, void (*pg_callback)(FAR _TCB *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> + diff --git a/nuttx/Documentation/NuttxPortingGuide.html b/nuttx/Documentation/NuttxPortingGuide.html index e605dd109..a339b3a99 100644 --- a/nuttx/Documentation/NuttxPortingGuide.html +++ b/nuttx/Documentation/NuttxPortingGuide.html @@ -3935,7 +3935,7 @@ build 16-bit addressability have smaller overhead than devices that support 32-bit addressability. However, there are many MCUs that support 32-bit addressability <i>but</i> have internal SRAM - of size less than or equal to 64Kb. In this case, CONFIG_MM_SMALL + of size less than or equal to 64K. In this case, CONFIG_MM_SMALL can be defined so that those MCUs will also benefit from the smaller, 16-bit-based allocation overhead. </li> @@ -4740,7 +4740,7 @@ build <li> <code>CONFIG_P14201_FRAMEBUFFER</code>: If defined, accesses will be performed using an in-memory copy of the OLEDs GDDRAM. - This cost of this buffer is 128 * 96 / 2 = 6Kb. + This cost of this buffer is 128 * 96 / 2 = 6K. If this is defined, then the driver will be fully functional. If not, then it will have the following limitations: <ul> diff --git a/nuttx/Documentation/NxWidgets.html b/nuttx/Documentation/NxWidgets.html index cef99d494..1678d9ebe 100755 --- a/nuttx/Documentation/NxWidgets.html +++ b/nuttx/Documentation/NxWidgets.html @@ -33,7 +33,7 @@ <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 40Kb of FLASH and maybe 4Kb of SRAM. + 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. diff --git a/nuttx/ReleaseNotes b/nuttx/ReleaseNotes index 8c6ae0ccb..26af0e38d 100644 --- a/nuttx/ReleaseNotes +++ b/nuttx/ReleaseNotes @@ -1668,7 +1668,7 @@ Important bugfixes included: And feature enhancements: * The LPC176x Ethernet driver was using all of AHB SRAM Bank0 for - Ethernet packet buffers (16Kb). An option was added to limit + Ethernet packet buffers (16K). An option was added to limit the amount of SRAM used for packet buffering and to re-use any extra Bank0 memory for heap. @@ -2022,7 +2022,7 @@ and is available for download from the SourceForge website. The * A PCI-based E1000 Ethernet driver (contributed by Yu Qiang) * New C library functions: inet_addr() (contributed by Yu Qiang), strndup(), asprintf() - * Reduced memory allocation overhead for MCUs with small heaps (<64Kb). + * Reduced memory allocation overhead for MCUs with small heaps (<64K). * fdopen() now works with socket descriptors allowing standard buffered C functions to be used for network communications. * The NSH ifconfig command can now be used to set or change the @@ -2062,7 +2062,7 @@ they are, ordered from the least to the most complete: This port of NuttX to the Amber Web Server from SoC Robotics (http://www.soc-robotics.com/index.htm). Is only partially in place. The Amber Web Server is based on an Atmel ATMega128 - (128Kb FLASH but only 4Kb of SRAM). + (128K FLASH but only 4K of SRAM). STATUS: Work on this port has stalled due to toolchain issues. It is complete, but untested. @@ -2073,7 +2073,7 @@ they are, ordered from the least to the most complete: Micropendous3 may be populated with an AT90USB646, 647, 1286, or 1287. See http://code.google.com/p/opendous/. I have only the AT90USB647 version for testing. This version has very - limited memory resources: 64Kb of FLASH and 4Kb of SRAM. + limited memory resources: 64K of FLASH and 4K of SRAM. STATUS: The basic port was released in NuttX-6.5. This basic port consists only of a "Hello, World!!" example that demonstrates @@ -2085,8 +2085,8 @@ they are, ordered from the least to the most complete: This is a port of NuttX to the PJRC Teensy++ 2.0 board. This board was developed by PJRC (http://pjrc.com/teensy/). The - Teensy++ 2.0 is based on an Atmel AT90USB1286 MCU with 128Kb - of FLASH and 8Kb of SRAM; a little more room to move than the + Teensy++ 2.0 is based on an Atmel AT90USB1286 MCU with 128K + of FLASH and 8K of SRAM; a little more room to move than the AT90USB647. STATUS: The basic port was released in NuttX-6.5. This basic @@ -2109,7 +2109,7 @@ integrated into the normal, general purpose OS. Most NuttX test applications are console-oriented with lots of strings used for printf and debug output. These strings are all stored in SRAM now due to these data accessing issues and even the -smallest console-oriented applications can quickly fill a 4-8Kb +smallest console-oriented applications can quickly fill a 4-8K memory. So, in order for the AVR port to be useful, one of two things would need to be done: diff --git a/nuttx/TODO b/nuttx/TODO index 7ffcb9ca8..f9fc558ea 100644 --- a/nuttx/TODO +++ b/nuttx/TODO @@ -1819,7 +1819,7 @@ o mc68hc1x (arch/hc) Description: There is no script for building in banked mode (more correctly, there is a script, but logic inside the script has not yet been implemented). It would be necessary to implement banked mode to able to access more - the 48Kb of FLASH. + the 48K of FLASH. Status: Open. Priority: Medium/Low diff --git a/nuttx/arch/arm/src/lpc43xx/lpc43_usb0dev.c b/nuttx/arch/arm/src/lpc43xx/lpc43_usb0dev.c index 40233ec0f..2ce19a325 100644 --- a/nuttx/arch/arm/src/lpc43xx/lpc43_usb0dev.c +++ b/nuttx/arch/arm/src/lpc43xx/lpc43_usb0dev.c @@ -69,9 +69,7 @@ #include "up_arch.h" #include "up_internal.h" -#include "lpc43_usbotg.h" -#include "lpc43_evntrtr.h" -#include "lpc43_syscreg.h" +#include "lpc43_usb0dev.h" /******************************************************************************* * Definitions diff --git a/nuttx/arch/arm/src/lpc43xx/lpc43_usb0dev.h b/nuttx/arch/arm/src/lpc43xx/lpc43_usb0dev.h new file mode 100644 index 000000000..97076cd80 --- /dev/null +++ b/nuttx/arch/arm/src/lpc43xx/lpc43_usb0dev.h @@ -0,0 +1,98 @@ +/************************************************************************************ + * arch/arm/src/lpc43xx/lpc43_usbdev.h + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_LPC43XX_LPC32_USB0DEV_H +#define __ARCH_ARM_SRC_LPC43XX_LPC32_USB0DEV_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include <nuttx/config.h> +#include <nuttx/usb/usbdev.h> +#include <stdint.h> + +#include "chip.h" +#include "chip/lpc43_usb0.h" + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/************************************************************************************ + * Name: lpc43_usbpullup + * + * Description: + * If USB is supported and the board supports a pullup via GPIO (for USB software + * connect and disconnect), then the board software must provide lpc43_pullup. + * See include/nuttx/usb/usbdev.h for additional description of this method. + * Alternatively, if no pull-up GPIO the following EXTERN can be redefined to be + * NULL. + * + ************************************************************************************/ + +EXTERN int lpc43_usbpullup(FAR struct usbdev_s *dev, bool enable); + +/************************************************************************************ + * Name: lpc43_usbsuspend + * + * Description: + * Board logic must provide the lpc43_usbsuspend logic if the USBDEV driver is + * used. This function is called whenever the USB enters or leaves suspend mode. + * This is an opportunity for the board logic to shutdown clocks, power, etc. + * while the USB is suspended. + * + ************************************************************************************/ + +EXTERN void lpc43_usbsuspend(FAR struct usbdev_s *dev, bool resume); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_LPC43XX_LPC32_USB0DEV_H */ + |