Saturday, February 27, 2010

The Laboratory

Here, are some pics of our Laboratory.
This lab is used by the Research Center and Design Services.
Notice how well organized the lab is - I know, I am actually trying to show off here :P



Link to the above album on Picasa (ie thumbnailed gallery)

Thursday, February 4, 2010

Getting Serial Port to work under Ubuntu!

The setup: I have a Intel motherboard inside my office desktop with a built-in serial port. Over the days, I managed to screw up the builtin COM port (and my friends at office did the same to their desktop PCs too.. haha!). What probably happened is that does to some ESD or overvoltage on one of the pins during experimentation caused the RS232 Driver on board the motherboard to get spoilt.
As a result, the COM port (COM1 in this case) was detected alright by windows XP but Bray's Terminal or Hyperterminal were either not able to receive or transmit data out of the port.

So we all got Serial Port PCI cards which costed around Rs.250 a piece. Each of these cards are based around the CH352 (more specifically CH325L) chip made by WCH (a chinese company).

WCH Website (Chinese): www.wch.cn
WCH Website (English): www.wch-ic.com
CH352 Product Page and Datasheet: http://www.wch-ic.com/product/pci/ch352.asp

All these cards have 2 Serial Ports on them. and they worked super fine on windows XP.
Then one day we all uninstalled Windows XP from our PCs and installed Ubuntu 9.10 x86 32bit. All of our hardware worked directly without any intervention on Ubuntu except the PCI Serial Cards.

Here is a list of what all I tried and what finally worked.

1) First I installed "Serial Port Terminal" from Ubuntu Software Center. This is actually "gtkterm"



2) Of course the serial ports werent working directly out of the box. The COM ports are named differently under ubuntu:

Windows Linux
COM1 /dev/ttyS0
COM2 /dev/ttyS1
COM3 /dev/ttyS2
COM4 /dev/ttyS3

Why? you ask: well under Linux and UNIX each and every hardware device treated as a file. These are called device files.
(as an aside: USB to serial convertors based around popular ICs like Prolific's PL2303 and FTDI's FT232RL work directly without any configuration on ubuntu. They appear as /dev/ttyUSB0 , dev/ttyUSB1 etc.
There is a blog post by swamytk on how to run FlashMagic (for programming P89V51RD2 microcontrollers via UART) on ubuntu using Wine: here . In the comments section on that page you can see how to redirect I/O from what appears as COM1 to /dev/ttyUSB0 - which is what USB-Serial convertors appear as under ubuntu)

Googling led me to the command for listing all the serial ports under ubuntu:
setserial -g /dev/ttyS*
But before you use that command, you will need to install the setserial package. You can install that by going over to Synaptic Package Manager and searching for and installing "setserial". Alternatively you can issuse the command "sudo apt-get install setserial" at the terminal prompt.

The output of the setserial -g /dev/ttyS* came out as:
/dev/ttyS0, UART: 16550A, Port: 0x03f8, IRQ: 4
/dev/ttyS1, UART: undefined, Port: 0x1108, IRQ: 18
/dev/ttyS2, UART: undefined, Port: 0x1100, IRQ: 18
/dev/ttyS3, UART: unknown, Port: 0x02e8, IRQ: 3
The first entry was of /dev/ttyS0 which would have been COM1 on Windows. Thats the motherboard's detectable but nor working COM port. The entries for ttyS1 and ttyS2 had the same Interrupt Request Number and so I knew those were the entries for the two serial ports on the PCI card that I had installed. The number "16550A" refers to the UART type. 16550 is the part number of the IC invented by National Semiconductor which was first used to implement UART. Read more about 16550 UART and 16550A (improved version) on wikipedia.

The output of lspci -v command for the serial port PCI card was:
05:04.0 Serial controller: Device 4348:3253 (rev 10) (prog-if 02)
Subsystem: Device 4348:3253
Flags: medium devsel, IRQ 18
I/O ports at 1108 [size=8]
I/O ports at 1100 [size=8]
Kernel driver in use: serial
and some of the serial port related system messages uncovered by dmesg were:
[ 0.808748] Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled
[ 0.808852] serial8250: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A
[ 0.809268] 00:0a: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A
[ 0.809362] serial 0000:05:04.0: PCI INT A -> GSI 18 (level, low) -> IRQ 18
[ 0.809438] 0000:05:04.0: ttyS1 at I/O 0x1108 (irq = 18) is a XScale
[ 0.809530] 0000:05:04.0: ttyS2 at I/O 0x1100 (irq = 18) is a XScale




3) Next I found the driver CD that came with the PCI card. There was a linux driver for the card on it. There was am executable file named "ch35x_80x86.o" on it. The instructions were as follows:
This installation guide describes the procedures to install and uninstall CH35X PCI to two serial ports,one serial and one parport,
two serial ports and one parport,four serial ports in Linux platform.
1-install and uninstall CH35X PCI boards

