Using other UARTs in Linux
From Platformx Wiki
There are three UARTs available on the PXA271, as described by the PXA27x Developer's Manual:
- Full-Function UART (FFUART)
- The FFUART supports modem-control capability. The maximum baud rate is 921,600 bps.
- Bluetooth UART (BTUART)
- The BTUART is a high-speed UART that supports baud rates up to 921,600 bps and can be connected to a Bluetooth module. It supports the functions in the feature list, but supports only two modem control pins (nCTS and nRTS).
- Standard UART (STUART)
- The STUART supports all functions in the feature list, but does not support modem-control capability. The maximum baud rate is 921,600 bps.
On startup the three UARTs are initalized by the pxa2xx-uart driver:
ttyS0 at MMIO 0x40100000 (irq = 22) is a FFUART
ttyS1 at MMIO 0x40200000 (irq = 21) is a BTUART
ttyS2 at MMIO 0x40700000 (irq = 20) is a STUART
You can find the tty's in the /sys interface at:
/sys/class/tty/ttyS0
/sys/class/tty/ttyS1
/sys/class/tty/ttyS2
Adding /dev entries
The current Linux image only has /dev/ttyS2 (the STUART) added as a /dev entry. To create the /dev/ttySX entries for the other UARTs you have to use mknod.
# Usage: mknod [OPTIONS] NAME TYPE MAJOR MINOR
mknod /dev/ttyS0 char 4 64
mknod /dev/ttyS1 char 4 65
Setting up UARTs
Use stty to setup the baud rates, etc. of the UARTs or to view their current setup:
[root@Linux /dev]# stty -F /dev/ttyS0
speed 9600 baud;
-brkint -imaxbel
[root@Linux /dev]# stty -F /dev/ttyS0 115200
[root@Linux /dev]# stty -F /dev/ttyS0
speed 115200 baud;
-brkint -imaxbel
Note you can use stty to setup the baud rate to be just about any standard UART speed up to 460.8kbps. However, you cannot use stty to set the UART to 921.6kbps
Setting Baud Rate to 921.6kbps
Because 921,600 bps is not a common standard baud rate programs like stty do not typically support it. A quick work around to this problem is to use a simple C program to set the baud rate manually using the termOptions struct in Linux. The underlying driver knows how to set the baud rate correctly (assuming you're using a patched version of the uart drivers) so you just need to be able to request it.
Here is a simple C program that can do this for us:
#include <unistd.h> #include <stdio.h> #include <termios.h> #include <sys/fcntl.h> int main( int argc, char *argv[] ) { struct termios termOptions; char port[1024]; int ttyFid; if( argc == 2 ) { // Copy the port from the argument strcpy( port, argv[1] ); printf( "Read port name: %s\n", port ); } else { // No argument or incorrect number of arguments read: printf( "Usage: setSer /dev/ttySX\n" ); return -1; } // Open the tty: ttyFid = open( port, O_RDWR ); if (ttyFid == -1) { printf( "Error unable to open port: %s\n", port ); return -1; } // Get the current options: tcgetattr( ttyFid, &termOptions ); // Set the input/output speed to 921.6kbps cfsetispeed( &termOptions, B921600 ); cfsetospeed( &termOptions, B921600 ); // Now set the term options (set immediately) tcsetattr( ttyFid, TCSANOW, &termOptions ); // All done printf( "Done, port speed set on: %s\n", port ); }
To compile the program you can use arm-linux-gcc (I had a few problems with arm-linux-g++ with this code):
arm-linux-gcc main.c -o setSer
arm-linux-strip setSer
Once you've compiled the program you will need to either add it to your file system (and load the file system onto your platform) or download it somehow. To use simply call the program with the tty you wish to set i.e. setSerial /dev/ttyS2.
Note, that this code works on x86 desktop platforms just as easily. Also right now there's not too much error checking for the actual setting of the termOptions, so code for reloading the actual termOptions (after pausing to give the driver a chance to set them) and comparing them to your set options might be useful for some people. Also this code doesn't actually close the port it's opened. This doesn't seem to cause any problems, but you might want to add close( ttyFid ); to the last line of the code (unless that doesn't work of course).
