EEVblog Electronics Community Forum
Products => Computers => Programming => Topic started by: DiTBho on March 23, 2021, 04:54:01 pm
-
I am developing a board where the RS232's RTS signal is used to force a reset to the MPU in order to upload the code.
I am using a MAX232 chip for the { RX, TX, RTS} signals
RX_232 ---MAX232--- RX_TTL
TX_232 ---MAX232--- TX_TTL
RTS_232 ---MAX232--- RTS_TTL -----------> N-MOS ---> /Reset
Measuring the volt at the RTS_TTL pin, I see it's
0V during a Minicom session
5V on the Linux bash, before launching Minicom
So this causes the target to have unwanted resets.
I can hack Minicom and invert the logic, but I'd prefer to modify the Linux behavior in order to have the same behavior of Minicom for the RTS signal.
How to do it? Should I have to hack the RS232 kernel module? Or is there something I can do in user-space.
Thanks :D
edit: mistake fixed
RTS and DTR are output pins,
DCD and CTS are input pins and can only be read.
-
It's standard termios (https://man7.org/linux/man-pages/man3/termios.3.html) behaviour.
I'm not perfectly clear on the signal logic you need (RTS low or high), but hangup is often used for this:
stty -F device speed 0
(see man 1 stty (https://man7.org/linux/man-pages/man1/stty.1.html) for the stty manual page).
If you need a particular pattern or way for request-to-send (RTS) to be de-asserted/low/negative, you might need to write a tiny C program that opens the serial device, sets proper termios settings (in particular, .c_iflag &= ~(IXON | IXOFF) and .c_cflag |= CRTSCTS), and calls tcflow(devfd, TCIOFF).
Either way, these can then be run at init time, or by udev when the device providing the port is connected (as opposed to a device being connected to the serial port).
-
Thanks!
I was a bit worried due to what is reported here (https://unix.stackexchange.com/questions/446088/how-to-prevent-dtr-on-open-for-cdc-acm) :-//
-
I have a second board where I am using the DTR signal.
-
If one wanted to patch this, a proper patch would add a device attribute (auto-DTR) and a driver attribute (default-DTR), so that a sysadmin can control this. For example, for serial core, it would mean an added if check in drivers/tty/serial/serial_core.c:uart_dtr_rts() (https://elixir.bootlin.com/linux/latest/source/drivers/tty/serial/serial_core.c). For usb-serial, in drivers/usb/serial/usb-serial.c:serial_port_dtr_rts() (https://elixir.bootlin.com/linux/latest/source/drivers/usb/serial/usb-serial.c).
However, you can also use a simple C program I roughly described. (Let me know if you want a real-world example; this is simple enough to make into a fully static binary using freestanding C.) You may wish to use the TIOCMBIS/TIOCMIC tty ioctl (https://man7.org/linux/man-pages/man4/tty_ioctl.4.html)s, too.
Essentially, the Linux assert-DTR logic is based on the TTY_PORT_INITIALIZED bit (in the iflags member of the relevant struct tty_port structure); see drivers/tty/tty_port.c:tty_port_open() (https://elixir.bootlin.com/linux/latest/source/drivers/tty/tty_port.c). It gets set on the first open() of the device, and is cleared on shutdown. Shutdown occurs on system suspend, and whenever the last open descriptor to the device is closed; so, if that minimal helper program just keeps the descriptor open, it can completely control the serial port state. Even the termios structure can be locked using TIOCSLCKTRMIOS ioctl.
So no, kernel modification is not necessary, although I admit that in this particular case making the behaviour tunable would be preferable. If one wishes to construct such a patch and send it upstream to LKML, one should remember that the behaviour control bit should be in the TTY structure, whereas the default can be driver-specific.
-
I didn't have more time than a long coffee break (30 min), so I wildly hacked the serial kernel module kernel-v2.6.39/drivers/tty/serial/serial_core.c and removed all the DTR and RTS handling.
Recompiled, not the kerenl doesn't touch the DTR and RTS signal, and everything is done in userspace. So my uploader took can correctly reset the target, send the firmware, and when Minicom is executed (without any flow-control) it doesn't force further (unwanted) resets.
A dirty job for now, but it works :D
(I will move the patch to kernel v4.11, and I will clean it a bit)