This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new dbeaec4cdc Doc: migration 5
dbeaec4cdc is described below
commit dbeaec4cdc58b161d140d149856d795797db4972
Author: Ludovic Vanasse <[email protected]>
AuthorDate: Sat Nov 9 15:40:53 2024 -0500
Doc: migration 5
Migrate pages:
* Delayed ACK and TCP Performance
* TCP Network Performance
* NxWM Threading
* Framebuffer Character Driver
From Confluence wiki to official wiki
---
.../components/net/delay_act_and_tcp_perf.rst | 195 +++++++++++
Documentation/components/net/index.rst | 2 +
Documentation/components/net/tcp_network_perf.rst | 193 +++++++++++
.../components/nxgraphics/GraphicsInterfaces.png | Bin 0 -> 82985 bytes
.../nxgraphics/framebuffer_char_driver.rst | 383 +++++++++++++++++++++
Documentation/components/nxgraphics/index.rst | 2 +
.../components/nxgraphics/nxwm_threading.rst | 13 +
.../nxwm_theading_model_page_0.png | Bin 0 -> 314995 bytes
.../nxwm_theading_model_page_1.png | Bin 0 -> 172777 bytes
.../nxwm_theading_model_page_2.png | Bin 0 -> 121021 bytes
.../nxwm_theading_model_page_3.png | Bin 0 -> 157603 bytes
.../nxwm_theading_model_page_4.png | Bin 0 -> 252166 bytes
12 files changed, 788 insertions(+)
diff --git a/Documentation/components/net/delay_act_and_tcp_perf.rst
b/Documentation/components/net/delay_act_and_tcp_perf.rst
new file mode 100644
index 0000000000..50247b9a57
--- /dev/null
+++ b/Documentation/components/net/delay_act_and_tcp_perf.rst
@@ -0,0 +1,195 @@
+===============================
+Delayed ACK and TCP Performance
+===============================
+
+.. warning::
+ Migrated from:
+
https://cwiki.apache.org/confluence/display/NUTTX/Delayed+ACK+and+TCP+Performance
+
+uIP and NuttX
+=============
+
+The heart of the NuttX IP stack derived from Adam Dunkel's tiny `uIP
+stack <http://sourceforge.net/projects/uip-stack/>`_ back at version 1.0.
+The NuttX TCP/IP stack contains the uIP TCP state machine and
+some uIP "ways of doing things," but otherwise, there is
+now little in common between these two designs.
+
+**NOTE**: uIP is also built into Adam Dunkel's
+`Contiki <http://contiki.sourceforge.net/docs/2.6/a01793.html>`_
+operating system.
+
+uIP, Delayed ACKs, and Split Packets
+====================================
+
+In uIP, TCP packets are sent and ACK'ed one at a time.
+That is, after one TCP packet is sent, the next packet cannot
+be sent until the previous packet has been ACKed by the
+receiving side.
+The TCP protocol, of course, supports sending multiple packets
+which can be ACKed be the receiving time asynchronously.
+This one-packet-at-a-time logic is a simplification in the
+uIP design; because of this, uIP needs only a single packet
+buffer any you can use uIP in even the tiniest environments.
+This is a good thing for the objectives of uIP.
+
+Improvements in packet buffering is the essential improvement
+that you get if upgrade from Adam Dunkel's uIP to his
+`lwIP <http://savannah.nongnu.org/projects/lwip/>`_ stack.
+The price that you pay is in memory usage.
+
+This one-at-a-time packet transfer does create a performance
+problem for uIP:
+RFC 1122 states that a host may delay ACKing a packet for up
+to 500ms but must respond with an ACK to every second segment.
+In the baseline uIP, the effectively adds a one half second
+delay between the transfer of every packet to a recipient
+that employs this delayed ACK policy!
+
+uIP has an option to work around this:
+It has logic that can be enable to split each packet into half,
+sending half as much data in each packet.
+Sending more, smaller packets does not sound like a performance
+improvement.
+This tricks the recipient that follows RFC 1122 into receiving
+the two, smaller back-to-back packets and ACKing the second
+immediately.
+References: `uip-split.c
<http://contiki.sourceforge.net/docs/2.6/a00427_source.html>`_
+and `uip-split.h <http://contiki.sourceforge.net/docs/2.6/a00428.html>`_.
+
+The NuttX TCP/IP Stack and Delay ACKs
+=====================================
+
+The NuttX, low-level TCP/IP stack does not have the
+limitations of the uIP TCP/IP stack.
+It can send numerous TCP/IP packets regardless of
+whether they have been ACKed or not.
+That is because in NuttX, the accounting for which
+packets have been ACKed and which have not has been
+moved to a higher level in the architecture.
+
+NuttX includes a standard, BSD socket interface on top
+of the low-level TCP/IP stack.
+It is in this higer-level, socket layer where the ACK
+accounting is done, specifically in the function
+`send() <http://pubs.opengroup.org/onlinepubs/009695399/functions/send.html>`_.
+If you send a large, multi-packet buffer via ``send()``,
+it will be broken up into individual packets and each
+packet will be sent as quickly as possible, with no
+concern for whether the previous packet has been ACKed or not.
+
+However, the NuttX ``send()`` function will not return to
+the caller until the final packet has been ACKed.
+It does this to assure that the callers data was sent
+successfully (or not).
+This behavior means that if an odd number of packets
+were sent, there could still be a delay after the final
+packet before ``send()`` receives the ACK and returns.
+
+So the NuttX approach is similar to the uIP way of doing
+things, but does add one more buffer, the user provided
+buffer to ``send()``, that can be used to improve TCP/IP
+performance (of course, this user provided buffer is
+also required by in order to be compliant with ``send()``""
+`specification
<http://pubs.opengroup.org/onlinepubs/009695399/functions/send.html>`_.
+
+The NuttX Split Packet Configuration
+====================================
+
+But what happens if all of the user buffer is smaller than
+the MSS of one TCP packet?
+Suppose the MTU is 1500 and the user I/O buffer is only
+512 bytes?
+In this case, ``send()`` performance degenerates to the same
+behavior as uIP:
+An ACK is required for each packet before ``send()`` can
+return and before ``send()`` can be called again to send
+the next packet.
+
+And the fix? A fix has recently been contributed by
+Yan T that works in a similar way to uIP split
+packet logic:
+In ``send()``, the logic normally tries to send a full packet
+of data each time it has the opportunity to do so.
+However, if the configuration option ``CONFIG_NET_TCP_SPLIT=y``
+is defined, the behavior of ``send()`` will change in the
+following way:
+
+* ``send()`` will keep track of `even` and `odd` packets; `even`
+ packets being those that we do not expect to be ACKed
+ and `odd` packets being the those that we do expect to
+ be ACKed.
+* ``send()`` will then reduce the size of even packets as
+ necessary to assure that an even number of packets is
+ always sent. Every call to send will result in an even
+ number of packets being sent.
+
+This clever solution tricks the RFC 1122 recipient in the
+same way that uIP split logic does.
+So if you are working with hosts the following the RFC 1122
+ACKing behavior and you have MSS sizes that are larger that
+the average size of the user buffers, then your throughput
+can probably be greatly improved by enabling ``CONFIG_NET_TCP_SPLIT=y``
+
+NOTE: NuttX is `not` an RFC 1122 recipient; NuttX will ACK
+every TCP/IP packet that it receives.
+
+Write Buffering
+===============
+
+The best technical solution to the delayed ACK problem
+would be to support `write buffering`.
+Write buffering is enabled with ``CONFIG_NET_TCP_WRITE_BUFFERS``.
+If this option is selected, the NuttX networking layer will
+pre-allocate several write buffers at system initialization
+time. The sending a buffer of data then works like this:
+
+* ``send()`` (1) obtains a pre-allocated write buffer from a free
+ list, and then (2) simply copies the buffer of data that the
+ user wishes to send into the allocated write buffer. If no
+ write buffer is available, ``send()`` would have to block waiting
+ for free write buffer space.
+* ``send()`` then (3) adds the write buffer to a queue of outgoing
+ data for a TCP socket. Each open TCP socket has to support
+ such a queue. ``send()`` could then (4) return success to the
+ caller (even thought the transfer could still fail later).
+* Logic outside of the ``send()`` implementation manages the actual
+ transfer of data from the write buffer. When the Ethernet
+ driver is able to send a packet on the TCP connection, this
+ external logic (5) copies a packet of data from the write
+ buffer so that the Ethernet driver can perform the
+ transmission (a `zero-copy` implementation would be preferable).
+ Note that the data has to remain in the write buffer for now;
+ it may need to be re-transmitted.
+* This external logic would also manage the receipt TCP ACKs.
+ When TCP peer acknowledges the receipt of data, the
+ acknowledged portion of the data can the (6) finally
+ be deleted from the write buffer.
+
+The following options configure TCP write buffering:
+
+* ``CONFIG_NET_TCP_WRITE_BUFSIZE``: The size of one TCP write buffer.
+* ``CONFIG_NET_NTCP_WRITE_BUFFERS``: The number of TCP
+ write buffers (may be zero to disable TCP/IP write buffering)
+
+NuttX also supports TCP read-ahead buffering. This option
+is enabled with ``CONFIG_NET_TCP_READAHEAD``. TCP read-ahead
+buffer is necessary on TCP connections; otherwise data
+received while there is no ``recv()`` in place would be lost.
+For consistency, it would be best if such a TCP write
+buffer implementation worked in a manner similar to the
+existing TCP read-ahead buffering.
+
+The following lists the NuttX configuration options
+available to configure the TCP read-ahead buffering feature:
+
+* ``CONFIG_NET_TCP_READAHEAD_BUFSIZE``: The size of one TCP read-ahead buffer.
+* ``CONFIG_NET_NTCP_READAHEAD_BUFFERS``: The number of TCP
+ read-ahead buffers (may be zero to disable TCP/IP read-ahead buffering)
+
+A future enhancement is to combine the TCP write buffer
+management logic and the TCP read-ahead buffer management
+so that one common pool of buffers can be used for both
+functions (this would probably also require additional logic
+to `throttle` read-buffering so that received messages do not
+consume all of the buffers).
\ No newline at end of file
diff --git a/Documentation/components/net/index.rst
b/Documentation/components/net/index.rst
index ebefe8d32c..025966919b 100644
--- a/Documentation/components/net/index.rst
+++ b/Documentation/components/net/index.rst
@@ -16,6 +16,8 @@ Network Support
netlink.rst
slip.rst
wqueuedeadlocks.rst
+ tcp_network_perf.rst
+ delay_act_and_tcp_perf.rst
``net`` Directory Structure ::
diff --git a/Documentation/components/net/tcp_network_perf.rst
b/Documentation/components/net/tcp_network_perf.rst
new file mode 100644
index 0000000000..33e89d8efd
--- /dev/null
+++ b/Documentation/components/net/tcp_network_perf.rst
@@ -0,0 +1,193 @@
+=======================
+TCP Network Performance
+=======================
+
+.. warning::
+ Migrated from:
+ https://cwiki.apache.org/confluence/display/NUTTX/TCP+Network+Performance
+
+
+(Abstracted and extended from a discussion from the NuttX Google group)
+
+Question
+========
+
+For some unknown reason, I am seeing poor TCP network performance.
+
+Answer
+======
+
+First let's talk about TCP send performance.
+
+Source of Performance Bottlenecks
+---------------------------------
+
+General TCP send performance is not determined by the TCP stack as much
+as it is by the network device driver. Bad network performance is due
+to time lost `BETWEEN` packet transfers. The packet transfers themselves
+go at the wire speed*. So if you want to improve performance on a
+given network, you have to reduce time lost between transfers.
+There is no other way.
+
+Ignoring Ethernet issues like collisions, back-off delays,
+inter-packet gaps (IPG), etc.
+
+The time between packets is limited primarily by the buffering
+design of the network driver. If you want to improve performance,
+then you must improve the buffering at the network driver.
+You need to support many full size (1500 byte) packet buffers.
+You must be able to query the network for new data to transfer,
+and queue those transfers in packet buffers. In order to reach
+peak performance, the network driver must have the next transfer
+buffered and ready-to-go before the previous transfer is finished
+to minimize the GAP between packet transfers.
+
+Different network devices also support more or less efficient
+interfaces: The worst performing support interfaces that can
+handle only one packet at a time, the best performing are able
+to retain linked lists of packet buffers in memory and perform
+scatter-gather DMA for a sequence of packets.
+
+In the NuttX TCP stack, you can also improve performance by
+enabling TCP write buffering. But the driver is the real key.
+
+It would be good to have a real in-depth analysis of the
+network stack performance to identify bottlenecks and
+generate ideas for performance improvement. No one has
+ever done that. If I were aware of any stack related
+performance issue, I would certainly address it.
+
+RFC 1122
+--------
+
+There is one important feature missing the NuttX TCP that
+can help when there is no write buffering: Without write
+buffering send() will not return until the transfer has
+been ACKed by the recipient. But under RFC 1122, the host
+need not ACK each packet immediately; the host may wait
+for 500 MS before ACKing. This combination can cause very
+slow performance when small, non-buffered transfers are
+made to an RFC 1122 client. However, the RFC 1122 must
+ACK at least every second (odd) packet so sequences of
+packets with write buffering enabled do not suffer from
+this problem.
+
+`Update: RFC 1122 support was added to the NuttX TCP
+stack with commit 66ef6d143a627738ad7f3ce1c065f9b1f3f303b0
+in December of 2019. That, however, that affects only
+received packet ACK behavior and has no impact on transmitted
+packet performance; write buffering is still recommended.`
+
+TCPBlaster
+----------
+
+I created a new test application at ``apps/examples/tcpblaster`` to
+measure TCP performance and collected some data for the
+configuration that happens to be on my desk. The `tcpblaster`
+test gives you the read and write transfer rates in ``Kb/sec``
+(I won't mention the numbers because I don't believe they
+would translate any other setup and, hence, would be
+misleading).
+
+There is a nifty `TCP Throughput Tool
<https://www.switch.ch/network/tools/tcp_throughput/>`_
+that gives some theoretical upper limits on performance.
+The tool needs to know the ``MSS`` (which is the Ethernet
+packet size that you configured minus the size of the
+Ethernet header, 14), the round-trip time (``RTT``)in
+milliseconds (which you can
+get from the Linux host ping), and a loss constant (which
+I left at the default). With these values, I can determine
+that the throughput for the NuttX TCP stack is approximately
+at the theoretical limits. You should not be able to do
+better any better than that (actually, it performs above
+the theoretical limit, but I suppose that is why it is
+"theoretical").
+
+So, If you are unhappy with your network performance, the I
+suggest you run the `tcpblaster` test, use that data
+(along with the ``RTT`` from ping) with the
+`TCP Throughput Tool <https://www.switch.ch/network/tools/tcp_throughput/>`_.
+If you are still unhappy with the performance, don't go
+immediately pointing fingers at the stack (which everyone does).
+Instead, you should focus on optimizing your network
+configuration settings and reviewing the buffer handling
+of the Ethernet driver in you MCU.
+
+If you do discover any significant performance issues
+with the stack I will of course gladly help you resolve
+them. Or if you have ideas for improved performance,
+I would also be happy to hear those.
+
+What about Receive Performance?
+-------------------------------
+
+All of the above discussion concerns `transmit performance`,
+i.e., "How fast can we send data over the network?" The other
+side is receive performance. Receive performance is very
+different thing. In this case it is the remote peer who is
+in complete control of the rate at which packets appear on
+the network and, hence, responsible for all of the raw bit
+transfer rates.
+
+However, we might also redefine performance as the number of
+bytes that were `successfully` transferred. In order for the
+bytes to be successfully transferred they must be successfully
+received and processed on the NuttX target. If we fail in
+this if the packet is `lost` or `dropped`. A packet is lost if
+the network driver is not prepared to receive the packet when
+it was sent. A packet is dropped by the network if it is
+received but could not be processed either because there
+is some logical issue with the packet (not the case here)
+or if we have no space to buffer the newly received packet.
+
+If a TCP packet is lost or dropped, then the penalty is big:
+The packet will not be ACKed, the remote peer may send a
+few more out-of-sequence packets which will also be dropped.
+Eventually, the remote peer will time out and retransmit
+the data from the point of the lost packet.
+
+There is logic in the TCP protocol to help manage these data
+overruns. The TCP header includes a TCP `receive window` which
+tells the remote peer how much data the receiver is able to
+buffer. This value is sent in the ACK to each received
+packet. If well tuned, this receive window could possibly
+prevent packets from being lost due to the lack of
+read-ahead storage. This is a little better. The remote
+peer will hold off sending data instead of timing out and
+re-transmitting. But this is still a loss of performance;
+the gap between the transfer of packets caused by the hold-off
+will result in a reduced transfer rate.
+
+So the issues for good reception are buffering and processing
+time. Buffering again applies to handling within the driver
+but unlike the transmit performance, this is not typically
+the bottleneck. And there is also a NuttX configuration
+option that controls `read-ahead` buffering of TCP packets.
+The buffering in the driver must be optimized to avoid lost
+packets; the ` buffering can be tuned to minimize
+the number packets dropped because we have no space to buffer them.
+
+But the key to receive perform is management of processing
+delays. Small processing delays can occur in the network
+driver or in the TCP stack. But the major source of
+processing delay is the application which is the ultimate
+consumer of the incoming data. Imagine, for example,
+and FTP application that is receiving a file over a
+TCP and writing the file into FLASH memory. The primary
+bottleneck here will be the write to FLASH memory which
+is out of the control of software.
+
+We obtain optimal receive performance when the processing
+delays keep up with the rate of the incoming packets.
+If the processing data rate is even slightly slower
+then the receive data rate, then there will be a
+growing `backlog` of buffered, incoming data to be
+processed. If this backlog continues to grow then
+eventually our ability to buffer data will be exhausted,
+packets will be held off or dropped, and performance
+will deteriorate. In an environment where a high-end,
+remote peer is interacting with the low-end, embedded
+system, that remote peer can easily overrun the
+embedded system due to the embedded system's limited
+buffering space, its much lower processing capability,
+and its slower storage peripherals.
\ No newline at end of file
diff --git a/Documentation/components/nxgraphics/GraphicsInterfaces.png
b/Documentation/components/nxgraphics/GraphicsInterfaces.png
new file mode 100644
index 0000000000..4fe1177b2c
Binary files /dev/null and
b/Documentation/components/nxgraphics/GraphicsInterfaces.png differ
diff --git a/Documentation/components/nxgraphics/framebuffer_char_driver.rst
b/Documentation/components/nxgraphics/framebuffer_char_driver.rst
new file mode 100644
index 0000000000..a7afce5b17
--- /dev/null
+++ b/Documentation/components/nxgraphics/framebuffer_char_driver.rst
@@ -0,0 +1,383 @@
+============================
+Framebuffer Character Driver
+============================
+
+.. warning::
+ Migrated from:
+
https://cwiki.apache.org/confluence/display/NUTTX/Framebuffer+Character+Driver
+
+
+NX Graphics
+===========
+
+NuttX has supported higher level graphics for some time with
+the OS's :doc:`/components/nxgraphics/index` and application
+oriented :doc:`NxWidgets </applications/graphics/nxwidgets/index>` and the
tiny
+window manager :doc:`NxWM </applications/graphics/nxwm/index>`.
+These are higher level in the sense that the primary
+graphical function is to support windowing and control
+of tools and toolbars within windows. These graphics
+tools often do not meet the needs
+of developers with very low end graphics and minimal display
+requirements.
+
+Figure 1
+========
+
+The framebuffer character driver, along with the option LCD
+framebuffer interface, is an optional lighter-weight graphics interface.
+
+.. image:: GraphicsInterfaces.png
+
+Framebuffer Character Driver details
+====================================
+
+A `framebuffer character driver` has been recently been added
+to bypass the complexity of `NX` and to provide a direct
+application interface to the framebuffer graphic device.
+The framebuffer buffer character devices, as with all
+character devices, provides the interface to the graphics
+device via stand POSIX VFS commands (``open()``, ``close()``,
+``read()``, ``write()``, ``seek()``, ...), through IOCTL commands,
+and for this driver via the ``mmap()`` function. These
+interfaces are described below,
+
+The framebuffer character driver is located in the NuttX
+source tree at ``drivers/video/fb.c``. It is enabled in the
+build with ``CONFIG_VIDEO_FB=y``. In order to register the
+framebuffer driver, you will need to include logic in the
+your board-specific start-up function that calls
+``fb_register()`` That code sequence might look something
+like:
+
+.. code-block:: c
+
+ #include <nuttx/video/fb.h>
+
+ #ifdef CONFIG_VIDEO_FB
+ /* Initialize and register the simulated framebuffer driver */
+
+ ret = fb_register(0, 0);
+ if (ret < 0)
+ {
+ syslog(LOG_ERR, "ERROR: fb_register() failed: %d\n", ret);
+ }
+ #endif
+
+The ``fb_register()`` function takes two parameters:
+
+* `display`. The display number for the case of boards
+ supporting multiple displays or for hardware that supports
+ multiple layers (each layer is consider a display). Typically zero.
+* `plane`. Identifies the color plane on hardware that supports
+ separate framebuffer "planes" for each color component.
+ Should be zero because no planar hardware is currently
+ supported by NuttX.
+
+``fb_register()`` will register the framebuffer character device
+at ``/dev/fb`` `N` where `N` is the display number if the devices
+supports only a single plane. If the hardware supports
+multiple color planes, then the device will be registered
+at ``/dev/fb`` `N-M` where `N` is the again display number but `M`
+is the display plane.
+
+There is a simple example at ``apps/examples/fb`` that provides
+an illustration of most of the following interfacing methods.
+
+POSIX Interfaces
+================
+
+The interaction with the framebuffer character driver via POSIX
+VFS interface calls is the same as for other character drivers.
+The only aspect that might require some additional discussion
+is the use of ``read()``, ``write()``, and ``seek()``.
+
+* ``read()`` returns data from the framebuffer memory and
+ updates the file position based on the number of bytes read.
+* ``write()`` puts data into the framebuffer memory and
+ also updates the file position.
+
+That file position is initially set to the position
+zero meaning the beginning of the framebuffer. It is
+advanced each time you ``read()`` from or ``write()`` to the
+framebuffer. Is also updated by ``seek()``:
+
+* ``seek()`` sets the file position to any desired
+ location within the framebuffer.
+
+The file position is in units of `bytes`. This can be
+confusing because other positional data may be in units
+`pixels`. Pixels have different `depth` in different displays,
+that is, different graphic hardware may support pixels with
+differing bits-per-pixel. The pixel depth can be obtained
+using one of the IOCTL commands listed below. Since the file
+position is in bytes, the bits-per-pixel must be taken account
+when using ``read()``, ``write()``, and ``seek()``. The usual conversion
+from pixels to bytes is:
+
+.. code-block:: C
+
+ start_byte = (start_pixel * bits_per_pixel) >> 3;
+ end_byte = (end_pixel * bits_per_pixel + 7) >> 3;
+
+While the framebuffer may be accessed with these POSIX interfaces,
+a more typical way of interacting with the framebuffer from an
+application would involve use of ``mmap()`` as described below.
+
+IOCTL Commands
+==============
+
+* ``FBIOGET_VIDEOINFO``. Get color plane info. Its argument is
+ pointer a writable instance of ``struct fb_videoinfo_s``:
+
+ .. code-block:: c
+
+ struct fb_videoinfo_s
+ {
+ uint8_t fmt; /* see FB_FMT_* */
+ fb_coord_t xres; /* Horizontal resolution in pixel columns */
+ fb_coord_t yres; /* Vertical resolution in pixel rows */
+ uint8_t nplanes; /* Number of color planes supported */
+ };
+
+* ``FBIOGET_PLANEINFO``. Get video plane info. It received
+ a pointer to a writable instance of ``struct fb_planeinfo_s`` as its
argument:
+
+ .. code-block:: C
+
+ struct fb_planeinfo_s
+ {
+ FAR void *fbmem; /* Start of frame buffer memory */
+ uint32_t fblen; /* Length of frame buffer memory in bytes */
+ fb_coord_t stride; /* Length of a line in bytes */
+ uint8_t display; /* Display number */
+ uint8_t bpp; /* Bits per pixel */
+ };
+
+* ``FBIOGET_CMAP`` and ``FBIOPUT_CMAP``. Get/Put RGB color mapping.
+ These commands are available only if the hardware and
+ framebuffer driver support color mapping (``CONFIG_FB_CMAP=y``).
+ They each take a pointer to an instance of ``struct fb_cmap_s``
+ as an argument (writeable for ``FBIOGET_CMAP`` and read-only
+ for ``FBIOPUT_CMAP``).
+
+ .. code-block:: c
+
+ #ifdef CONFIG_FB_CMAP
+ struct fb_cmap_s
+ {
+ uint16_t first; /* Offset offset first color entry in tables */
+ uint16_t len; /* Number of color entries in tables */
+
+ /* Tables of color component. Any may be NULL if not used */
+
+ uint8_t *red; /* Table of 8-bit red values */
+ uint8_t *green; /* Table of 8-bit green values */
+ uint8_t *blue; /* Table of 8-bit blue values */
+ #ifdef CONFIG_FB_TRANSPARENCY
+ uint8_t *transp; /* Table of 8-bit transparency */
+ #endif
+ };
+ #endif
+
+* ``FBIOGET_CURSOR``. Get cursor attributes. This command is
+ available only if the hardware and framebuffer driver
+ support cursors (``CONFIG_FB_HWCURSOR=y``). It take a pointer
+ to a writable instance of ``struct fb_cursorattrib_s``:
+
+ .. code-block:: c
+
+ #ifdef CONFIG_FB_HWCURSOR
+ #ifdef CONFIG_FB_HWCURSORIMAGE
+ struct fb_cursorimage_s
+ {
+ fb_coord_t width; /* Width of the cursor image in pixels */
+ fb_coord_t height /* Height of the cursor image in pixels */
+ const uint8_t *image; /* Pointer to image data */
+ };
+ #endif
+
+ struct fb_cursorpos_s
+ {
+ fb_coord_t x; /* X position in pixels */
+ fb_coord_t y; /* Y position in rows */
+ };
+
+ #ifdef CONFIG_FB_HWCURSORSIZE
+ struct fb_cursorsize_s
+ {
+ fb_coord_t h; /* Height in rows */
+ fb_coord_t w; /* Width in pixels */
+ };
+ #endif
+
+ struct fb_cursorattrib_s
+ {
+ #ifdef CONFIG_FB_HWCURSORIMAGE
+ uint8_t fmt; /* Video format of cursor */
+ #endif
+ struct fb_cursorpos_s pos; /* Current cursor position */
+ #ifdef CONFIG_FB_HWCURSORSIZE
+ struct fb_cursorsize_s mxsize; /* Maximum cursor size */
+ struct fb_cursorsize_s size; /* Current size */
+ #endif
+ };
+ #endif
+
+* ``FBIOPUT_CURSOR``. Set cursor attributes. This command is
+ available only if the hardware and framebuffer driver
+ support cursors (``CONFIG_FB_HWCURSOR=y``). It take a
+ pointer to a writable instance of ``struct fb_setcursor_s``:
+
+ .. code-block:: c
+
+ #ifdef CONFIG_FB_HWCURSOR
+ struct fb_setcursor_s
+ {
+ uint8_t flags; /* See FB_CUR_* definitions */
+ struct fb_cursorpos_s pos; /* Cursor position */
+ #ifdef CONFIG_FB_HWCURSORSIZE
+ struct fb_cursorsize_s size; /* Cursor size */
+ #endif
+ #ifdef CONFIG_FB_HWCURSORIMAGE
+ struct fb_cursorimage_s img; /* Cursor image */
+ #endif
+ };
+ #endif
+
+* ``FBIO_UPDATE``. This IOCTL command updates a rectangular region
+ in the framebuffer. Some hardware requires that there be
+ such a notification when a change is made to the
+ framebuffer (see, for example, the discussion of LCD drivers
+ below). This IOTCL command is if ``CONFIG_NX_UPDATE=y`` is
+ defined. It takes a pointer to a read-only instance of
+ ``struct nxgl_rect_s`` that describes the region to be updated:
+
+ .. code-block:: c
+
+ struct nxgl_rect_s
+ {
+ struct nxgl_point_s pt1; /* Upper, left-hand corner */
+ struct nxgl_point_s pt2; /* Lower, right-hand corner */
+ };
+
+``mmap()``
+==========
+
+Above we talked about using ``read()``, ``write()``, and ``seek()`` to
+access the framebuffer. The simplest way to access the
+framebuffer, however, is by using the ``mmap()`` to map
+the framebuffer memory into the application memory
+space. The following ``mmap()`` command, for example, can
+be used to obtain a pointer to a read-able, write-able
+copy of the framebuffer:
+
+.. code-block:: c
+
+ FAR void *fbmem;
+
+ fbmem = mmap(NULL, fblen, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FILE, fd,
0);
+ if (state.fbmem == MAP_FAILED)
+ {
+ /* Handle failure */
+ ...
+ }
+
+ printf("Mapped FB: %p\n", fbmem);
+
+Where fd is the file descriptor of the opened framebuffer
+character driver and ``fblen`` was obtained via an IOCTL
+command as described above. NOTE that the framebuffer
+buffer pointer is also available within the values
+returned by the IOCTL commands. The address is a
+kernel memory address and may not be valid in all
+build configurations. Hence, ``mmap()`` is the preferred,
+portable way to get the framebuffer address.
+
+Framebuffer vs. LCD Graphics Drivers
+====================================
+
+Framebuffer graphics drivers are very common in high-end CPUs
+but most low-end, embedded hardware will not support a
+framebuffer.
+
+A framebuffer graphics driver supports a region of memory
+that is shared both by the software and by the graphics
+hardware. Any modification to the framebuffer memory
+results in a corresponding modification on the display
+with no intervening software interaction. Some video
+memory is dual ported to support concurrent video processor
+and application processor accesses; or perhaps the LCD
+peripheral just constantly DMAs the framebuffer memory
+to the graphics hardware.
+
+Most low-end embedded MCUs have a much simpler hardware
+interface: The interface to the LCD may be through a simple
+parallel interface or, more commonly, through a slower serial
+interface such as SPI. In order to support such low-end
+hardware with the framebuffer character driver, a special
+software layer called the `Framebuffer LCD Front End` has
+been developed. This is the topic of the next paragraph.
+
+LCD Framebuffer Front-End
+=========================
+
+The `LCD Framebuffer Front-End` provides a standard NuttX
+framebuffer interface, but works on top of a standard
+parallel or serial LCD driver. It provides the framebuffer,
+the framebuffer interface, and the hooks to adapt the LCD
+driver. The LCD framebuffer front-end can be found in the
+NuttX source tree at ``drivers/lcd/lcd_framebuffer.c``.
+
+In order to provide updates to the LCD hardware after
+updates to the framebuffer, the LCD framebuffer front-end
+must be notified when significant changes to the framebuffer
+have been made. This notification is supported when
+``CONFIG_NX_UPDATE=y`` is defined in the configuration. In
+this case, the LCD framebuffer front-end will support
+the special. OS-internal interface function ``nx_notify_rectangle()``
+which defines the rectangular region in the framebuffer that
+has been changed. In response to a call to ``nx_notify_rectangle()``
+will use the lower-level LCD interface to update only that
+rectangular region on the display.
+
+This kind of update for standard LCD drivers is very efficient:
+It is usually more efficient to update a region on the
+display than it is for form a complex image with text and
+line drawing; the updated region seems to update very
+quickly because of that. In fact, many of the low-end
+LCD drivers already include an internal framebuffer to
+support this style of LCD update.
+
+When used with LCD character driver, the ``nx_notify_rectangle()``
+function will be called by the character river in response
+to the ``FBIO_UPDATE IOCTL`` command.
+
+Another advantage of the framebuffer, both the LCD internal
+framebuffer and the framebuffer character driver, is
+that super-efficient reading of the LCD display memory:
+The LCD display memory is not read at all! The read is
+from the copy in the framebuffer.
+
+Of course, using both an LCD internal framebuffer with the
+framebuffer character drivers is wasteful; one framebuffer
+is enough!
+
+As a caution, it is important to remember that a framebuffer
+can be quite large. For example, a 480x320 display with
+16-bit RGB pixels would require an allocated framebuffer
+of size 300 KiB. This is inappropriate with most small
+MCUs (unless they support external memory). For tiny displays,
+such as 128x64 1-bit monochromatic displays, the framebuffer
+memory usage is not bad: 1 KiB in that example.
+
+Framebuffer Graphics Library
+============================
+
+Now the missing part is some kind of application-space
+framebuffer graphics library. The NuttX framebuffer
+driver is superficially similar to the Linux framebuffer
+driver so there is a lot of support for Linux
+framebuffer graphics support that should be easily ported to
+NuttX – Perhaps DirectFB would be an GPL option? SDL with its
+MIT license might be a more compatible source for such a port.
\ No newline at end of file
diff --git a/Documentation/components/nxgraphics/index.rst
b/Documentation/components/nxgraphics/index.rst
index f5740a45c8..318f3bd98e 100644
--- a/Documentation/components/nxgraphics/index.rst
+++ b/Documentation/components/nxgraphics/index.rst
@@ -171,6 +171,8 @@ NX Header Files
nxtk.rst
nxfonts.rst
nxcursor.rst
+ nxwm_threading.rst
+ framebuffer_char_driver.rst
sample.rst
appendix.rst
diff --git a/Documentation/components/nxgraphics/nxwm_threading.rst
b/Documentation/components/nxgraphics/nxwm_threading.rst
new file mode 100644
index 0000000000..ea5c8ac965
--- /dev/null
+++ b/Documentation/components/nxgraphics/nxwm_threading.rst
@@ -0,0 +1,13 @@
+==============
+NxWM Threading
+==============
+
+.. warning::
+ Migrated from:
+ https://cwiki.apache.org/confluence/display/NUTTX/NxWM+Threading
+
+.. image:: nxwm_threading_model/nxwm_theading_model_page_0.png
+.. image:: nxwm_threading_model/nxwm_theading_model_page_1.png
+.. image:: nxwm_threading_model/nxwm_theading_model_page_2.png
+.. image:: nxwm_threading_model/nxwm_theading_model_page_3.png
+.. image:: nxwm_threading_model/nxwm_theading_model_page_4.png
diff --git
a/Documentation/components/nxgraphics/nxwm_threading_model/nxwm_theading_model_page_0.png
b/Documentation/components/nxgraphics/nxwm_threading_model/nxwm_theading_model_page_0.png
new file mode 100644
index 0000000000..eb95bc5a3f
Binary files /dev/null and
b/Documentation/components/nxgraphics/nxwm_threading_model/nxwm_theading_model_page_0.png
differ
diff --git
a/Documentation/components/nxgraphics/nxwm_threading_model/nxwm_theading_model_page_1.png
b/Documentation/components/nxgraphics/nxwm_threading_model/nxwm_theading_model_page_1.png
new file mode 100644
index 0000000000..3e38e9b0db
Binary files /dev/null and
b/Documentation/components/nxgraphics/nxwm_threading_model/nxwm_theading_model_page_1.png
differ
diff --git
a/Documentation/components/nxgraphics/nxwm_threading_model/nxwm_theading_model_page_2.png
b/Documentation/components/nxgraphics/nxwm_threading_model/nxwm_theading_model_page_2.png
new file mode 100644
index 0000000000..8bde18ebf7
Binary files /dev/null and
b/Documentation/components/nxgraphics/nxwm_threading_model/nxwm_theading_model_page_2.png
differ
diff --git
a/Documentation/components/nxgraphics/nxwm_threading_model/nxwm_theading_model_page_3.png
b/Documentation/components/nxgraphics/nxwm_threading_model/nxwm_theading_model_page_3.png
new file mode 100644
index 0000000000..80020f0e34
Binary files /dev/null and
b/Documentation/components/nxgraphics/nxwm_threading_model/nxwm_theading_model_page_3.png
differ
diff --git
a/Documentation/components/nxgraphics/nxwm_threading_model/nxwm_theading_model_page_4.png
b/Documentation/components/nxgraphics/nxwm_threading_model/nxwm_theading_model_page_4.png
new file mode 100644
index 0000000000..cbdc132904
Binary files /dev/null and
b/Documentation/components/nxgraphics/nxwm_threading_model/nxwm_theading_model_page_4.png
differ