您尚未登录。

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

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,223
积分: 9197

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

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,223
积分: 9197

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
已发帖子: 363
积分: 312

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

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

离线

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

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,223
积分: 9197

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

shaoxi2010 说:

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

请教如何修改呢?





离线

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

zhenfanhei
会员
注册时间: 2018-01-18
已发帖子: 296
积分: 251
个人网站

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

我都用全自动的,省io,

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





离线

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

shaoxi2010
会员
注册时间: 2019-06-13
已发帖子: 363
积分: 312

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

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

离线

#7 2020-04-20 08:12:59

路人甲
会员
注册时间: 2017-09-07
已发帖子: 202
积分: 199.5

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

shaoxi2010 说:

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

我的RS485 驱动控制GPIO半双工控制问题也解决了, 在此抛砖引玉: https://whycan.cn/t_4012.html#p39120

离线

#8 2024-02-20 09:09:38

smbzd
会员
注册时间: 2022-10-27
已发帖子: 1
积分: 1

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

@shaoxi2010
请问是如何修改的fifo为1/2触发?我改了之后又立马读,发现改不动。看了用户手册,它是这样说的:
“TFT
TX Empty Trigger
Writes have no effect when THRE_MODE_USER = Disabled. This is used to
select the empty threshold level at which the THRE Interrupts are
generated when the mode is active. lt also determines when the
dma_tx_req_n signal is asserted when in certain modes of operation.
00: FIFO empty
01: 2 characters in the FIFO
10: FIFO 1/4 full
11: FIFO 1/2 full”

离线

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn