嵌入式爱好者

查看: 18650|回复: 7

[Linux] 关于OK335D LINUX下485驱动的问题

[复制链接]

0

主题

0

帖子

3

积分

扫一扫,手机访问本帖
发表于 2013-10-21 22:52:24 | 显示全部楼层 |阅读模式
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;
}


回复

使用道具 举报

153

主题

3910

帖子

4207

积分

AM5718通行证AM335x通行证i.MX6UL通行证i.MX RT通行证i.MX6Q通行证XX18通行证TCU通行证FCU1401通行证FCU1301通行证FCU11xx通行证

发表于 2013-10-24 16:56:39 | 显示全部楼层
RS485 驱动 源码路径 : drivers/tty/serial/omap-serial.c
技术支持电话:0312-3119192
技术支持邮箱:Linux@forlinx.com
点评回复 支持 反对

使用道具 举报

0

主题

0

帖子

3

积分

 楼主| 发表于 2013-10-24 21:05:52 | 显示全部楼层
飞凌-unix 发表于 2013-10-24 16:56
RS485 驱动 源码路径 : drivers/tty/serial/omap-serial.c

上的几个函数就是从这个源码路径复制的!
点评回复 支持 反对

使用道具 举报

153

主题

3910

帖子

4207

积分

AM5718通行证AM335x通行证i.MX6UL通行证i.MX RT通行证i.MX6Q通行证XX18通行证TCU通行证FCU1401通行证FCU1301通行证FCU11xx通行证

发表于 2013-10-28 08:35:38 | 显示全部楼层
楼主如果你想写的是驱动程序,单单复制代码是不行的,其他的东西也要改啊,你有没有屏蔽之前的驱动啊?
技术支持电话:0312-3119192
技术支持邮箱:Linux@forlinx.com
点评回复 支持 反对

使用道具 举报

阿尔巴 该用户已被删除
发表于 2013-12-10 11:09:20 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
点评回复 支持 反对

使用道具 举报

0

主题

1836

帖子

1028

积分

发表于 2013-12-10 11:17:15 | 显示全部楼层
楼上朋友,正解,RS485的驱动是有“串口驱动+GPIO控制”实现的,GPIO控制部分体现在用户程序,楼主可以看一下我们的RS485测试APP,近期将发布最新测试程序,里面会含有RS485测试源码,有GPIO控制部分,如果着急需要可以联系技术服务部门,或者加我的工作QQ:2652547374.

点评

485的测试程序在哪个文件夹?  详情 回复 发表于 2014-8-25 17:37
该会员没有填写今日想说内容.
点评回复 支持 反对

使用道具 举报

阿尔巴 该用户已被删除
发表于 2014-8-25 17:37:26 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
点评回复 支持 反对

使用道具 举报

0

主题

1836

帖子

1028

积分

发表于 2014-9-10 15:43:34 | 显示全部楼层
RS485的测试位于光盘目录:OK335xD光盘资料(A)\linux\src\test.tar.bz2 测试程序压缩包中。
该会员没有填写今日想说内容.
点评回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋| 飞凌嵌入式 ( 冀ICP备12004394号-1 )

GMT+8, 2024-12-21 02:20

Powered by Discuz! X3.4

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表