nuttx-apps/system/zmodem
Xiang Xiao d660492289 Run codespell -w against all files
and fix the wrong correction
2020-02-22 14:41:36 -06:00
..
host Run codespell -w against all files 2020-02-22 14:41:36 -06:00
.gitignore Remove extra whitespace from files (#43) 2020-01-31 08:29:24 -06:00
Kconfig Run codespell -w against all files 2020-02-22 14:41:36 -06:00
Make.defs Remove extra whitespace from files (#43) 2020-01-31 08:29:24 -06:00
Makefile Makefiles: This reverts part of commit cf0365ea9. It restores 'conditional' inclusion of TOPDIR/Make.defs. Otherwise all make targets fail if the board has not been configured. That is okay most of the time, but not for things like clean and distclean which should not depend on being configured. 2019-10-15 09:25:48 +08:00
Makefile.host system: zmodem: Fix compile error in zmodem host tool 2020-01-08 20:43:39 +08:00
README.txt Update comments, README's, etc. to reflect changes to nuttx/boards directory reorganization. 2019-08-09 08:40:22 -06:00
rz_main.c Unify the void cast usage 2020-01-02 23:21:01 +08:00
sz_main.c Unify the void cast usage 2020-01-02 23:21:01 +08:00
zm_proto.c apps/, Various Makefiles: Fix mixed references to nuttx/lib. These need to be changed to nuttx/staging. 2018-05-30 11:08:13 -06:00
zm_receive.c Run codespell -w against all files 2020-02-22 14:41:36 -06:00
zm_send.c Run codespell -w against all files 2020-02-22 14:41:36 -06:00
zm_state.c fix typo 2020-01-24 22:12:06 +09:00
zm_utils.c Fix minor typos in docs and comments. 2019-09-29 12:53:39 -06:00
zm_watchdog.c A few more zmodem files; still missing a few but those are still fragile and like to undergo some resign before they are usable 2013-07-12 16:28:35 -06:00
zm.h system: zmodem: Improve zmodem send performance 2020-01-08 20:43:39 +08:00

README
======

Contents
========

  o Buffering Notes
    - Hardware Flow Control
    - RX Buffer Size
    - Buffer Recommendations
  o Using NuttX ZModem with a Linux Host
    - Sending Files from the Target to the Linux Host PC
    - Receiving Files on the Target from the Linux Host PC
  o Building the ZModem Tools to Run Under Linux
  o Status

Buffering Notes
===============

  Hardware Flow Control
  ---------------------
  Hardware flow control must be enabled in serial drivers in order to
  prevent data overrun.  However, in the most NuttX serial drivers, hardware
  flow control only protects the hardware RX FIFO:  Data will not be lost in
  the hardware FIFO but can still be lost when it is taken from the FIFO.
  We can still overflow the serial driver's RX buffer even with hardware
  flow control enabled! That is probably a bug.  But the workaround solution
  that I have used is to use lower data rates and a large serial driver RX
  buffer.

  Those measures should be unnecessary if buffering and hardware flow
  control are set up and working correctly.

  Software Flow Control
  ---------------------
  The ZModem protocol has XON/XOFF flow control built into it.  The protocol
  permits XON or XOFF characters placed at certain parts of messages.  If
  software flow control is enabled on the receiving end it will consume the
  XONs and XOFFs.  Otherwise they will be ignored in the data by the ZModem
  logic.

  NuttX, however, does not implement XON/XOFF flow control so these do
  nothing. On NuttX you will have to use hardware flow control in most cases.

  The XON/XOFF controls built into ZModem could be used if you enabled
  software flow control in the host.  But that would only work in one
  direction:  If would prevent the host from overrunning the the target Rx
  buffering.  So you should be able to do host-to-target software flow
  control.  But there would still be no target-to-host flow control.  That
  might not be an issue because the host is usually so much faster than
  that target.

  RX Buffer Size
  --------------
  The ZModem protocol supports a message that informs the file sender of
  the maximum size of data that you can buffer (ZRINIT).  However, my
  experience is that the Linux sz ignores this setting and always sends file
  data at the maximum size (1024) no matter what size of buffer you report.
  That is unfortunate because that, combined with the possibilities of data
  overrun mean that you must use quite large buffering for ZModem file
  receipt to be reliable (none of these issues effect sending of files).

  Buffer Recommendations
  ----------------------
  Based on the limitations of NuttX hardware flow control and of the Linux
  sz behavior, I have been testing with the following configuration
  (assuming UART1 is the ZModem device):

    1) This setting determines that maximum size of a data packet frame:

       CONFIG_SYSTEM_ZMODEM_PKTBUFSIZE=1024

    2) Input Buffering.  If the input buffering is set to a full frame, then
       data overflow is less likely.

       CONFIG_UART1_RXBUFSIZE=1024

    3) With a larger driver input buffer, the ZModem receive I/O buffer can be
       smaller:

       CONFIG_SYSTEM_ZMODEM_RCVBUFSIZE=256

    4) Output buffering.  Overrun cannot occur on output (on the NuttX side)
       so there is no need to be so careful:

       CONFIG_SYSTEM_ZMODEM_SNDBUFSIZE=512
       CONFIG_UART1_TXBUFSIZE=256

