Skip to content

Instantly share code, notes, and snippets.

@Julio-Guerra
Last active August 19, 2016 19:59
Show Gist options
  • Save Julio-Guerra/0110b478c7950d67c6c90d68f9031627 to your computer and use it in GitHub Desktop.
Save Julio-Guerra/0110b478c7950d67c6c90d68f9031627 to your computer and use it in GitHub Desktop.
KMTronic FTDI USB-Serial out of sync test case

Content

U2CR test-case:

  • test.sh: test running P1 and P2 interleaved until the error is detected.
  • p1.sh: process P1 which creates problems.
  • p2.sh: process P2 which detect the problem.

Description

Process 1 p1.sh:

    1. Send a status request, like "\xff\x01\x03"
    1. Do not read the answer.

Process 2 p2.sh:

    1. Send another status request, like "\xFF\x02\x03"
    1. Read the answer
    1. Check the answer is the good one : \xFF\x02\xXX"

The problem can happen at point 2 of process 2 where in fact you can receive the status requested by process 1.

Usage examples

root@nuclab:~/u2cr-unsync# ./test.sh /dev/ttyUSB0
answer received:
01ff0a
data received then:
020a
answer expected: FF02XX
the expected answer is out-of-sync - offsetted by P1 request
the answer can be truncated because linux ftdi driver reset the device which flushes the RX/TX FIFOS
root@nuclab:~/u2cr-unsync# ./test.sh /dev/ttyUSB0
answer received:
ff010a
data received then:
ff020a
answer expected: FF02XX
the expected answer is out-of-sync - offsetted by P1 request
the answer can be truncated because linux ftdi driver reset the device which flushes the RX/TX FIFOS

Explanation

Given the facts that:

  1. The linux driver ftdi_sio resets the ftdi chipset which flushes the RX and TX FIFOs.
  2. The USB data is read by polling the ftdi device (debugged using wireshark on usbmon). There are no interrupts.
  3. Flushing the kernel TTY FIFOs using tcflush() after flushing the USB FIFOs does not solve the issue.

It means the KMTronic device behing the FTDI device is processing the request during the USB or TTY flush operations. Which explains why all or part of the previous unterminated answer of P1 is received by P2.

uname -a

Linux nuclab 4.5.0-2-amd64 #1 SMP Debian 4.5.4-1 (2016-05-16) x86_64 GNU/Linux

lscpu

Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                1
On-line CPU(s) list:   0
Thread(s) per core:    1
Core(s) per socket:    1
Socket(s):             1
NUMA node(s):          1
Vendor ID:             GenuineIntel
CPU family:            6
Model:                 55
Model name:            Intel(R) Atom(TM) CPU  E3815  @ 1.46GHz
Stepping:              3
CPU MHz:               533.194
CPU max MHz:           1466.3000
CPU min MHz:           533.2000
BogoMIPS:              2930.40
Virtualization:        VT-x
L1d cache:             24K
L1i cache:             32K
L2 cache:              512K
NUMA node0 CPU(s):     0
Flags:                 fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm sse4_1 sse4_2 movbe popcnt tsc_deadline_timer aes rdrand lahf_lm 3dnowprefetch epb tpr_shadow vnmi flexpriority ept vpid tsc_adjust smep erms dtherm arat
#!/bin/bash
# P1 is a process behaving badly: requesting the state of relay 1
# and does not read the answer for any reason (killed, power cut...).
: ${1?"missing argument 1: device node (e.g. /dev/ttyUSB0)"}
dev=$1
echo -ne "\xFF\x01\x03" > $dev
#!/bin/bash
# P2 is a process behaving correctly: requesting the state of relay 2
# and reading the answer. It then checks the answer is correctly
# formatted: on or off state for the relay 2.
: ${1?"missing argument 1: device node (e.g. /dev/ttyUSB0)"}
dev=$1
# set the device in raw mode
stty -F $dev 9600 raw min 1
# open the device using the file descriptor 4
exec 4<>$dev
echo -n $'\xFF\x02\x03' >&4
# read the answer: exactly 3 bytes
# dd is used because it does not change the tty settings and
# does not expect ascii.
answer=$(dd bs=1 count=3 <&4 2>&-)
# check the anwer
off=$'\xFF\x02\x00'
on=$'\xFF\x02\x01'
if [ $answer = $on ] || [ $answer = $off ]; then
rc=0
else
rc=1
function dump() {
hexdump -e '1/1 "%.2x"'
# newline
echo
}
echo "buffer received:"
echo -n $answer | dump
echo "buffer received after:"
# give the kernel lots of time so that it receives what is left
sleep 1s
# read up to 1024 bytes
answer=$(dd bs=1024 count=1 <&4 2>&-)
echo -n $answer | dump
fi
# close the file descriptor
exec 4>&-
exit $rc
#!/bin/bash
: ${1?"missing argument 1: device node (e.g. /dev/ttyUSB0)"}
dev=$1
# run until an unexpected buffer is received
while ./p2.sh $dev; do
./p1.sh $dev
./p1.sh $dev
./p1.sh $dev
./p1.sh $dev
./p1.sh $dev
./p1.sh $dev
./p1.sh $dev
./p1.sh $dev
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment