Hi Folks,
After a long time I
manged to write this post. We are well aware of inter-process
communication for data exchange between processes, here we are now
going to discuss the reliable means of data transfer between two CPUs
running Linux over UART interface.
PPP (Point-to-Point
Protocol) is a specification for transmission of network data over
point-to-point links, in simple words it provides TCP/IP across a
serial link. Over internet you can find lot of information over PPP
and I am not going to discuss here.
This post mainly
focuses on configuration PPP services on a embedded device running
Linux. I choose an ARM based CPU with buildroot filesystem.
In one of the designs
I worked on, we had UART interface between two ARM CPUs, cross
connected like in null-modem cable. Tx line of UART from one CPU is
connected to Rx line of the other CPU UART, similarly Rx is connected
to Tx with a common ground as shown in the below Figure-1. Both the
CPUs are running Linux (4.4.41+) with buildroot filesystem.
Figure-1: UART cross
connection between two CPUs
UART interface between
the CPUs was intended for command/data exchange in the design, I
though I can implement a standalone c-application on either side for
data transfer and achieve functionality. Realized application will
grow in complexity if at all we had to do implement transfer of files
between the CPUs over UART or if multiple application want to use the
same interface then synchronization comes into picture, considering
all these I decided to choose PPP communication protocol. Using PPP
will ease all the development efforts as CPUs see each other as a
network device with fixed IP, hence you can use all standard network
tools like ssh, scp, ping ..etc. and for custom application to do
command/data exchange start developing it as a socket program, and
works even if the UART is replaced by another physical interface say
Ethernet.
We go through a set of steps enabling support right from Kernel, Buildroot & PPP configuration options to filesystem.
Enable PPP in Kernel
from menuconfig
"Device Drivers --> Network device support" enable
following
CONFIG_PPP=y
CONFIG_PPP_FILTER=y
CONFIG_PPP_ASYNC=y
I have observed below
configs are enabled as well, could have be dependencies.
CONFIG_SLHC=y
CONFIG_CRC_CCITT=y
CONFIG_NF_NAT_PROTO_GRE=m
CONFIG_NF_NAT_PPTP=m
CONFIG_NF_NAT_PPTP=m
CONFIG_NF_CONNTRACK=y
CONFIG_NF_CONNTRACK_PROCFS=y
CONFIG_NF_CT_PROTO_GRE=y
CONFIG_NF_CT_PROTO_SCTP=m
CONFIG_NF_CONNTRACK_PPTP=y
CONFIG_NF_CONNTRACK_PROCFS=y
CONFIG_NF_CT_PROTO_GRE=y
CONFIG_NF_CT_PROTO_SCTP=m
CONFIG_NF_CONNTRACK_PPTP=y
Figure2: Menuconfig
to enable PPP in kernel
Enable PPP in Buildroot
from menuconfig
"Target packages --> Networking applications" enable
"pppd"
Figure3: Menuconfig
to enable PPP service in buildroot
Enabling PPP Communication
One of the CPU is
regarded as server say CPU-1 and the other as client say CPU-2. UART
device node on CPU-1 is "/dev/ttyS1" and on that of CPU-2
is "/dev/ttyS0". In Linux PPP is implemented by "pppd"
daemon. All its configuration files are available at "/etc/ppp",
in this processes we will either create or modifying the following
list of files.
- /etc/ppp/options
- Contains all general configuration options of PPP service
- /etc/ppp/options.ttyS1
- Contains PPP options specific to UART connection over /dev/ttyS1
- /etc/ppp/pap-secrets
- Contains authentication information
Server Configurations (on CPU-1)
Note: The lines starting with a "#" are comments.
$ vi /etc/ppp/options
#/etc/ppp/options lock auth login
- lock : Parameter indicates that a lock file will be created to ensure exclusive access to the serial device.
- auth: Parameter indicates that the client will need to authenticate itself, it will still use pap-secrets for username & password information during authentication.
- login: Parameter tell pppd to use the system user names and passwords for authentication.
$ vi /etc/ppp/pap-secrets
#/etc/ppp/pap-secrets # Secrets for authentication using PAP # client server secret IP addresses * * "" *
The only line, in the file allows any machine with any IP address to connect to the server without using a password. "login" parameter specified in the "/etc/ppp/options" file makes that the username and password supplied by the client for authorization have to match the "/etc/ppp/pap-secrets" file as well as the system user name and password, so the connection will only succeed after a valid username and password are provided.
$ vi /etc/ppp/options.ttyS1
Options specific to the serial line we are connecting with, are placed in "/etc/ppp/options.ttySn", where n is the number of the serial device. In our case Server/CPU-1 is using "/dev/ttyS1", hence the options go into the file with name "/etc/ppp/options.ttyS1"
Options specific to the serial line we are connecting with, are placed in "/etc/ppp/options.ttySn", where n is the number of the serial device. In our case Server/CPU-1 is using "/dev/ttyS1", hence the options go into the file with name "/etc/ppp/options.ttyS1"
#/etc/options.ttyS1 asyncmap 0 local silent 192.168.0.1:192.168.1.1 require-pap 115200 xonxoff
- local: Indicates modem lines are not used
- silent: Causes pppd to wait until a connection is made from other side
- xonxoff: The better flow control is CTS/RTS. However, if you
can not do the hardware flow control with the signals CTS and
RTS, then use XON/XOFF. In the Figure-1 we are just using Tx & Rx lines only.
- asyncmap: This parameter is used when software control is used in conjunction with xonxoff, please refer man page.
- 192.168.0.1:192.168.1.1 This entry specifies the local and remote IP address to be assigned after the link is up. Server/CPU-1 is given IP 192.168.0.1 and the Client/CPU-2 is given IP 192.168.1.1.
- 115200: Specifies the baud-rate on serial-link.
Client Configurations (on CPU-2)
On client side it is pretty easy, following are the list of files
$ vi /etc/ppp/options
#/etc/ppp/options lock
$ vi /etc/ppp/pap-secrets
# Secrets for authentication using PAP # client server secret IP addresses root * root #
So user "root" uses password "root"
$ vi /etc/ppp/options.ttyS0
Options specific to the serial line we are connecting with, are placed in "/etc/ppp/options.ttySn", where n is the number of the serial device. In our case Server/CPU-1 is using "/dev/ttyS1", hence the options go into the file with name "/etc/ppp/options.ttyS1"
Options specific to the serial line we are connecting with, are placed in "/etc/ppp/options.ttySn", where n is the number of the serial device. In our case Server/CPU-1 is using "/dev/ttyS1", hence the options go into the file with name "/etc/ppp/options.ttyS1"
#/etc/options.ttyS0 115200 local xonxoff user root noauth
now that all configuration files are in place, its time to run the pppd services on CPU-1 & CPU-2
Running PPPD Services on Server & Client
It is understood that you have serial console access to shell of both CPU using the popular utilities like gtkterm or cutecome .etc.
Server Side
On CPU-1 that is server, run the pppd service in background as shown below
# pppd /dev/ttyS1 nodetach &
You see the following output, server is now waiting indefinitely for clients request.# pppd /dev/ttyS1 nodetach & # Using interface ppp0 Connect: ppp0 <--> /dev/ttyS1
Client Side
On CPU-2 that is client, run the pppd service in background as shown below.# pppd /dev/ttyS0 nodetach &
You see the following output, client has established the connection with server and has obtained the IP-address as 192.168.1.1.# pppd /dev/ttyS0 nodetach & # Using interface ppp0 Connect: ppp0 <--> /dev/ttyS0 Warning - secret file /etc/ppp/pap-secrets has world and/or group access Warning - secret file /etc/ppp/pap-secrets has world and/or group access Remote message: Session started successfully PAP authentication succeeded local IP address 192.168.1.1 remote IP address 192.168.0.1
After the client established connection with server, following is the server log with local IP assigned to 192.168.0.1 and client IP over ppp0 interface assigned to 192.168.1.1
#Warning - secret file /etc/ppp/pap-secrets has world and/or group access Warning - secret file /etc/ppp/pap-secrets has world and/or group access user root logged in on tty ttyS4 intf ppp0 PAP peer authentication succeeded for root local IP address 192.168.0.1 remote IP address 192.168.1.1
You can now ping client from server and vice versa
On server side
# ifconfig ppp0 ppp0 Link encap:Point-to-Point Protocol inet addr:192.168.0.1 P-t-P:192.168.1.1 Mask:255.255.255.255 UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1 RX packets:91 errors:0 dropped:0 overruns:0 frame:0 TX packets:91 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:3 RX bytes:4907 (4.7 KiB) TX bytes:4904 (4.7 KiB) # # ping 192.168.1.1 PING 192.168.1.1 (192.168.1.1): 56 data bytes 64 bytes from 192.168.1.1: seq=0 ttl=64 time=16.590 ms 64 bytes from 192.168.1.1: seq=1 ttl=64 time=16.637 ms ^C --- 192.168.1.1 ping statistics --- 2 packets transmitted, 2 packets received, 0% packet loss round-trip min/avg/max = 16.590/16.613/16.637 ms #
On client side
# ifconfig ppp0 ppp0 Link encap:Point-to-Point Protocol inet addr:192.168.1.1 P-t-P:192.168.0.1 Mask:255.255.255.255 UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1 RX packets:103 errors:0 dropped:0 overruns:0 frame:0 TX packets:103 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:3 RX bytes:5546 (5.4 KiB) TX bytes:5549 (5.4 KiB) # ping 192.168.0.1 PING 192.168.0.1 (192.168.0.1): 56 data bytes 64 bytes from 192.168.0.1: seq=0 ttl=64 time=16.592 ms 64 bytes from 192.168.0.1: seq=1 ttl=64 time=16.354 ms 64 bytes from 192.168.0.1: seq=2 ttl=64 time=16.527 ms ^C --- 192.168.0.1 ping statistics --- 3 packets transmitted, 3 packets received, 0% packet loss round-trip min/avg/max = 16.354/16.491/16.592 ms #