(1)-install
<1>-copy ch35x_80x86.o to /usr/sbin
<2>-Add /usr/sbin/ch35x_80x86 at the end of the /etc/rc.d/rc.local.
<3>-reboot
if you inster two serials port board
The ttyS2 and ttyS3 are ready for application.

if you inster one serial port and one parport port board
The ttyS2 and LPT1 or LPT2 ready for application.

if you inster four serials port board
The ttyS2 ttyS3 ttyS4 and ttyS5 are ready for application.

if you inster two serials port and aone parport port board
The ttyS2 ttyS3 and LPT1 or LPT2 are ready for application.

(2)-uninstall
(1)-Remove /usr/sbin/ch35x_80x86 at the end of the /etc/rc.d/rc.local.
(2)-Remove /usr/sbin/ch35x_80x86.o



Of course this didnt work (note that on ubuntu, the file to be modified is "/etc/rc.local" instead of "/etc/rc.d/rc.local". You will have to do sudo gedit /etc/rc.local to edit that file.)

4) While I was doing all this (people with similar problems), my friend Rajesh somehow got the serial port to work on his PC. When we asked him how he did it, he said he didnt know. Being complete a n00b to linux (that includes all of us!) , he had forgotten that led him to get it to work. We tried gtkterm on his PC and shorted pins 2 and3 on the RS232 Connector and could see the characters being echoed back!
the setserial list command on Rajesh's PC yielded:
/dev/ttyS0, UART: 16550A, Port: 0x03f8, IRQ: 4
/dev/ttyS1, UART: 16550A, Port: 0x9000, IRQ: 19, Flags: spd_cust
/dev/ttyS2, UART: 16550A, Port: 0x9400, IRQ: 19
/dev/ttyS3, UART: unknown, Port: 0x02e8, IRQ: 3

which led me to believe that maybe the PCI was detected properly on my PC but the linux's serial driver didnt know what kind uart was there on the PCI card.

Further surfing on the web saw me stumble acrosss the following link: http://serial.sourceforge.net/
which is the Project repository for the Linux Serial Driver. The page refers to using the lspci-v command to get port address information about your PCI card and then using the information with setserial command to get your serial ports working. Here is the extract:
Hopefully, there are one or more I/O port regions associated with the card. If you're comfortable using the setserial command, try setting one of your unusued /dev/ttyS devices to one of the I/O port regions listed by lspci, and set its IRQ to the IRQ listed by the lspci listing, and see if you can communicate to your serial port or your modem. I recommend using a low-level modem communications program such as C-Kermit for this testing purpose. If you find that some number of the lspci's I/O regions allow you to talk to the serial port/modem, let me know in your report to me.


Reading this give me inspiration to go and read the manual pages for setserial. (how many times have we heard RTFM thrown at our face!!)

Some points I picked up from the setserial man pages:
uart uart_type
This option is used to set the UART type. The permitted types
are none, 8250, 16450, 16550, 16550A, 16650, 16650V2, 16654,
16750, 16850, 16950, and 16954. Using UART type none will dis‐
able the port.

Some internal modems are billed as having a "16550A UART with a
1k buffer". This is a lie. They do not have really have a
16550A compatible UART; instead what they have is a 16450 com‐
patible UART with a 1k receive buffer to prevent receiver over‐
runs. This is important, because they do not have a transmit
FIFO. Hence, they are not compatible with a 16550A UART, and
the autoconfiguration process will correctly identify them as
16450's. If you attempt to override this using the uart parame‐
ter, you will see dropped characters during file transmissions.
These UART's usually have other problems: the skip_test parame‐
ter also often must be specified.


..I can live with a few dropped characters.. as long as my serial works!!

MULTIPORT CONFIGURATION
Certain multiport serial boards which share multiple ports on a single
IRQ use one or more ports to indicate whether or not there are any
pending ports which need to be serviced. If your multiport board sup‐
ports these ports, you should make use of them to avoid potential lock‐
ups if the interrupt gets lost.

In order to set these ports specify set_multiport as a parameter, and
follow it with the multiport parameters. The multiport parameters take
the form of specifying the port that should be checked, a mask which
indicate which bits in the register are significant, and finally, a
match parameter which specifies what the significant bits in that reg‐
ister must match when there is no more pending work to be done.


...this multiport thing was probaly applicable to my card, but I thought lemme first get the ports working, and so I issued the following two commands to for the serial driver to think of my ports as 16550A:

sudo setserial /dev/ttyS1 uart 16550A
sudo setserial /dev/ttyS2 uart 16550A


and lo! and behold! they started working!! used gtkterm with 2 and 3 pins shorted and I was able to get the echo back!

The setserial -g /dev/ttyS* now yields:
/dev/ttyS0, UART: 16550A, Port: 0x03f8, IRQ: 4
/dev/ttyS1, UART: 16550A, Port: 0x1108, IRQ: 18
/dev/ttyS2, UART: 16550A, Port: 0x1100, IRQ: 18
/dev/ttyS3, UART: unknown, Port: 0x02e8, IRQ: 3