Re: Modem control lines for RTSCTS hardware flow control via rts-gpio and cts-gpio with IMX

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




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



[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux PPP]     [Linux FS]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Linmodem]     [Device Mapper]     [Linux Kernel for ARM]

  Powered by Linux