NUC980 RS485驱动收发bug解决

遇到的问题

RS485在收发过程中,一旦close()后,重新open(),无法读写,必须设备发送一次消息才能正常恢复串口读写。

例如:使用modbus_close(ctx);之后必须执行modbus_send_raw_data(ctx,"test",4);

串口才能正常。否则设备串口将一直处于发送状态而无法接收数据。

初步判断

经调试,判断是在关闭串口后发送标志位没有清空。导致重新打开串口后,uart_tx_stopped()函数中的if判断未通过(因为tty->stopped一直等于0,同时硬件流控已经关掉),一直处于发送状态而导致RS485的使能引脚没有打开。

static inline int uart_tx_stopped(struct uart_port *port)
{
	struct tty_struct *tty = port->state->port.tty;
	if (tty->stopped || port->hw_stopped)
		return 1;
	return 0;
}

解决方法

文件目录:drivers/tty/serial/nuc980_serial.c

在nuc980serial_shutdown()这个函数中,最后添加两行代码停止rx和tx即可

当然你也可以用nuc980serial_stop_tx()和nuc980serial_stop_rx(),只不过传入的形参需要强制转换一下。

static void nuc980serial_shutdown(struct uart_port *port)
{
	struct uart_nuc980_port *up = (struct uart_nuc980_port *)port;
#if defined(CONFIG_ENABLE_UART_PDMA) || defined(CONFIG_USE_OF)
	struct nuc980_ip_rx_dma *pdma_rx = &(up->dma_rx);
	struct nuc980_ip_tx_dma *pdma_tx = &(up->dma_tx);
#endif

#if defined(CONFIG_ENABLE_UART_PDMA) || defined(CONFIG_USE_OF)
	if(up->uart_pdma_enable_flag == 1) {
		dma_release_channel(pdma_rx->chan_rx);
		dma_release_channel(pdma_tx->chan_tx);

#ifdef USING_SRAM
		sram_free((void *)up->dest_mem_p.vir_addr, up->dest_mem_p.size);
#endif

		if(up->src_mem_p.vir_addr != 0)
			dma_free_writecombine(NULL, up->src_mem_p.size, (void *)up->src_mem_p.vir_addr, up->src_mem_p.phy_addr);

		up->dest_mem_p.size = 0;
		up->src_mem_p.size = 0;
	}
#endif

	free_irq(port->irq, port);

	/*
	 * Disable interrupts from this port
	 */
	serial_out(up, UART_REG_IER, 0);

    //以下是添加的两行代码
	// the same as using  nuc980serial_stop_rx()
	serial_out(up, UART_REG_IER, serial_in(up, UART_REG_IER) & ~RDA_IEN); 

	// the same as using nuc980serial_stop_tx()
	__stop_tx(up);
	
}

你可能感兴趣的:(bug)