Partial fixes for Zmodem RX buffering problems.

This commit is contained in:
Gregory Nutt 2013-07-15 12:33:35 -06:00
parent ff9554097e
commit df4fb5a4cc
2 changed files with 134 additions and 42 deletions

View File

@ -1068,21 +1068,81 @@ Where <subdir> is one of the following:
1. UART0 is still the NuttX serial console as with most of the other
configurations here. However, UART1 is also enabled for performing
the Zmodem transfers. Zmodem transfers can be performed on the
console device, however, this configuration permits debug output on
the serial console which the transfer is in progress without
interfering with the file transfer.
the Zmodem transfers.
CONFIG_LPC17XX_UART1=y
CONFIG_UART1_ISUART=y
CONFIG_UART1_RXBUFSIZE=256
CONFIG_UART1_RXBUFSIZE=512
CONFIG_UART1_TXBUFSIZE=256
CONFIG_UART1_BAUD=115200
CONFIG_UART1_BAUD=9600
CONFIG_UART1_BITS=8
CONFIG_UART1_PARITY=0
CONFIG_UART1_2STOP=0
2. Support is included for the NuttX sz and rz commands. In order to
2. Hardware Flow Control
In principle, Zmodem transfers could be performed on the any serial
device, including the console device. However, only the LPC17xx
UART1 supports hardware flow control which is required for Zmodem
trasnfers. Also, this configuration permits debug output on the
serial console while the transfer is in progress without interfering
with the file transfer.
In additional, a very low BAUD is selected to avoid other sources
of data overrun. This should be unnecessary if buffering and hardware
flow control are set up correctly.
However, in the LPC17xx serial driver, 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.
3. Buffering Notes:
RX Buffer Size
--------------
The Zmodem protocol supports a message that informs the file sender
of the maximum size of dat 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):
a) This setting determines that maximum size of a data packet frame:
CONFIG_SYSTEM_ZMODEM_PKTBUFSIZE=1024
b) Input Buffering. If the input buffering is set to a full frame,
then data overflow is less likely.
CONFIG_UART1_RXBUFSIZE=1024
c) With a larger driver input buffer, the Zmodem receive I/O buffer
can be smaller:
CONFIG_SYSTEM_ZMODEM_RCVBUFSIZE=256
d) 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
4. Support is included for the NuttX sz and rz commands. In order to
use these commands, you will need to mount the SD card so that you
will have a file system to transfer files in and out of:
@ -1097,52 +1157,64 @@ Where <subdir> is one of the following:
Hmmm.. I probably should set up an NSH script to just mount /dev/mmcsd0
at /mnt/sdcard each time the board boots.
3. Sending Files from the Target to the Linux Host PC
4. Sending Files from the Target to the Linux Host PC
This program has 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:
This program has 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:
$ sudo stty -F /dev/ttyS0 57600
$ sudo stty -F /dev/ttyS0
$ sudo stty -F /dev/ttyS0 9600 # Select 9600 BAUD
$ sudo stty -F /dev/ttyS0 crtscts # Enables CTS/RTS handshaking
$ sudo stty -F /dev/ttyS0 # Show the TTY configuration
Start rz on the Linux host:
Start rz on the Linux host:
$ sudo rz </dev/ttyS0 >/dev/ttyS0
$ sudo rz </dev/ttyS0 >/dev/ttyS0
You can add the rz -v option multiple times, each increases the level
of debug output.
You can add the rz -v option multiple times, each increases the level
of debug output.
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.
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).
If you don't have the rz command on your Linux box, the package to
install rzsz (or possibily lrzsz).
Then on the target:
Then on the target:
> sz -d /dev/ttyS1 <filename>
> sz -d /dev/ttyS1 <filename>
Where filename is the full path to the file to send (i.e., it begins
with the '/' character).
Where filename is the full path to the file to send (i.e., it begins
with the '/' character).
4. Receiving Files on the Target from the Linux Host PC
/dev/ttyS1 is configured to support Hardware flow control in order to
throttle therates of data transfer to fit within the allocated buffers.
Other devices may be used but if they do not support hardware flow
control, the transfers will fail
5. Receiving Files on the Target from the Linux Host PC
To send a file to the target, first make sure that the serial port on
the host is configured to work with the board:
$ sudo stty -F /dev/ttyS0 57600
$ sudo stty -F /dev/ttyS0
$ sudo stty -F /dev/ttyS0 9600 # Select 9600 BAUD
$ sudo stty -F /dev/ttyS0 crtscts # Enables CTS/RTS handshaking
$ sudo stty -F /dev/ttyS0 # Show the TTY configuration
Start rz on the on the target:
nsh> rz -d /dev/ttyS1
/dev/ttyS1 is configured to support Hardware flow control in order to
throttle therates of data transfer to fit within the allocated buffers.
Other devices may be used but if they do not support hardware flow
control, the transfers will fail
Then use the sz command on Linux to send the file to the target:
$ sudo sz <filename> t </dev/ttyS0 >/dev/ttyS0
@ -1161,3 +1233,20 @@ Where <subdir> is one of the following:
If you don't have the az command on your Linux box, the package to
install rzsz (or possibily lrzsz).
STATUS
2013-7-15: I have been able to send large and small files with the
sz command. I have been able to receive small files, but there are
problems receiving large files: 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 (maybe 10). 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.

