WhyCan Forum

本站无需注册,无需积分,无需回复可下载所有资料,如果真的喜欢小站,请您注册之后请至少回复一个帖子激活Id,谢谢支持! 站长QQ: 516333132 (挖坑网/填坑网) admin@whycan.cn

您尚未登录。

#1 2019-08-19 11:32:46

晕哥
Administrator
注册时间: 2017-09-06
累计积分: 7,403

F1C100s 串口可能用 RS485半双工模式吗?本来想通过控制 PE10 高低电平实现半双工, 结果连ioctl都通不过

dts 修改:

&uart2 {
	pinctrl-names = "default";
	pinctrl-0 = <&uart2_pins_a>;
	rts-gpio = <&pio 4 10 GPIO_ACTIVE_HIGH>; //PE10
	rs485-rts-active-high;
	rs485-rts-delay = <0 0>;
	linux,rs485-enabled-at-boot-time;
	status = "okay";
};

https://gist.github.com/amarburg/07564916d8d32e20e6ae375c1c83a995

测试代码:

/*
 * Test program Linux RS485-mode ioctls.
 *
 * cc -o rs485_mode rs485_mode.c
 */

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <linux/serial.h>

/* RS485 ioctls: */
#define TIOCGRS485      0x542E
#define TIOCSRS485      0x542F

int main( int argc, char **argv )
{
        unsigned int i;
        char buf[80];

        if( argc < 3 ) {
                printf("Usage:  %s [port name] [0|1]\n", argv[0]);
                exit(0);
        }

        int enable = atoi( argv[2] );
        char *port = argv[1];

        int fd = open(port, O_RDWR);
        if (fd < 0) {
          /* Error handling. See errno. */
                fprintf( stderr, "Error opening port \"%s\" (%d): %s\n", port, errno, strerror( errno ));
                exit(-1);
        }

        struct serial_rs485 rs485conf;

        if (ioctl (fd, TIOCGRS485, &rs485conf) < 0) {
                fprintf( stderr, "Error reading ioctl port (%d): %s\n",  errno, strerror( errno ));
        }

        printf("Port currently RS485 mode is %s\n", (rs485conf.flags & SER_RS485_ENABLED) ? "set" : "NOT set");

        if( enable ) {
                printf("RS485 mode will be SET\n");
                rs485conf.flags |= SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND;
        } else {
                printf("RS485 mode will be UNSET\n");
                rs485conf.flags &= ~SER_RS485_ENABLED;
        }

        if (ioctl (fd, TIOCSRS485, &rs485conf) < 0) {
                fprintf( stderr, "Error sending ioctl port (%d): %s\n",  errno, strerror( errno ));
        }

        /* Use read() and write() syscalls here... */

        if (ioctl (fd, TIOCGRS485, &rs485conf) < 0) {
                fprintf( stderr, "Error reading ioctl port (%d): %s\n",  errno, strerror( errno ));
        }

        printf("Confirm RS485 mode is %s\n", (rs485conf.flags & SER_RS485_ENABLED) ? "set" : "NOT set");

        /* Do something on the serial port... */
        for( i = 0; i < 100; ++i ) {
                snprintf( buf,79, "%d\r\n", i );
                write( fd, buf, strlen(buf));
                sleep(1);
        }

        /* Close the device when finished: */
        if (close (fd) < 0) {
                fprintf( stderr, "Error closing port (%d): %s\n", errno, strerror( errno ));
        }

        exit(0);
}

测试命令:

# rs485test /dev/ttyS2 1
Port currently RS485 mode is NOT set
RS485 mode will be SET
Error sending ioctl port (25): Inappropriate ioctl for device
Confirm RS485 mode is NOT set

离线

#2 2019-08-19 11:58:42

晕哥
Administrator
注册时间: 2017-09-06
累计积分: 7,403

Re: F1C100s 串口可能用 RS485半双工模式吗?本来想通过控制 PE10 高低电平实现半双工, 结果连ioctl都通不过

serial_core.c 参与了编译, ioctl 命令实现了 TIOCGRS485, TIOCSRS485


