depuración de Cortex M3: carga parcial intermitente de binario con pyOCD, luego tiempo de espera

1

Estoy depurando un sistema integrado y obtengo errores de carga binaria intermitentes al actualizar el binario a través de gdb (bueno, arm-none-eabi-gdb, el cliente de gdb de la cadena de herramientas). Aquí están los detalles de mi configuración:

  • La placa de desarrollo LPC1768 en el firmware rev 141212 (procesador Cortex-M3 con interfaz de depuración CMSIS-DAP)
  • GCC-ARM Toolchain (incluido el depurador de cliente arm-none-eabi-gdb client)
  • Hardware de destino conectado a través de USB serial (no se hace nada especial para conectarlo, Ubuntu 14.04 simplemente lo montó automáticamente como un dispositivo de almacenamiento USB)
  • pyOCD 0.4.5
  • pyusb 1.0.0rcl
  • Ubuntu 14.04 como sistema operativo invitado VirtualBox 5.0.0 (sistema operativo host de Win7).

El servidor GDB se inicia en el hardware de destino (remoto) lo suficientemente bien:

${ubuntu:honkaboy} python gdb_test.py
INFO:root:new board id detected: 10100936d079f041404682e3fb480a743a63
INFO:root:board allows 10 concurrent packets
INFO:root:DAP SWD MODE initialised
INFO:root:IDCODE: 0x2BA01477
INFO:root:6 hardware breakpoints, 4 literal comparators
INFO:root:CPU core is Cortex-M3
INFO:root:4 hardware watchpoints
INFO:root:GDB server started at port:3333
INFO:root:One client connected!

Y el cliente gdb también se lanza bien:

{ubuntu:honkaboy}: /usr/local/gcc-arm-none-eabi-4_9-2015q2/bin/arm-none-eabi-gdb Motion-Control.59.elf
GNU gdb (GNU Tools for ARM Embedded Processors) 7.8.0.20150604-cvs
...
[bunch of omitted startup messages (canned and irrelevant)]
...
Reading symbols from Motion-Control.59.elf...done.
(gdb) target remote localhost:3333
Remote debugging using localhost:3333
0x00003cb0 in Reset_Handler ()

Pero cuando cargo el binario a través del cliente, a menudo obtendré un tiempo de espera de transferencia de datos:

Terminal de cliente:

(gdb) load
Loading section .text, size 0x11940 lma 0x0
Loading section .ARM.exidx, size 0x8 lma 0x11940
Loading section .data, size 0x134 lma 0x11948
Remote connection closed

Terminal de servidor:

INFO:root:One client connected!
[=======             ]  35%Exception in thread Thread-2:
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
    self.run()
  File "/usr/local/lib/python2.7/dist-packages/pyOCD/gdbserver/gdbserver.py", line 318, in run
    resp, detach = self.handleMsg(packet)
  File "/usr/local/lib/python2.7/dist-packages/pyOCD/gdbserver/gdbserver.py", line 390, in handleMsg
    return self.flashOp(msg[2:]), 0
  File "/usr/local/lib/python2.7/dist-packages/pyOCD/gdbserver/gdbserver.py", line 548, in flashOp
    self.flashBuilder.program(chip_erase = self.chip_erase, progress_cb=progress_cb, fast_verify=self.fast_program)
  File "/usr/local/lib/python2.7/dist-packages/pyOCD/flash/flash_builder.py", line 250, in program
    flash_operation = self._page_erase_program(progress_cb)
  File "/usr/local/lib/python2.7/dist-packages/pyOCD/flash/flash_builder.py", line 486, in _page_erase_program
    data = self.flash.target.readBlockMemoryUnaligned8(page.addr, len(page.data))
  File "/usr/local/lib/python2.7/dist-packages/pyOCD/target/cortex_m.py", line 569, in readBlockMemoryUnaligned8
    mem = self.readBlockMemoryAligned32(addr, size/4)
  File "/usr/local/lib/python2.7/dist-packages/pyOCD/target/cortex_m.py", line 667, in readBlockMemoryAligned32
    resp += self.transport.readBlock32(addr, n/4)
  File "/usr/local/lib/python2.7/dist-packages/pyOCD/transport/cmsis_dap.py", line 221, in readBlock32
    resp = self._transferBlock(size, READ | AP_ACC | AP_REG['DRW'])
  File "/usr/local/lib/python2.7/dist-packages/pyOCD/transport/cmsis_dap.py", line 402, in _transferBlock
    return self.protocol.transferBlock(count, request, data)
  File "/usr/local/lib/python2.7/dist-packages/pyOCD/transport/cmsis_dap_core.py", line 256, in transferBlock
    self.interface.write(cmd)
  File "/usr/local/lib/python2.7/dist-packages/pyOCD/interface/pyusb_backend.py", line 155, in write
    self.ep_out.write(data)
  File "/usr/local/lib/python2.7/dist-packages/usb/core.py", line 360, in write
    return self.device.write(self, data, timeout)
  File "/usr/local/lib/python2.7/dist-packages/usb/core.py", line 921, in write
    self.__get_timeout(timeout)
  File "/usr/local/lib/python2.7/dist-packages/usb/backend/libusb1.py", line 834, in intr_write
    timeout)
  File "/usr/local/lib/python2.7/dist-packages/usb/backend/libusb1.py", line 912, in __write
    _check(retval)
  File "/usr/local/lib/python2.7/dist-packages/usb/backend/libusb1.py", line 592, in _check
    raise USBError(_strerror(ret), ret, _libusb_errno[ret])
