Pymcuprog can't use my UART?

Trying to use a Raspberry Pi 4’s native UART (physical pins 8 and 10 on the GPIO header) to program an ATtiny402, using the pymcuprog library:

aaron@Aaron-Bench:~ $ sudo pip install pymcuprog
[sudo] password for aaron: 
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting pymcuprog
  Downloading pymcuprog-3.17.3.45-py3-none-any.whl (224 kB)
     |████████████████████████████████| 224 kB 968 kB/s 
Collecting IntelHex
  Downloading https://www.piwheels.org/simple/intelhex/intelhex-2.3.0-py2.py3-none-any.whl (50 kB)
     |████████████████████████████████| 50 kB 175 kB/s 
Collecting appdirs
  Downloading https://www.piwheels.org/simple/appdirs/appdirs-1.4.4-py2.py3-none-any.whl (9.6 kB)
Collecting PyYAML
  Downloading PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (731 kB)
     |████████████████████████████████| 731 kB 1.1 MB/s 
Collecting pyedbglib>=2.24
  Downloading pyedbglib-2.24.2.18-py3-none-any.whl (70 kB)
     |████████████████████████████████| 70 kB 810 kB/s 
Requirement already satisfied: pyserial in /usr/lib/python3/dist-packages (from pymcuprog) (3.5b0)
Collecting hidapi
  Downloading hidapi-0.14.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (925 kB)
     |████████████████████████████████| 925 kB 23 kB/s 
Collecting pyserial
  Downloading https://www.piwheels.org/simple/pyserial/pyserial-3.5-py2.py3-none-any.whl (90 kB)
     |████████████████████████████████| 90 kB 286 kB/s 
Collecting cython
  Downloading Cython-3.0.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (3.5 MB)
     |████████████████████████████████| 3.5 MB 1.4 MB/s 
Requirement already satisfied: setuptools>=19.0 in /usr/lib/python3/dist-packages (from hidapi->pyedbglib>=2.24->pymcuprog) (52.0.0)
Installing collected packages: pyserial, hidapi, cython, PyYAML, pyedbglib, IntelHex, appdirs, pymcuprog
  Attempting uninstall: pyserial
    Found existing installation: pyserial 3.5b0
    Not uninstalling pyserial at /usr/lib/python3/dist-packages, outside environment /usr
    Can't uninstall 'pyserial'. No files were found to uninstall.
Successfully installed IntelHex-2.3.0 PyYAML-6.0.1 appdirs-1.4.4 cython-3.0.10 hidapi-0.14.0 pyedbglib-2.24.2.18 pymcuprog-3.17.3.45 pyserial-3.5
aaron@Aaron-Bench:~ $ pymcuprog ping -d attiny402 -t uart -u /dev/ttyS0
Connecting to SerialUPDI
pymcuprog.pymcuprog - ERROR - Operation failed with error: (22, 'Invalid argument')
aaron@Aaron-Bench:~ $ 

Just to check and see if it’s even trying, I put a logic analyzer on the wire and tried again. It saw nothing. But CuteCom does work:


Okay, so the port works, and the 1k “contention resistor” works as an echo, as seen in CuteCom.

Back to pymcuprog, intentionally keeping the port open in CuteCom as another test:

aaron@Aaron-Bench:~ $ pymcuprog ping -d attiny402 -t uart -u /dev/ttyS0
Connecting to SerialUPDI
pymcuprog.serialupdi.physical - ERROR - Unable to open serial port '/dev/ttyS0'
pymcuprog.pymcuprog - ERROR - Operation failed with SerialException: [Errno 16] could not open port /dev/ttyS0: [Errno 16] Device or resource busy: '/dev/ttyS0'
aaron@Aaron-Bench:~ $ 

So at least I got the port right. The “Invalid argument” can’t be that.

Closed the port in CuteCom, re-armed the logic analyzer, and tried pymcuprog again. Same error as the first time, and the analyzer again saw nothing.

With such a terrible error message, I’m out of ideas. Anyone know what’s going on?

Just a wild guess from the code that opens the actual serial port

It might not like the parity = even and 2 stop bits? Usually Parity = none and stopbits = 1.

Just open a python shell and try the same

import serial
s = serial.Serial("/dev/ttyS0", 115200, parity=serial.PARITY_EVEN, timeout=1.0, stopbits=serial.STOPBITS_TWO

see what happens

aaron@Aaron-Bench:~ $ python
Python 3.9.2 (default, Feb 28 2021, 17:03:44) 
[GCC 10.2.1 20210110] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import serial
>>> s = serial.Serial("/dev/ttyS0", 115200, parity=serial.PARITY_EVEN, timeout=1.0, stopbits=serial.STOPBITS_TWO)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.9/dist-packages/serial/serialutil.py", line 244, in __init__
    self.open()
  File "/usr/local/lib/python3.9/dist-packages/serial/serialposix.py", line 332, in open
    self._reconfigure_port(force_update=True)
  File "/usr/local/lib/python3.9/dist-packages/serial/serialposix.py", line 517, in _reconfigure_port
    termios.tcsetattr(
termios.error: (22, 'Invalid argument')
>>> s.close()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 's' is not defined
>>> exit()
aaron@Aaron-Bench:~ $ 

Try again with the more standard options:

aaron@Aaron-Bench:~ $ python
Python 3.9.2 (default, Feb 28 2021, 17:03:44) 
[GCC 10.2.1 20210110] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import serial
>>> s = serial.Serial("/dev/ttyS0", 115200, parity=serial.PARITY_NONE, timeout=1.0, stopbits=serial.STOPBITS_ONE)
>>> s.write('hello'.encode('utf-8'))
5
>>> s.close()
>>> exit()
aaron@Aaron-Bench:~ $ 

…and the logic analyzer saw “hello” on the wire.

Doesn’t look good. The Pi 4’s UART does 8N1, but does it really not do 8E2?

Edit: Playing with CuteCom some more, suggests that the stop bits are okay, but it just doesn’t do parity. At all. :frowning:

The linux kernel is probably bullshitting you by not exposing the functionality. When I look at the Pi 4 datasheet (https://datasheets.raspberrypi.com/rpi4/raspberry-pi-4-datasheet.pdf) it has a BCM2711 SoC, and in that perpiheral datasheet it says

Hmm… Well, I guess I’ll go squawk at them then. Thanks!

Oh, possibly this is actually right:

If it’s the “mini-UART” that’s exposed on the GPIO headers and it’s not supporting parity in hardware, I guess the Linux kernel behaves correctly. Which makes running pymcuprog serial not possible.

(It would have been possible if there would be a 9 data bits settings so you can compute the 9th (parity) bit yourself)

https://forums.raspberrypi.com/viewtopic.php?t=370332
Turns out that the Pi 4 and before share the first PL011 and the mini-UART with the advertised GPIO pins and the bluetooth module. By default, the full-featured one is used for BT and the mini one is on the GPIO header, hence the problem above. But adding a line in /boot/config.txt swaps those assignments:
dtoverlay=miniuart-bt

So now pymcuprog produces something on the wire that looks like it’s trying. I don’t have the chip hooked up yet, so it times out, but I think I’ll call this thread solved. Thank you!


Regardless of routing:
/dev/ttyAMA_ is the PL011
/dev/ttyS0 is the mini-UART

The Pi 5 doesn’t have a mini-UART at all, so it shouldn’t have this problem. Don’t have one to test though.