https://github.com/torvalds/linux/blob/master/drivers/tty/serial/serial_core.c

/*
 * Called via sys_ioctl.  We can use spin_lock_irq() here.
 */
static int
uart_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
{
	struct uart_state *state = tty->driver_data;
	struct tty_port *port = &state->port;
	struct uart_port *uport;
	void __user *uarg = (void __user *)arg;
	int ret = -ENOIOCTLCMD;


	/*
	 * These ioctls don't rely on the hardware to be present.
	 */
	switch (cmd) {
	case TIOCSERCONFIG:
		down_write(&tty->termios_rwsem);
		ret = uart_do_autoconfig(tty, state);
		up_write(&tty->termios_rwsem);
		break;
	}

	if (ret != -ENOIOCTLCMD)
		goto out;

	if (tty_io_error(tty)) {
		ret = -EIO;
		goto out;
	}

	/*
	 * The following should only be used when hardware is present.
	 */
	switch (cmd) {
	case TIOCMIWAIT:
		ret = uart_wait_modem_status(state, arg);
		break;
	}

	if (ret != -ENOIOCTLCMD)
		goto out;

	mutex_lock(&port->mutex);
	uport = uart_port_check(state);

	if (!uport || tty_io_error(tty)) {
		ret = -EIO;
		goto out_up;
	}

	/*
	 * All these rely on hardware being present and need to be
	 * protected against the tty being hung up.
	 */

	switch (cmd) {
	case TIOCSERGETLSR: /* Get line status register */
		ret = uart_get_lsr_info(tty, state, uarg);
		break;

	case TIOCGRS485:
		ret = uart_get_rs485_config(uport, uarg);
		break;

	case TIOCSRS485:
		ret = uart_set_rs485_config(uport, uarg);
		break;

	case TIOCSISO7816:
		ret = uart_set_iso7816_config(state->uart_port, uarg);
		break;

	case TIOCGISO7816:
		ret = uart_get_iso7816_config(state->uart_port, uarg);
		break;
	default:
		if (uport->ops->ioctl)
			ret = uport->ops->ioctl(uport, cmd, arg);
		break;
	}
out_up:
	mutex_unlock(&port->mutex);
out:
	return ret;
}

接下来再跟踪一下

离线

#3 2019-08-19 23:47:03

shaoxi2010
会员
注册时间: 2019-06-13
累计积分: 22

Re: F1C100s 串口可能用 RS485半双工模式吗?本来想通过控制 PE10 高低电平实现半双工, 结果连ioctl都通不过

可以实现,不过我没走linux 485框架,直接魔改驱动实现的

离线

#4 2019-08-20 06:48:20

晕哥
Administrator
注册时间: 2017-09-06
累计积分: 7,403

Re: F1C100s 串口可能用 RS485半双工模式吗?本来想通过控制 PE10 高低电平实现半双工, 结果连ioctl都通不过

shaoxi2010 说:

可以实现,不过我没走linux 485框架,直接魔改驱动实现的

请教如何修改呢?

离线

#5 2019-08-20 10:25:21

zhenfanhei
会员
注册时间: 2018-01-18
累计积分: 240
个人网站

Re: F1C100s 串口可能用 RS485半双工模式吗?本来想通过控制 PE10 高低电平实现半双工, 结果连ioctl都通不过

我都用全自动的,省io,

最近编辑记录 zhenfanhei (2019-08-20 10:25:31)

离线

#6 2019-08-20 15:00:46

shaoxi2010
会员
注册时间: 2019-06-13
累计积分: 22

Re: F1C100s 串口可能用 RS485半双工模式吗?本来想通过控制 PE10 高低电平实现半双工, 结果连ioctl都通不过

实现代码不方便放出来了,不过思路还是很简单的。先在串口发送中断进入时修改到2分之一fifo,将发送置位,在最后中断触发先修改fifo到empty触发,再去判断lsr的最后位有没有发送,接着置位为接收。和ti的实现不同全志串口呵呵呵...

离线

页脚