View File

@ -357,7 +357,7 @@ CONFIG_UART0_SERIAL_CONSOLE=y
#
# UART0 Configuration
#
CONFIG_UART0_RXBUFSIZE=256
CONFIG_UART0_RXBUFSIZE=1024
CONFIG_UART0_TXBUFSIZE=256
CONFIG_UART0_BAUD=57600
CONFIG_UART0_BITS=8
@ -371,14 +371,14 @@ CONFIG_UART0_2STOP=0
#
CONFIG_UART1_RXBUFSIZE=256
CONFIG_UART1_TXBUFSIZE=256
CONFIG_UART1_BAUD=57600
CONFIG_UART1_BAUD=9600
CONFIG_UART1_BITS=8
CONFIG_UART1_PARITY=0
CONFIG_UART1_2STOP=0
# CONFIG_UART1_IFLOWCONTROL is not set
# CONFIG_UART1_OFLOWCONTROL is not set
# CONFIG_SERIAL_IFLOWCONTROL is not set
# CONFIG_SERIAL_OFLOWCONTROL is not set
CONFIG_UART1_IFLOWCONTROL=y
CONFIG_UART1_OFLOWCONTROL=y
CONFIG_SERIAL_IFLOWCONTROL=y
CONFIG_SERIAL_OFLOWCONTROL=y
# CONFIG_USBDEV is not set
# CONFIG_USBHOST is not set
# CONFIG_WIRELESS is not set
@ -793,11 +793,12 @@ CONFIG_READLINE_ECHO=y
# Zmodem Commands
#
CONFIG_SYSTEM_ZMODEM=y
CONFIG_SYSTEM_ZMODEM_RCVBUFSIZE=512
CONFIG_SYSTEM_ZMODEM_PKTBUFSIZE=512
CONFIG_SYSTEM_ZMODEM_DEVNAME="/dev/ttyS1"
CONFIG_SYSTEM_ZMODEM_RCVBUFSIZE=256
CONFIG_SYSTEM_ZMODEM_PKTBUFSIZE=1024
CONFIG_SYSTEM_ZMODEM_SNDBUFSIZE=512
CONFIG_SYSTEM_ZMODEM_MOUNTPOINT="/mnt/sdcard"
CONFIG_SYSTEM_ZMODEM_SENDSAMPLE=y
# CONFIG_SYSTEM_ZMODEM_RCVSAMPLE is not set
CONFIG_SYSTEM_ZMODEM_SENDATTN=y
CONFIG_SYSTEM_ZMODEM_ALWAYSSINT=y
# CONFIG_SYSTEM_ZMODEM_FULLSTREAMING is not set
@ -805,3 +806,5 @@ CONFIG_SYSTEM_ZMODEM_ALWAYSSINT=y
# CONFIG_SYSTEM_ZMODEM_RESPTIME is not set
CONFIG_SYSTEM_ZMODEM_SERIALNO=0
CONFIG_SYSTEM_ZMODEM_MAXERRORS=20
CONFIG_SYSTEM_ZMODEM_WRITESIZE=512
# CONFIG_DEBUG_ZMODEM is not set