mirror of
https://github.com/elua/elua.git
synced 2025-01-08 20:56:17 +08:00
284 lines
16 KiB
Plaintext
284 lines
16 KiB
Plaintext
// $$HEADER$$
|
|
The eLua serial multiplexer
|
|
---------------------------
|
|
*(v0.8 and above)* The *serial multiplexer* is an optional eLua component that allows
|
|
using several serial ports over a single physical serial link connection. It can be a
|
|
very convenient feature, since some eLua components (such as link:using.html#rpc[the RPC mechanism]
|
|
or link:arch_rfs.html[the remote file system]) need a serial link to the PC and
|
|
it's very incovenient (or even impossible sometimes) to connect the eLua board
|
|
to the PC with 2 or more serial cables. A common use scenario for the serial
|
|
multiplexer is to have the eLua shell and RFS running over a single physical
|
|
connection to the PC, a very convenient method that will probably appeal to most
|
|
eLua users.
|
|
|
|
How does it work?
|
|
~~~~~~~~~~~~~~~~~
|
|
On the eLua side a number of virtual serial ports are defined. The eLua code
|
|
can use these ports just like they would use a physical port, simply by specifing
|
|
a virtual port ID instead of a physical port ID. On the PC side, two things are
|
|
needed:
|
|
|
|
- a program that can (de)multiplex UART requests from the eLua board. It is called
|
|
*mux* and it is part of the standard eLua distribution.
|
|
- a mechanism for creating and using "virtual serial ports" on the PC itself. These
|
|
are actually pairs of virtual UARTs that are connected internally (inside
|
|
the OS) via a null-modem cable mechanism, which means that when you type something
|
|
on one port you can see its output on its pair (and the other way around).
|
|
|
|
See below for details on how to use virtual serial ports in Linux and Windows.
|
|
|
|
Virtual serial ports in Linux
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
Linux already supports the virtual serial port mechanism described above via the
|
|
standard UNIX pseudo terminals, see http://en.wikipedia.org/wiki/Pseudo_terminal[here]
|
|
for details. Note that the multiplexer supports only BSD PTYs (*dev/ttypx*) and not
|
|
Unix98 PTYs (*/dev/ptmx*). They are quite standard (although they are becoming
|
|
obsolete in some Linux distributions) so you shouldn't have any problems with them.
|
|
A quick check for BSD PTYs is to look in your */dev* directory for *ttypx* and *ptypx* files.
|
|
If they aren't there, you need to enable support for BSD PTYs in your system. How to
|
|
do this is OS dependent and beyond the scope of this tutorial, so google is your friend.
|
|
For an example on how to enable them in Ubuntu check
|
|
http://ubuntuforums.org/showthread.php?t=1147994[this link].
|
|
|
|
Once they are enabled you can get a quick feel of how their work. */dev/ttypx* and */dev/ptypx*
|
|
are paired by default, so any transmit/receive at one end is mirrored at the other end.
|
|
A simple experiment:
|
|
|
|
- start two shell sessions
|
|
- execute *screen /dev/ttyp0 115200* in one of the shells
|
|
- execute *screen /dev/ptyp0 115200* in the other shell
|
|
|
|
Now everything you type in one of the shell sessions should be visible in the other one.
|
|
|
|
Virtual serial ports in Windows
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
Windows doesn't have out-of-the-box support for virtual serial ports, but
|
|
fortunately there's an extremely nice open source program that does exactly
|
|
what eLua needs. It is called http://com0com.sourceforge.net/[com0com]. Download it,
|
|
install it, then open the com0com serial port manager to create your virtual
|
|
serial port pairs. Then give it a little spin to get used to how it works. Supposing
|
|
that you created COM10 and COM11 as a virtual serial port pair, try this:
|
|
|
|
- start your terminal emulator program. My preffered terminal emulator program in
|
|
Windows is http://www.ayera.com/teraterm/[TeraTerm], but you can use any emulator
|
|
you want. Open COM10 at baud 115200.
|
|
- start another instance of the terminal emulator, but this time open COM11 at baud 115200.
|
|
|
|
Now everything you type in one of the terminal emulators should be visible in the other one.
|
|
|
|
NOTE: com0com can create pairs of serial ports with unusual names, for example *CNCA1* and *CNCB1*.
|
|
While they work fine with eLua's serial multiplexer, they might not work equally well with terminal
|
|
emulator programs, so you're advised to stick with standard port names (*COMx*).
|
|
|
|
Enabling the serial multiplexer in Lua
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
This is the easy part, just follow the instruction in the link:building.html[building page].
|
|
You need to define the following macros for the serial multiplexer:
|
|
|
|
[width="90%", cols="<2s,<5", options="header"]
|
|
|===================================================================
|
|
^| Option ^| Meaning
|
|
| BUILD_SERMUX | Enable serial multiplexer support in eLua.
|
|
| SERMUX_PHYS_ID | The ID of the physical UART interface used by the serial multiplexer.
|
|
| SERMUX_PHYS_SPEED | Communication speed of the multiplexer UART interface.
|
|
| SERMUX_FLOW_TYPE | Flow control type on the physical serial multiplexer interface, see link:arch_platform_uart.html#flow_control_type[here] for details.
|
|
If not specified it defaults to \'no flow control'.
|
|
| SERMUX_NUM_VUART | The number of virtual UART interfaces. This number can't be higher than 8.
|
|
| SERMUX_BUFFER_SIZES | An array of *SERMUX_NUM_VUART* integers that specify the buffer sizes for the virtual
|
|
UART interfaces. Note that a virtual UART *MUST* have a buffer associated with it. The sizes are specified as
|
|
*BUF_SIZE_xxx* constants defined in _inc/buf.h_
|
|
|===================================================================
|
|
|
|
As a simple example, let's change the configuration of an eLua board that uses UART 0
|
|
as its console UART to use a serial multiplexer with 2 ports (one for RFS and the other
|
|
one for console) over UART 0. The original configuration (in _src/platform/<platform>/platform_conf.h_)
|
|
will look like this:
|
|
|
|
------------------------------------
|
|
#define CON_UART_ID 0
|
|
#define CON_UART_SPEED 115200
|
|
------------------------------------
|
|
|
|
The new configuration should be similar to the one below:
|
|
|
|
[subs="quotes"]
|
|
------------------------------------
|
|
#include "sermux.h" [bblue]**// for virtual uart IDs**
|
|
#include "buf.h" [bblue]**// for buffer sizes**
|
|
|
|
#define BUILD_SERMUX [bblue]**// enable serial multiplexer support**
|
|
#define CON_UART_ID ( SERMUX_SERVICE_ID_FIRST + 1 ) [bblue]**// console runs on the second virtual UART**
|
|
#define CON_BUF_SIZE BUF_SIZE_128 [bblue]**// size of console UART buffer, cannot be 0**
|
|
#define RFS_UART_ID ( SERMUX_SERVICE_ID_FIRST ) [bblue]**// RFS runs on the first virtual UART**
|
|
#define RFS_BUFFER_SIZE BUF_SIZE_512 [bblue]**// size of the RFS UART buffer, cannot be 0**
|
|
// Serial multiplexer data
|
|
#define SERMUX_PHYS_ID 0 [bblue]**// multiplexer runs on UART 0**
|
|
#define SERMUX_PHYS_SPEED 115200 [bblue]**// multiplexer runs at 115200 baud**
|
|
#define SERMUX_NUM_VUART 2 [bblue]**// multiplexer creates 2 virtual UARTs**
|
|
#define SERMUX_BUFFER_SIZES { RFS_BUFFER_SIZE, CON_BUF_SIZE } [bblue]**// buffer sizes for the virtual UARTs**
|
|
------------------------------------
|
|
|
|
This sequence of macro definitions will enable serial multiplexer support in eLua and will allow the
|
|
code to use two *virtual UARTs*. The virtual UART IDs start at *SERMUX_SERVICE_ID_FIRST*. A maximum
|
|
of 8 virtual UARTs are supported by the system. In this particular example the first virtual UART
|
|
is assigned to RFS and the second one to the system console.
|
|
|
|
IMPORTANT: when using the RFS in a virtual UART configuration, remember that *RFS_UART_ID must be the
|
|
first virtual UART ID in the system (SERMUX_SERVICE_ID_FIRST)*. Otherwise, the serial multiplexer will
|
|
NOT work properly in *rfsmux* mode. Check xref:rfsmux[here] for details, and link:arch_rfs.html[here]
|
|
for more details about the RFS.
|
|
|
|
Serial multiplexer on the PC side
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
The serial multiplexer needs a program running on the PC side, the *mux server*. This is
|
|
the program that implements the actual serial port multiplexing (eLua connects to this program via
|
|
the *SERMUX_PHYS_ID* UART). The mux server was succesfully built and tested under
|
|
Windows 7 (32 bit) and Linux (Ubuntu 64 bit). To build it you need:
|
|
|
|
- a build environment. This means gcc under Linux (see for example link:tc_arm.html[here] for instruction on how to install a toolchain in
|
|
Ubuntu Linux) and a gcc-based development environment under Windows. How to install a gcc-based development environment under Windows is
|
|
beyond the scope of this tutorial, but check http://www.mingw.org/[here] and http://tdm-gcc.tdragon.net/[here] for possible solution
|
|
(the mux server was compiled and tested under Win32 using the second soluation, the tdm gcc compiler).
|
|
- scons. See link:building_win.html[here] for details on how to install scons on Windows, or link:building_unix.html[here] for details on how
|
|
to install scons on Linux.
|
|
|
|
If the above requirements are met, building the mux server is a simple matter of invoking this command from the eLua source tree base directory:
|
|
|
|
---------------
|
|
scons -f mux.py
|
|
---------------
|
|
|
|
After this you should end up with a *mux.exe* file in Windows, or a *mux* file in Linux. Running it without arguments prints
|
|
the usage help:
|
|
|
|
---------------
|
|
Usage: mux <mode> <transport> <vcom1> [<vcom2>] ... [<vcomn>] [-v]
|
|
mode:
|
|
'mux': serial multiplexer mode
|
|
'rfsmux:<directory>: combined RFS and multiplexer mode.
|
|
transport: '<port>,<baud>,<flow> ('flow' specifies the flow control type and can be 'none' or 'rtscts').
|
|
vcom1, ..., vcomn: multiplexer serial ports. Use '-v' for verbose output.
|
|
---------------
|
|
|
|
Using the multiplexer in "mux" mode
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
This is the basic use scenario for the serial multiplexer. Im this mode *mux* will
|
|
simply multiplex the serial connection with the eLua board with a number of virtual
|
|
serial ports in the system.
|
|
|
|
This is best understood by an example. We'll ask *mux*
|
|
to multiplex two serial ports for us, these will be *dev/ptyp0* (and its pair */dev/ttyp0*)
|
|
and */dev/ptyp1* (and its pair */dev/ttyp1*) in Linux and COM10 (and its pair COM11)
|
|
and COM20 (and its pair COM21) in Windows. The physical UART is /dev/ttyUSB0 in
|
|
Linux and COM5 in Windows. So, to run it in Linux, execute this:
|
|
|
|
-------------------------------------------------------
|
|
./mux.exe mux /dev/ttyUSB0,115200,rtscts /dev/ptyp0 /dev/ptyp1
|
|
-------------------------------------------------------
|
|
|
|
In Windows:
|
|
|
|
-------------------------------
|
|
mux mux com5,115200,rtscts com10 com20
|
|
-------------------------------
|
|
|
|
And now let's put this to good use. Remember that in the previous paragraph we
|
|
built an eLua configuration that assigned RFS to the first virtual UART (which corresponds
|
|
to the *vcom1* argument of *mux*) and the console to the second one (which corresponds
|
|
to the *vcom2* argument of *mux*). To make this happen on the PC, we start
|
|
the respective services on the UART pairs of the *vcomx* arguments of *mux*.
|
|
In Linux:
|
|
|
|
-----------------------------------------------------
|
|
./rfs_server ser:/dev/ttyp0,115200,none /home/user/work/fs
|
|
screen /dev/ttyp1 115200
|
|
-----------------------------------------------------
|
|
|
|
In Windows:
|
|
|
|
----------
|
|
rfs_server ser:com11,115200,none c:\elua\fs
|
|
(also run TeraTerm or your preffered terminal emulator on port COM21 at 115200 baud)
|
|
----------
|
|
|
|
Reset your eLua board, and you're ready to go! *mux* will send all the RFS requests
|
|
to */dev/ptyp0* (or COM10) which in turn gets automatically redirected to */dev/ttyp0*
|
|
(or COM11) and will redirect all console I/O to */dev/ptyp1* (or COM20)
|
|
which in turn gets automatically redirected to */dev/ptyp1* (or COM21).
|
|
|
|
Although this works, there is a simpler, more convenient way to do it if RFS
|
|
support is needed: use the *rfsmux* mode instead.
|
|
|
|
[[rfsmux]]
|
|
Using the multiplexer in "rfsmux" mode
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
To make things easier for RFS users *mux* includes a special operation mode (*rfsmux*)
|
|
that automatically "talks" to the RFS server. The user doesn't need to manually assign
|
|
a virtual UART for the RFS server and start the RFS server. In this mode *mux* uses a special
|
|
internal communication channel to the RFS server (that doesn't require a virtual UART).
|
|
A strict requirement for this mode is that *eLua must be configured to assign the first
|
|
virtual UART ID (SERMUX_SERVICE_ID_FIRST) to the RFS server (RFS_UART_ID)*. If this
|
|
doesn't happen, *rfsmux* mode will not work anymore (but note that you still can use the
|
|
*mux* mode described above with this setup).
|
|
|
|
This is best understood by an example. We'll ask *mux* to share a directory and
|
|
to multiplex one single serial port for us (we'll use it for the console), this
|
|
will be *dev/ptyp0* (and its pair */dev/ttyp0*) in Linux and COM10 (and its pair COM11)
|
|
in Windows. The physical UART is /dev/ttyUSB0 in Linux and COM5 in Windows.
|
|
So, to run it in Linux, execute this:
|
|
|
|
------------------------------------------------------------------
|
|
./mux.exe rfsmux:/home/user/work/fs /dev/ttyUSB0,115200,rtscts /dev/ptyp0
|
|
------------------------------------------------------------------
|
|
|
|
In Windows:
|
|
|
|
---------------------------------------
|
|
mux rfsmux:c:\elua\fs com5,115200,rtscts com10
|
|
---------------------------------------
|
|
|
|
All that's left now is to run the terminal emulator. In Linux:
|
|
|
|
------------------------
|
|
screen /dev/ttyp0 115200
|
|
------------------------
|
|
|
|
In Windows simply start TeraTerm or your preffered terminal emulator on port COM11 at 115200 baud.
|
|
|
|
Reset your eLua board, and you're ready to go! *mux* will send all the RFS requests
|
|
to the RFS server via its internal channel and will redirect all console I/O to */dev/ptyp0* (or COM10)
|
|
which in turn gets automatically redirected to */dev/ttyp0* (or COM11).
|
|
|
|
Notes
|
|
~~~~~
|
|
Some things you should consider when using the serial multiplexer:
|
|
|
|
- the code is still in beta. It works well most of the time, but sometimes it simply crashes. If this happens, please consider submitting a bug report.
|
|
- if your eLua board has two hardware serial ports that you can use and the PC has also two free serial ports, consider disabling the serial multiplexer completely. Run RFS on a hardware
|
|
port and the system console on the other hardware port instead. This is both more realiable and more efficient.
|
|
- to avoid problems with the serial multiplexer use this sequence to start it:
|
|
1. start *mux*
|
|
2. start the terminal emulator
|
|
3. reset the eLua board
|
|
- using hardware flow control is strongly encouraged. To do this:
|
|
1. make sure that your eLua board has support for hardware flow control (see link:refman_gen_uart.html#platform_uart_set_flow_control[here] for details).
|
|
2. specify the correct *SERMUX_FLOW_TYPE* value at build time (it should be *PLATFORM_UART_FLOW_RTS | PLATFORM_UART_FLOW_CTS*).
|
|
3. make sure that the serial cable connecting the PC and the eLua board also supports flow control. Some simple serial connection cables have only the RX, TX and GND wires.
|
|
RTS/CTS flow control requires at least RX, TX, RTS, CTS and GND wires arranged in a null-modem configuration.
|
|
4. start *mux* specifying _rtscts_ as part of the _<transport>_ parameter (see above).
|
|
- the serial multiplexer "protocol" is an extremely simple one, it doesn't make provisions for error correction or detection, and it might loose
|
|
synchronization if there are errors on the serial line. So, if it starts behaving abnormally, you might want to restart *mux* (and *rfs_server*
|
|
if you're running it with *mux*) and reset your eLua board.
|
|
- some serial ports built around USB to RS232 adapters seem to confuse *mux* sometimes. If *mux* won't work after you tried all the above
|
|
instructions, or if *mux* terminates unexpectedly, unplugging and plugging the USB cable of the RS232 adapter and restarting *mux*
|
|
will most likely solve your problem.
|
|
- if you get an *"Error on select, aborting program"* error from *mux*, keep in mind that this is normal if you run a terminal emulator (*screen*)
|
|
under Linux on a virtual UART and then close it (by exiting *screen*). However, it is not normal if it happens under other circumstances in Linux,
|
|
or if it happens in Windows. In these cases, please consider submitting a bug report.
|
|
- if the serial multiplexer is enabled on the eLua board it's not possible to use the board with a regular terminal emulator anymore (without
|
|
running *mux*), although it might appear so. eLua will send some output to the terminal emulator, but it won't be able to accept any input from it.
|
|
- if you find a bug in *mux* and wish to report it, try to reproduce the problem again, but this time run *mux* with *-v* (verbose).
|
|
The resulting logs may help us identify the problem.
|
|
|
|
// $$FOOTER$$
|