Hi,
Le 14/01/2022 à 07:19, Tomasz Moń a écrit :
On 14.01.2022 04:08, Tim Harvey wrote:
So I believe in order to support using gpios for rts/cts in the imx
uart driver I must find the right place to call imx_uart_rts_active
and imx_uart_rts_inactive when the FIFO is not full and full
respectively. I'm not that familiar with the Linux uart driver
framework - am I on the right track and if so any ideas where this is
best done?
It is not really the driver (and thus FIFO level), but rather the amount
of free space in tty buffer (checked by Line Discipline workqueue) that
determines when to throttle (set RTS inactive). This mostly works fine,
but fails [1] when the RX interrupt frequency is too high [2].
The throttle/unthrottle request, when termios CRTSCTS is set, is seen by
the driver as the call to .set_mctrl (imx_uart_set_mctrl) with TIOCM_RTS
bit cleared/set in mctrl parameter. Currently imx_uart_set_mctrl() only
controls the UCR2_CTS and UCR2_CTSC bits based on mctrl.
To support your case you would most likely have to add the gpio handling
in imx_uart_set_mctrl(). However, I am unaware what other issues you
might encounter (i.e. if it is not done there yet simply because nobody
had that use case or if there is some deeper problem).
[1] https://lore.kernel.org/linux-serial/10e723c0-a28b-de0d-0632-0bd250478313@xxxxxxxxxxxxxxx/
[2] https://lore.kernel.org/linux-serial/20220104103203.2033673-1-tomasz.mon@xxxxxxxxxxxxxxx/
Best Regards,
Tomasz Mon
I'd suggest to start testing with a serial port connected to nothing, and check the pins values
with a scope or a voltmeter.
Setting pins values from userspace can done quite easily with :
#include <unistd.h>
#include <termios.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
void usage(char *prog)
{
printf("usage: %s serial_port id 0/1 sleep_time_sec\n", prog);
printf("%s\n", "1:DTR DTR (data terminal ready)");
printf("%s\n", "2:RTS RTS (request to send)");
printf("%s\n", "3:Both");
}
int main(int argc, char **argv)
{
int fd;
unsigned status = 0;
int enable;
int err;
if (argc < 5) {
usage(argv[0]);
return -1;
}
fd = open(argv[1], O_RDWR | O_NOCTTY);
enable = atoi(argv[3]);
if (fd < 0)
return -1;
switch(atoi(argv[2])) {
case 0:
if (enable)
status |= TIOCM_LE;
break;
case 1:
if (enable)
status |= TIOCM_DTR;
break;
case 2:
if (enable)
status |= TIOCM_RTS;
break;
case 3:
if (enable)
status |= TIOCM_DTR | TIOCM_RTS;
break;
default:
printf("unknown signal\n");
}
err = ioctl(fd, TIOCMSET, &status);
sleep(atoi(argv[4]));
out:
if (fd > -1)
close(fd);
return err;
}
regards,
Richard