Using NuttX ZModem with a Linux Host
====================================

    Sending Files from the Target to the Linux Host PC
    --------------------------------------------------
    The NuttX ZModem commands have been verified against the rzsz programs
    running on a Linux PC.  To send a file to the PC, first make sure that
    the serial port is configured to work with the board (Assuming you are
    using 9600 baud for the data transfers -- high rates may result in data
    overruns):

      $ sudo stty -F /dev/ttyS0 9600     # Select 9600 BAUD
      $ sudo stty -F /dev/ttyS0 crtscts  # Enables CTS/RTS handshaking *
      $ sudo stty -F /dev/ttyS0 raw      # Puts the TTY in raw mode
      $ sudo stty -F /dev/ttyS0          # Show the TTY configuration

      * Only if hardware flow control is enabled.

    Start rz on the Linux host (using /dev/ttyS0 as an example):

      $ sudo rz </dev/ttyS0 >/dev/ttyS0

    You can add the rz -v option multiple times, each increases the level
    of debug output.  If you want to capture the Linux rz output, then
    re-direct stderr to a log file by adding 2>rz.log to the end of the
    rz command.

    NOTE: The NuttX ZModem does sends rz\n when it starts in compliance with
    the ZModem specification.  On Linux this, however, seems to start some
    other, incompatible version of rz.  You need to start rz manually to
    make sure that the correct version is selected.  You can tell when this
    evil rz/sz has inserted itself because you will see the '^' (0x5e)
    character replacing the standard ZModem ZDLE character (0x19) in the
    binary data stream.

    If you don't have the rz command on your Linux box, the package to
    install rzsz (or possibily lrzsz).

    Then on the target (using /dev/ttyS1 as an example).

      > sz -d /dev/ttyS1 <filename>

    Where filename is the full path to the file to send (i.e., it begins
    with the '/' character).  /dev/ttyS1 or whatever device you select
    *MUST* support Hardware flow control in order to throttle therates of
    data transfer to fit within the allocated buffers.

    Receiving Files on the Target from the Linux Host PC
    ----------------------------------------------------
    NOTE:  There are issues with using the Linux sz command with the NuttX
    rz command. See "Status" below.  It is recommended that you use the
    NuttX sz command on Linux as described in the next paragraph.

    To send a file to the target, first make sure that the serial port on the
    host is configured to work with the board (Assuming that you are using
    9600 baud for the data transfers -- high rates may result in data
    overruns):

      $ sudo stty -F /dev/ttyS0 9600     # Select 9600 (or other) BAUD
      $ sudo stty -F /dev/ttyS0 crtscts  # Enables CTS/RTS handshaking *
      $ sudo stty -F /dev/ttyS0 raw      # Puts the TTY in raw mode
      $ sudo stty -F /dev/ttyS0          # Show the TTY configuration

     * Only is hardware flow control is enabled.

    Start rz on the on the target.  Here, in this example, we are using
    /dev/ttyS1 to perform the transfer

      nsh> rz -d /dev/ttyS1

    /dev/ttyS1 or whatever device you select *MUST* support Hardware flow
    control in order to throttle therates of data transfer to fit within the
    allocated buffers.

    Then use the sz command on Linux to send the file to the target:

      $ sudo sz <filename> [-l nnnn] [-w nnnn] </dev/ttyS0 >/dev/ttyS0

    Where <filename> is the file that you want to send. If -l nnnn and -w nnnn
    is not specified, then there will likely be packet buffer overflow errors.
    nnnn should be set to a value less than or equal to
    CONFIG_SYSTEM_ZMODEM_PKTBUFSIZE

    The resulting file will be found where you have configured the ZModem
    "sandbox" via CONFIG_SYSTEM_ZMODEM_MOUNTPOINT.

    You can add the sz -v option multiple times, each increases the level
    of debug output.  If you want to capture the Linux sz output, then
    re-direct stderr to a log file by adding 2>sz.log to the end of the
    sz command.

    If you don't have the sz command on your Linux box, the package to
    install rzsz (or possibily lrzsz).