USBError: [Errno 110] Operation timed out

Exception in thread gdb-packet-thread (most likely raised during interpreter shutdown):
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
  File "/usr/local/lib/python2.7/dist-packages/pyOCD/gdbserver/gdbserver.py", line 119, in run
<type 'exceptions.AttributeError'>: 'NoneType' object has no attribute 'error'

Como mencioné, el error es intermitente. Es probable que ocurra el 70% del tiempo, el otro 30% se carga perfectamente y puedo depurar el programa normalmente. El porcentaje de carga en el que se produjo el tiempo de espera en mi ejemplo aquí fue del 35%, pero eso no es consistente. A veces se agota el 10% de carga, a veces el 69%, etc.

    
pregunta honkaboy

1 respuesta

1

Tengo una solución (curita) para el problema y dos conjeturas para lo que podría ser la causa subyacente. Daré mi corrección primero.

( Descargo de responsabilidad : no tengo muchos conocimientos sobre pyOCD o pyusb y mi solución aquí se derivó puramente de forma heurística. Esta solución puede muy bien estropear alguna otra funcionalidad de pyOCD o pyusb.)

Aumente el tiempo de espera de escritura en serie de Pyusb. No estoy seguro de cuál es el tiempo de espera predeterminado, pero tengo aproximadamente la misma frecuencia de falla cuando configuro el tiempo de espera de escritura en 1000 ms. 2000ms parecía lo suficientemente largo para tener éxito consistentemente.

Aquí es donde se cambia el tiempo de espera. Tenga en cuenta que instalé pyusb y pyOCD con pip en las ubicaciones predeterminadas en Ubuntu 14.04, que pusieron el archivo en /usr/local/lib/python2.7/dist-packages/usb/core.py .

Función self.device.write (), en core.py:349 (parte de pyusb 1.0.0rcl).

Antes (función completa para el contexto):

def write(self, data, timeout = None):
    r"""Write data to the endpoint.

    The parameter data contains the data to be sent to the endpoint and
    timeout is the time limit of the operation. The transfer type and
    endpoint address are automatically inferred.

    The method returns the number of bytes written.

    For details, see the Device.write() method.
    """
    return self.device.write(self, data, timeout)

Después (solo el cambio es el valor de tiempo de espera predeterminado):

def write(self, data, timeout = 2000):
    r"""Write data to the endpoint.
    [ ... ]
    """
    return self.device.write(self, data, timeout)

Ahora, para mis conjeturas sobre el problema subyacente.

  1. Estoy ejecutando Ubuntu 14.04 como una máquina virtual invitada a través de VirtualBox 5.0.0, por lo que es posible que haya una latencia adicional en el extremo USB, ya que el dispositivo USB debe montarse a través del marco de la VM.
  2. Algunos errores con pyusb, pyOCD o el firmware de destino.

Sospecho # 1 más que # 2. Probando una configuración similar de forma nativa en Windows (pyocd_win), no tengo ningún problema de tiempo de espera de carga.

    
respondido por el honkaboy

Lea otras preguntas en las etiquetas