最近这几天准备用串口实现DMA的传输数据,刚开始研究三天DMA,结果是一脸懵逼,无奈之下,只能跑去研究串口,结果发现Linux系统串口和DMA是真的难(小白,而且没人一起研究!),芯片手册对应的页数可以让人放弃,最后还是放弃看芯片手册,从网上百度开始,看看前人的总结,最终写下以下总结笔记(以下仅为笔记,实际上我并没有实现用DMA实现串口传输数据)。
系统:linux3.0.15
cpu:imxdl
一、DMA
首先阅读前人的参考文献:
1、这是有关i.MX51的SDMA内核的简短教程:
乔纳的博客
ELI的博客
要是你基础扎实,按照上面大牛的教程,基本就可以实现SDMA传输了。
2、这是恩智浦上的一个帖子,里面又许多大牛对DMA的见解与资料
通过以上外文博客再加上自己百度的东西,基本就明白DMA的基本操作了。
二、串口波特率设置与SDMA传输
首先阅读前人的参考文献:
1、jkan2001的博客:IMX6增加UART口的操作步骤
2、 恩智浦技术社区 :imx6平台串口通信问题
3、漫不经心博客:
tty初探—uart驱动框架分析(一)
uart驱动框架分析(二)
4、嘉明的博客: IMX6DL 串口驱动分析
主要有以下4篇文章
5、o777788的博客:imx6 UART 驱动分析
6、明远智睿技术论坛:imx6 uart开启DMA
7、苏西守护者的博客:imx6的uart小结(1)
8、美丽的时光机器的博客:uart&tty驱动
参照以上文献,足以将串口修改为DMA传输。
三、串口DMA及波特率的设置
虽然我没有实现用DMA传输数据,但如果用在应用层实现数据传输的话,我觉得我就差最后一部了(验证是否可以DMA传输),为了以后再进一步研究,把串口的SDMA配置过程记录下来。
与串口相关的函数及头文件如下所示:
1、首先配置好io口,具体配置参考上面的博客。 其实串口的DMA设置非常简单在board-mx6q_sabresd.c中有
static inline void mx6q_sabresd_init_uart(void)
{
imx6q_add_imx_uart(2, NULL);
imx6q_add_imx_uart(0, NULL);
}
上面两句就是配置串口1和串口3.
在board-mx6q_arm2.c有
static const struct imxuart_platform_data mx6_arm2_uart1_data __initconst = {
.flags = IMXUART_HAVE_RTSCTS | IMXUART_USE_DCEDTE | IMXUART_SDMA,
.dma_req_rx = MX6Q_DMA_REQ_UART2_RX,
.dma_req_tx = MX6Q_DMA_REQ_UART2_TX,
};
static inline void mx6_arm2_init_uart(void)
{
imx6q_add_imx_uart(3, NULL);
imx6q_add_imx_uart(1, &mx6_arm2_uart1_data);
}
从上面可以看到串口2通过.flag或上了SDMA,这就是配置SDMA了,也就是说系统自带的串口2是打开了SDMA,要打开其他串口的SDMA的话只需下一个imxuart_platform_data 函数,照葫芦画瓢就行了,最后在应用层调用串口就可以了。(以上是我的个人见解,若那位网友验证了该想法的可行性,麻烦请评论留言,大家相互借鉴)
2、串口波特率的修改,若直接用应用层调用串口的话一句话即可实现,然而,要是不调用函数怎么修改串口控制默认值呢?
首先,我们要清楚串口的驱动虽然写在内核,但它和uboot与跟文件系统都是有关的,具体参考 :linux console驱动详解
打开uboot,找到相关的config,如们708dl.h
上面定义的就是115200波特率。
一般而言,串口在哪里初始化的就修改那个.h文件。
修改完成后,发现开机时出现卡死,这是因为rc_mxc.S的设置和uboot的设置不一样,
打开根文件的rc_mxc.S如下,将自己所要修改的串口默认波特率修改就可以了。