Building the ZModem Tools to Run Under Linux
============================================

  Build support has been added so that the NuttX ZModem implementation
  can be executed on a Linux host PC.  This can be done by

    - Change to the apps/systems/zmodem directory
    - Make using the special makefile, Makefile.host

  NOTES:

  1. TOPDIR and APPDIR must be defined on the make command line:  TOPDIR is
     the full path to the nuttx/ directory;  APPDIR is the full path to the
     apps/ directory.  For example, if you installed nuttx at
     /home/me/projects/nuttx and apps at /home/me/projects/apps, then the
     correct make command line would be:

       make -f Makefile.host TOPDIR=/home/me/projects/nuttx APPDIR=/home/me/projects/apps

  2. Add CONFIG_DEBUG_FEATURES=1 to the make command line to enable debug output
  3. Make sure to clean old target .o files before making new host .o files.

  This build is has been verified as of 2013-7-16 using Linux to transfer
  files with an Olimex LPC1766STK board.  It works great and seems to solve
  all of the problems found with the Linux sz/rz implementation.

Status
======
    2013-7-15: Testing against the Linux rz/sz commands.

      I have tested with the boards/arm/lpc17xx_40xx/olimex-lpc1766stk
      configuration.  I have been able to send large and small files with
      the target sz command. I have been able to receive small files, but
      there are problems receiving large files using the Linux sz command:
      The Linux sz does not obey the buffering limits and continues to send
      data while rz is writing the previously received data to the file and
      the serial driver's RX buffer is overrun by a few bytes while the
      write is in progress. As a result, when it reads the next buffer of
      data, a few bytes may be missing.  The symptom of this missing data is
      a CRC check failure.

      Either (1) we need a more courteous host application, or (2) we
      need to greatly improve the target side buffering capability!

      My thought now is to implement the NuttX sz and rz commands as
      PC side applications as well.  Matching both sides and obeying
      the handshaking will solve the issues.  Another option might be
      to fix the serial driver hardware flow control somehow.

    2013-7-16. More Testing against the Linux rz/sz commands.

      I have verified that with debug off and at lower serial BAUD
      (2400), the transfers of large files succeed without errors.  I do
      not consider this a "solution" to the problem.  I also found that
      the LPC17xx hardware flow control caused strange hangs; ZModem
      works better with hardware flow control disabled on the LPC17xx.

      At this lower BAUD, RX buffer sizes could probably be reduced; Or
      perhaps the BAUD coud be increased.  My thought, however, is that
      tuning in such an unhealthy situation is not the approach:  The
      best thing to do would be to use the matching NuttX sz on the Linux
      host side.

    2013-7-16. More Testing against the NuttX rz/sz on Both Ends.

      The NuttX sz/rz commands have been modified so that they can be
      built and executed under Linux.  In this case, there are no
      transfer problems at all in either direction and with large or
      small files.  This configuration could probably run at much higher
      serial speeds and with much smaller buffers (although that has not
      been verified as of this writing).

    2018-5-27:
      Updates to checksum calculations.  Verified correct operation with
      hardware flow control using the olimex-stm32-p407/zmodem
      configuration.  Only the host-to-target transfer was verified.

      This was using the Linux sz utility.  There appears to still be a
      problem using the NuttX sz utility running on Linux.

    2018-5-27:
      Verified correct operation with hardware flow control using the
      olimex-stm32-p407/zmodem configuration with target-to-host
      transfers was verified.  Again, there are issues remaining if
      I tried the NuttX rz utility running on Linux.

    2018-6-26:
      with -w nnnn option, the host-to-target transfer can work reliably
      without hardware flow control.