zmodem Zmodem Commands
Contents
Buffering Notes
Hardware Flow Control
RX Buffer Size
Buffer Recommendations
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
Building the ZModem Tools to Run Under Linux
Status
Buffering Notes
Hardware Flow Control
Hardware flow control must be enabled in serial drivers in order to prevent data overrun. However, in 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 currently implemented workaround solution 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 XON s
and XOFF s. 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 the 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 affect sending of files).
Buffer Recommendations
Based on the limitations of NuttX hardware flow control and of the Linux sz
behavior, testing was conducted with the following configuration (assuming UART1
is the ZModem device):
This setting determines that maximum size of a data packet frame:
CONFIG_SYSTEM_ZMODEM_PKTBUFSIZE=1024
Input Buffering. If the input buffering is set to a full frame, then data overflow is less likely:
CONFIG_UART1_RXBUFSIZE=1024
With a larger driver input buffer, the ZModem receive I/O buffer can be smaller:
CONFIG_SYSTEM_ZMODEM_RCVBUFSIZE=256
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 possibly lrzsz).
Then on the target (using /dev/ttyS1 as an example):
nsh> 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 the rate 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 is
rzsz (or possibly 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/zmodemdirectoryMake using the special makefile,
Makefile.host
Notes:
TOPDIRandAPPDIRmust be defined on the make command line:TOPDIRis the full path to thenuttx/directory;APPDIRis the full path to theapps/directory. For example, if you installed nuttx at/home/me/projects/nuttxand 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
Add
CONFIG_DEBUG_FEATURES=1to the make command line to enable debug outputMake sure to clean old target
.ofiles before making new host.ofiles.
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 Linuxrz/szcommands.Performed tests with the
boards/arm/lpc17xx_40xx/olimex-lpc1766stkconfiguration. Large and small files were transferred with the targetszcommand. It was possible to receive small files, but there are problems receiving large files using the Linuxszcommand: The Linuxszdoes not obey the buffering limits and continues to send data whilerzis 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
szandrzcommands 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 Linuxrz/szcommands.Verified that with debug off and at lower serial BAUD (
2400), the transfers of large files succeed without errors. This is considered a _solution_ to the problem. In addition 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 could 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 NuttXrz/szon Both Ends.The NuttX
sz/rzcommands 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-27Updates to checksum calculations. Verified correct operation with hardware flow control using the
olimex-stm32-p407/zmodemconfiguration. Only the host-to-target transfer was verified.This was using the Linux
szutility. There appears to still be a problem using the NuttXszutility running on Linux.2018-5-27Verified correct operation with hardware flow control using the
olimex-stm32-p407/zmodemconfiguration with target-to-host transfers was verified. Again, there are issues remaining when using the NuttXrzutility running on Linux.2018-6-26With
-w nnnnoption, the host-to-target transfer can work reliably without hardware flow control.