代码之家  ›  专栏  ›  技术社区  ›  FKEinternet

pySerial问题:嵌入式控制器停止回显命令

  •  0
  • FKEinternet  · 技术社区  · 4 年前

    我正在尝试使用在Ubuntu主机上运行的pySerial来自动测试嵌入式控制器。我可以在终端窗口(例如PuTTY)中输入命令,并全天从EC获得响应。然而,当我尝试使用pySerial程序来做同样的事情时,EC会在一段时间后停止回显命令,就在回显命令的中间。从那时起,EC停止对程序的响应,包括不发送被中断的命令的结果。

    如果我终止程序并尝试再次使用终端连接到EC,则EC没有响应。如果发生外部事件,导致EC将输出写入终端,则该信息将正确显示。问题一直存在,直到我重新启动EC——这也会删除问题发生时EC上发生的任何日志。(日志只能通过串行端口访问…)

    似乎pySerial正在执行的某些操作导致EC的输入处理停止。我试着输入Ctrl-Q(XON),希望有一些不明显的软件流控制,但这并没有什么区别。我尝试过在程序中发送交替的命令,在发送命令之间发送空行,在命令发送之间插入延迟——但每次处理几个命令后,它都会失效。

    这是我目前正在使用的脚本:

    import serial
    from datetime import datetime
    
    ser = serial.Serial('/dev/ttyUSB0', 115200, timeout=1)
    
    print('Starting up')
    # send an empty command to ensure a prompt is displayed
    ser.write(b'\r\n')
    
    commandToSend = 'battery current'
    failed = 0
    running = True
    while running:
        while running:
            # read from the EC until a timeout occurs with no data available
            try:
                # wait for the EC prompt
                rcvData = ser.read_until(b' ec> ')
                now = datetime.now().time()
                print('{}\tRead from device: "{}"'.format(now, rcvData))
                decoded = rcvData.decode('ascii')
                if len(decoded) == 0:
                    # timeout, nothing read from EC, send next command
                    failed += 1
                    break
                # normalize line terminations then split the data into lines
                lines = decoded.replace('\r\r\n','\r\n').split('\r\n')
                for line in lines:
                    print('{}{}'.format(' '*34, line))
                break
            except KeyboardInterrupt:
                print('\nKeyboard interrupt, aborting')
                running = False
                break
            except Exception as e:
                print(e)  # this branch never executes, from my observation
                pass
        now = datetime.now().time()
        if failed > 1:
            print('{}\tCommunication with the EC has failed'.format(now))
            break
        if running:
            # send the command when there's no data to read
            print('{}\tWriting: "{}\\r\\n"'.format(now, commandToSend))
            ser.write('{}\r\n'.format(commandToSend).encode())
            ser.flush()
    

    运行上述脚本的典型结果是:

    $ ./ec-uart-test.py
    Starting up
    20:19:10.620998     Read from device: "b'\r\n ec> '"
                                  
                                       ec> 
    20:19:11.622234     Read from device: "b''"
    20:19:11.622345     Writing: "battery current\r\n"
    20:19:11.627921     Read from device: "b'\r\n ec> '"
                                  
                                       ec> 
    20:19:11.628690     Read from device: "b'battery current\r\n0ma\r\r\n ec> '"
                                      battery current
                                      0ma
                                       ec> 
    20:19:11.628777     Writing: "battery current\r\n"
    20:19:11.635899     Read from device: "b'\r\n ec> '"
    
                                       ec> 
    20:19:12.637335     Read from device: "b'battery cu'"
                                      battery cu
    20:19:12.637439     Writing: "battery current\r\n"
    20:19:13.644800     Read from device: "b''"
    
    20:19:14.646080     Read from device: "b''"
    20:19:14.646172     Communication with the EC has failed
    

    除了破解EC并在其上安装硬件分析器之外,我还应该尝试其他方法来让这些代码正常工作吗?

    0 回复  |  直到 4 年前
        1
  •  0
  •   FKEinternet    4 年前

    看起来测试程序实际上是错误的:按照我同事的一个例子,我在终端中输入了“电池电流”命令,得到了响应,然后使用向上箭头键重新运行该命令——这似乎一整天都有效。

    然而,这不是同一个测试:向上箭头(从EC的历史记录中检索最后一个命令)后面跟着 不 与重复键入命令并发送命令相同。

    当我以最快的速度反复将命令粘贴到终端窗口时,EC的故障方式与使用pySerial发送命令的方式完全相同:故障是EC内部的,与pySerial在通信线上所做的没有什么不同。