| 
 
贡献25 
飞刀2 FD
注册时间2017-9-8
在线时间0 小时积分3 
 
 扫一扫,手机访问本帖  | 
 
| OK335D LINUX下485使用的是UART2和GPIO3_2配合使用实现485驱动(见原理图),按我的理解就是把串口驱动实现为458驱动无非就是在串口发送时拉高或拉低GPIO3_2引脚,发送结束时做相反操作,按时这个485驱动在启动时会初始化这个GPIO3_2脚,我在驱动源码中serial_omap_startup()、serial_omap_start_tx()和serial_omap_stop_tx这几个函数中没找到初始化或控制GPIO3_2引脚的语句,或许是我看得不够仔细,飞凌工程师可以帮我指出来吗?如果不是按我理解的这样去做,请问是如何实现这个485驱动的?附上这几个函数的源码,谢谢 static void serial_omap_start_tx(struct uart_port *port)
 {
 struct uart_omap_port *up = (struct uart_omap_port *)port;
 struct circ_buf *xmit;
 unsigned int start;
 int ret = 0;
 
 if (!up->use_dma) {
 pm_runtime_get_sync(&up->pdev->dev);
 serial_omap_enable_ier_thri(up);
 pm_runtime_mark_last_busy(&up->pdev->dev);
 pm_runtime_put_autosuspend(&up->pdev->dev);
 return;
 }
 
 if (up->uart_dma.tx_dma_used)
 return;
 
 xmit = &up->port.state->xmit;
 
 if (up->uart_dma.tx_dma_channel == OMAP_UART_DMA_CH_FREE) {
 pm_runtime_get_sync(&up->pdev->dev);
 ret = omap_request_dma(up->uart_dma.uart_dma_tx,
 "UART Tx DMA",
 (void *)uart_tx_dma_callback, up,
 &(up->uart_dma.tx_dma_channel));
 
 if (ret < 0) {
 serial_omap_enable_ier_thri(up);
 return;
 }
 }
 spin_lock(&(up->uart_dma.tx_lock));
 up->uart_dma.tx_dma_used = true;
 spin_unlock(&(up->uart_dma.tx_lock));
 
 start = up->uart_dma.tx_buf_dma_phys +
 (xmit->tail & (UART_XMIT_SIZE - 1));
 
 up->uart_dma.tx_buf_size = uart_circ_chars_pending(xmit);
 /*
 * It is a circular buffer. See if the buffer has wounded back.
 * If yes it will have to be transferred in two separate dma
 * transfers
 */
 if (start + up->uart_dma.tx_buf_size >=
 up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE)
 up->uart_dma.tx_buf_size =
 (up->uart_dma.tx_buf_dma_phys +
 UART_XMIT_SIZE) - start;
 
 omap_set_dma_dest_params(up->uart_dma.tx_dma_channel, 0,
 OMAP_DMA_AMODE_CONSTANT,
 up->uart_dma.uart_base, 0, 0);
 omap_set_dma_src_params(up->uart_dma.tx_dma_channel, 0,
 OMAP_DMA_AMODE_POST_INC, start, 0, 0);
 omap_set_dma_transfer_params(up->uart_dma.tx_dma_channel,
 OMAP_DMA_DATA_TYPE_S8,
 up->uart_dma.tx_buf_size, 1,
 OMAP_DMA_SYNC_ELEMENT,
 up->uart_dma.uart_dma_tx, 0);
 /* FIXME: Cache maintenance needed here? */
 omap_start_dma(up->uart_dma.tx_dma_channel);
 }
 
 
 static void serial_omap_stop_tx(struct uart_port *port)
 {
 struct uart_omap_port *up = (struct uart_omap_port *)port;
 
 if (up->use_dma &&
 up->uart_dma.tx_dma_channel != OMAP_UART_DMA_CH_FREE) {
 /*
 * Check if dma is still active. If yes do nothing,
 * return. Else stop dma
 */
 if (omap_get_dma_active_status(up->uart_dma.tx_dma_channel))
 return;
 omap_stop_dma(up->uart_dma.tx_dma_channel);
 omap_free_dma(up->uart_dma.tx_dma_channel);
 up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE;
 pm_runtime_mark_last_busy(&up->pdev->dev);
 pm_runtime_put_autosuspend(&up->pdev->dev);
 }
 
 pm_runtime_get_sync(&up->pdev->dev);
 if (up->ier & UART_IER_THRI) {
 up->ier &= ~UART_IER_THRI;
 serial_out(up, UART_IER, up->ier);
 }
 
 pm_runtime_mark_last_busy(&up->pdev->dev);
 pm_runtime_put_autosuspend(&up->pdev->dev);
 }
 
 static int serial_omap_startup(struct uart_port *port)
 {
 struct uart_omap_port *up = (struct uart_omap_port *)port;
 unsigned long flags = 0;
 int retval;
 
 /*
 * Allocate the IRQ
 */
 retval = request_irq(up->port.irq, serial_omap_irq, up->port.irqflags,
 up->name, up);
 if (retval)
 return retval;
 
 dev_dbg(up->port.dev, "serial_omap_startup+%d\n", up->port.line);
 
 pm_runtime_get_sync(&up->pdev->dev);
 /*
 * Clear the FIFO buffers and disable them.
 * (they will be reenabled in set_termios())
 */
 serial_omap_clear_fifos(up);
 /* For Hardware flow control */
 serial_out(up, UART_MCR, UART_MCR_RTS);
 
 /*
 * Clear the interrupt registers.
 */
 (void) serial_in(up, UART_LSR);
 if (serial_in(up, UART_LSR) & UART_LSR_DR)
 (void) serial_in(up, UART_RX);
 (void) serial_in(up, UART_IIR);
 (void) serial_in(up, UART_MSR);
 
 /*
 * Now, initialize the UART
 */
 serial_out(up, UART_LCR, UART_LCR_WLEN8);
 spin_lock_irqsave(&up->port.lock, flags);
 /*
 * Most PC uarts need OUT2 raised to enable interrupts.
 */
 up->port.mctrl |= TIOCM_OUT2;
 serial_omap_set_mctrl(&up->port, up->port.mctrl);
 spin_unlock_irqrestore(&up->port.lock, flags);
 
 up->msr_saved_flags = 0;
 if (up->use_dma) {
 free_page((unsigned long)up->port.state->xmit.buf);
 up->port.state->xmit.buf = dma_alloc_coherent(NULL,
 UART_XMIT_SIZE,
 (dma_addr_t *)&(up->uart_dma.tx_buf_dma_phys),
 0);
 init_timer(&(up->uart_dma.rx_timer));
 up->uart_dma.rx_timer.function = serial_omap_rxdma_poll;
 up->uart_dma.rx_timer.data = up->port.line;
 /* Currently the buffer size is 4KB. Can increase it */
 up->uart_dma.rx_buf = dma_alloc_coherent(NULL,
 up->uart_dma.rx_buf_size,
 (dma_addr_t *)&(up->uart_dma.rx_buf_dma_phys), 0);
 }
 /*
 * Finally, enable interrupts. Note: Modem status interrupts
 * are set via set_termios(), which will be occurring imminently
 * anyway, so we don't enable them here.
 */
 up->ier = UART_IER_RLSI | UART_IER_RDI;
 serial_out(up, UART_IER, up->ier);
 
 /* Enable module level wake up */
 serial_out(up, UART_OMAP_WER, OMAP_UART_WER_MOD_WKUP);
 
 pm_runtime_mark_last_busy(&up->pdev->dev);
 pm_runtime_put_autosuspend(&up->pdev->dev);
 up->port_activity = jiffies;
 return 0;
 }
 
 
 
 | 
 |