Search code examples
linuxautomated-testsserial-portmodem

Automating serial port communication on Linux


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?


Solution

  • 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')