Hello,
I have several custom boards that are based on the imx6dl and imx6q. Each of the boards has the following configuration:
1) Two hardware uart ports (ttymxc), connected to the PC with rs232 port.
2) Yocto linux Dizzy with 3.10.17 linux kernel (i have also tried 3.14 and 3.18 linux kernels)
All uarts work well except for zmodem transmission protocol. When I try to send or receive file from/to PC with zmodem I get transmission error.
Log from imx6dl board (stty settings are the same on the both sides) (zmodem that included in minicom also doesn`t work):
root@imx6s-target:~# stty -F /dev/ttymxc3 time 0 -inlcr -igncr -icrnl -opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill -ofdel -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke -ixon 9600
root@imx6s-target:~# rz --zmodem > /dev/ttymxc3 < /dev/ttymxc3
rz waiting to receive.Retry 0: Got ZCAN
got ZCAN
Transfer incomplete
root@imx6s-target:~# sz --zmodem ./20k > /dev/ttymxc3 < /dev/ttymxc3
Sending: 20k
}U0Retry 0: Got ZCAN
got ZCAN
Transfer incomplete
What should I do to make zmodem work?
Thanks in advance.
Solved! Go to Solution.
Hi Ktulhu Uchiha,
Here is the test on the i.MX6 sabreSD board.
rz:
sz:
Thank you for your answer.
It helps me to understand that I used zmodem in wrong way.
Thus I`ve also found that zmodem worked well on imx6 uarts.
But in the rs485 mode, that was added in the latest versions of linux kernel, zmodem gives many errors (it can be caused by hardware problems with rs485 converter).
However, we decided to not investigate this problem further.
Maybe it will be helpful for somebody:
To test zmodem I`ve used the following ports configuration (“root@imx6s-kts” – target imx6 based board, “user@user-desktop” – usual x86 based host connected to the target board through usb to rs232 converter):
root@imx6s-kts:~# stty -a -F /dev/ttymxc3
speed 115200 baud; rows 0; columns 0; line = 0;
intr = M-^?; quit = <undef>; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R;
werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 1;
-parenb -parodd -cmspar cs8 -hupcl -cstopb cread clocal -crtscts
-ignbrk brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl ixon -ixoff -iuclc -ixany -imaxbel -iutf8
-opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
-isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase -tostop -echoprt -echoctl -echoke
root@imx6s-kts:~# stty -g -F /dev/ttymxc3
402:0:18b2:0:ff:0:7f:15:4:1:1:0:11:13:1a:0:12:f:17:16:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
user@user-desktop:~$ stty -a -F /dev/ttyUSB0
speed 115200 baud; rows 0; columns 0; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W;
lnext = ^V; flush = ^O; min = 1; time = 0;
-parenb -parodd cs8 -hupcl -cstopb cread clocal -crtscts
ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany -imaxbel -iutf8
-opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
-isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase -tostop -echoprt -echoctl -echoke
user@user-desktop:~$ stty -g -F /dev/ttyUSB0
1:0:18b2:0:3:1c:7f:15:4:0:1:0:11:13:1a:0:12:f:17:16:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
Then I`ve run the following commands on the target and the host respectively:
root@imx6s-kts:~# lsz --zmodem testFile2.txt > /dev/ttymxc3 < /dev/ttymxc3
user@user-desktop:~$ sudo rz --zmodem > /dev/ttyUSB0 < /dev/ttyUSB0
rs485 9bit mode, you need to modify the driver code.
Because RS-485 bit 8 is carried by the parity bit.
Biyong Sun,
Thank you.
But we use rs485 in 8 bit mode (we use the following patch: https://github.com/torvalds/linux/commit/17b8f2a3fdca29a9b296642fb3f6ad3c39ffc7d3 )
The patch depends on the RTS pin.
And it should not be a common solution.
If you want to use zmodem in RS458 mode. You should write down the special code.
At least , the mode should set to RS458 and igore the parity check sum error in driver's interrupt. As I mentioned before, the bit 8(zero-based) is carried by parity bit, which will be treated as error at least the host PC side.
To work in rs485 mode we use "MAX485" connected to imx6 RX, TX, RTS pins. And in common our scheme works well in RS485 mode. If we just send big files from host to imx6 and vice versa (using just "cat file > /dev/ttymxc3") or use modbus protocol, It works well. The problem is, that we found that zmodem doesn`t work properly in RS485 mode, then we tried to test imx uart in usual rs232 mode and it didn`t work too.
But now we know that we used zmodem wrong, and it seems that there is a bug in our hardware or in the RS485 patch.
At least , the mode should set to RS458 and igore the parity check sum error in driver's interrupt. As I mentioned before, the bit 8(zero-based) is carried by parity bit, which will be treated as error at least the host PC side.
It is required only in 9bit mode. But we work in 8bit mode, that bit to bit compatible with rs232 except for the physical layer.
understand what you mentioned.
Ok. You can dump the i.MX6 UART Status Register to see what's wrong..
Hello Ktulhu Uchiha,
I would recommend making sure that the kernel configuration is including the flow control protocol that is required by zmodem or any other options enabled that are required by zmodem.
Thank you for your answer.
But I can`t find any kernel configuration parameters for the serial flow control protocol.
Now I`m using Yocto Linux with 3.19 kernel from Freescale/linux-fslc at patches-3.19 · GitHub (git tag "5fdbf2af0ad0e2f86210f1e9bc61dcbccb79aa73" ).
There is a part of my device tree file:
&uart1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart1_sodimm>;
status = "okay";
};
&uart4 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart4_sodimm>;
fsl,uart-has-rtscts;
status = "okay";
};
&iomuxc {
...
uart4 {
pinctrl_uart4_sodimm: uart4-sodimm {
fsl,pins = <
MX6QDL_PAD_CSI0_DAT17__UART4_CTS_B 0x1b0b1
MX6QDL_PAD_CSI0_DAT16__UART4_RTS_B 0x1b0b1
MX6QDL_PAD_CSI0_DAT13__UART4_RX_DATA 0x1b0b1
MX6QDL_PAD_CSI0_DAT12__UART4_TX_DATA 0x1b0b1
>;
};
};
...
uart1 {
pinctrl_uart1_sodimm: uart1-sodimm {
fsl,pins = <
MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1
MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1
>;
};
};
...
};
Linux defconfig that I use is attached to this message.