Automating serial port communication on Linux

jasper77 picture jasper77 · Oct 6, 2010 · Viewed 13.8k times · Source

I have a linux server (Red Hat 4) with one serial port connection to an embedded linux device, and another serial port connection to a power controller for that device. My current way to control them is to open two minicom sessions, each in its own window. I would like to automate this communication through scripts. At first, I began to think how I could automate using minicom, then realized I shouldn't need to try to automate using a console application when a script should be able to speak to the port directly.

I know some Perl and some python. I do not have previous experience with modem communication (using AT commands). Perl has Device::Modem, though it's only beta, and Perl seems like a good choice because I prefer its text extraction and wrangling abilities. But, if I need to learn how to control a modem and write/debug a script, that adds more time to my task.

Is it possible/common to interactively control a console app like minicom with a script? If not, what are some good resources for me to learn how to use modem AT commands? Or is there another resource out there that could simplify things for me?

Answer

shodanex picture shodanex · Oct 7, 2010

Kermit is a serial communication app like minicom and it has its own script language, and I used it for some automatic upload on embedded devices. However, it is quite limited and/or buggy, so I finally switched to using python and pyserial.
Whenever you deal with texte mode, like AT command set or speaking to a shell over a serial line, it is really powerful.

If I need to do binary transfer using some standard protocol, I usually use command line tools in non interactive mode, and spawn them from my python script.

Here is some part of the tools I built : waiting for some input, sending data through xmodem, sending a command to u-boot and starting a transfer using the kermit protocol. I use it for automatic flashing and testing of embedded devices.

class Parser :
    def __init__(self, sport_name):
        self.currentMsg = ''
        if sport_name :
            self.ser = serial.Serial(sport_name, 115200)
    def WaitFor(self, s, timeOut=None):
        self.ser.timeout = timeOut
        self.currentMsg = ''
        while self.currentMsg.endswith(s) != True :
            # should add a try catch here
            c=self.ser.read()
            if c != '' :
                self.currentMsg += c
                sys.stdout.write(c)
            else :
                print 'timeout waiting for ' + s
                return False
        return True

    def XmodemSend(self,fname):
        if not self.WaitFor('C', 1) :
            print 'RomBOOT did not launch xmodem transfer'
            return
        self.ser.flushInput()
        self.ser.close()
        call(["xmodem","-d",self.ser.port,"-T",fname])
        self.ser.open() 

def UbootLoad(self, fname):
    self.ser.write('loadb 0x20000000\n')
    if not self.WaitFor('bps...',1) :
        print 'loadb command failed'
        sys.exit()
    self.ser.flushInput()
    self.ser.close()
    retcode=call(['kermit','-y','kermit_init','-s',fname])
    if retcode != 0 :
        print 'error sending' + fname
        sys.exit()
    self.ser.open()
    self.UbootCmd('echo\n')