生活随笔
收集整理的這篇文章主要介紹了
6410 实现 linux 串口驱动详解
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
為了實(shí)現(xiàn)串口通信,需要在嵌入式linux下編寫相應(yīng)的驅(qū)動(dòng)程序。在嵌入式系統(tǒng)中,串口被看做終端設(shè)備tty。終端設(shè)備是unix體系中一個(gè)非常重要的對象,內(nèi)容非常復(fù)雜,它是整個(gè)unix人機(jī)交互的基礎(chǔ),其地位并不亞于文件系統(tǒng)在操作系統(tǒng)中的作用。筆者muge0913在此對uart驅(qū)動(dòng)進(jìn)行整理。
本文章僅供技術(shù)交流請勿商用。轉(zhuǎn)載請標(biāo)明出處:http://blog.csdn.net/muge0913/article/details/7060254
一、串口概述
???? 串口分為:同步傳輸(usrt)和異步傳輸(uart),其中異步傳輸是嵌入系統(tǒng)中最長用的通信設(shè)備,串口常被當(dāng)做控制臺(tái)使用。
①同步傳輸:發(fā)送端和接收端使用同一個(gè)時(shí)鐘。其時(shí)序如下:
②異步傳輸:在數(shù)據(jù)傳輸過程中,接收時(shí)鐘和發(fā)送時(shí)鐘是不同步的,即在串行總線上并沒有時(shí)鐘線。
傳輸前有相應(yīng)的起始位,然后緊接著發(fā)送數(shù)據(jù)位(5~8位有用戶定義),最后是奇偶校驗(yàn)位和停止位。如圖:
二、串口物理層連接問題
?? 因?yàn)榇陔娎|有交叉和直連接之分,其接口有公頭和母頭之分,所以其連接有6中連接方式:
?? ①兩頭公頭的直線電纜
?? ②兩頭母頭的交叉線
?? ③兩頭公頭的交叉線
?? ④兩個(gè)母頭的直線電纜
?? ⑤一公頭一母頭的直線電纜
?? ⑥一公頭一母頭的交叉線
?? 在大多數(shù)的異步通信中不需要流的控制,所以3根線就能滿座嵌入式設(shè)備通信的要求,但是為了保持兼容常常使用下面的連接方法:
三、arm11中的uart
①概述:
??? S3C6410X的UART提供四個(gè)獨(dú)立的異步串行I / O(SIO)端口。異步串行I / O(SIO)端口,每個(gè)都可以在基于中斷或基于DMA模式。換句話說,UART可以產(chǎn)生中斷或DMA請求MEM和UART之間的數(shù)據(jù)傳輸。UART也可支持最大3Mbps的比特率。每個(gè)UART通道包含兩個(gè)64字節(jié)的FIFO的接收和傳輸?shù)摹?/span>
②特點(diǎn)
四、寄存器配置(略請開發(fā)者閱讀芯片資料和參考下列代碼中的注釋)
五、驅(qū)動(dòng)源碼:
[cpp]?view plaincopyprint?
#include?<linux/module.h>?? #include?<linux/ioport.h>?? #include?<linux/io.h>?? #include?<linux/platform_device.h>?? #include?<linux/init.h>?? #include?<linux/serial_core.h>?? #include?<linux/serial.h>?? ?? #include?<asm/irq.h>?? #include?<mach/hardware.h>?? ?? #include?<plat/regs-serial.h>?? ?? #include?"samsung.h"?? ?? static?int?s3c6400_serial_setsource(struct?uart_port?*port,?? ????????????????????struct?s3c24xx_uart_clksrc?*clk)?? {?? ????unsigned?long?ucon?=?rd_regl(port,?S3C2410_UCON);?? ?? ????if?(strcmp(clk->name,?"uclk0")?==?0)?{?? ????????ucon?&=?~S3C6400_UCON_CLKMASK;?? ????????ucon?|=?S3C6400_UCON_UCLK0;?? ????}?else?if?(strcmp(clk->name,?"uclk1")?==?0)?? ????????ucon?|=?S3C6400_UCON_UCLK1;?? ????else?if?(strcmp(clk->name,?"pclk")?==?0)?{?? ?????????? ????????ucon?&=?~S3C6400_UCON_UCLK0;?? ????}?else?{?? ????????printk(KERN_ERR?"unknown?clock?source?%s\n",?clk->name);?? ????????return?-EINVAL;?? ????}?? ?? ????wr_regl(port,?S3C2410_UCON,?ucon);?? ????return?0;?? }?? ?? ?? static?int?s3c6400_serial_getsource(struct?uart_port?*port,?? ????????????????????struct?s3c24xx_uart_clksrc?*clk)?? {?? ????u32?ucon?=?rd_regl(port,?S3C2410_UCON);?? ?? ????clk->divisor?=?1;?? ?? ????switch?(ucon?&?S3C6400_UCON_CLKMASK)?{?? ????case?S3C6400_UCON_UCLK0:?? ????????clk->name?=?"uclk0";?? ????????break;?? ?? ????case?S3C6400_UCON_UCLK1:?? ????????clk->name?=?"uclk1";?? ????????break;?? ?? ????case?S3C6400_UCON_PCLK:?? ????case?S3C6400_UCON_PCLK2:?? ????????clk->name?=?"pclk";?? ????????break;?? ????}?? ?? ????return?0;?? }?? ?? static?int?s3c6400_serial_resetport(struct?uart_port?*port,?? ????????????????????struct?s3c2410_uartcfg?*cfg)?? {?? ????unsigned?long?ucon?=?rd_regl(port,?S3C2410_UCON);?? ?? ????dbg("s3c6400_serial_resetport:?port=%p?(%08lx),?cfg=%p\n",?? ????????port,?port->mapbase,?cfg);?? ?? ?????? ?? ????ucon?&=?S3C6400_UCON_CLKMASK;?? ?? ????wr_regl(port,?S3C2410_UCON,??ucon?|?cfg->ucon);?? ????wr_regl(port,?S3C2410_ULCON,?cfg->ulcon);?? ?? ?????? ?? ????wr_regl(port,?S3C2410_UFCON,?cfg->ufcon?|?S3C2410_UFCON_RESETBOTH);?? ????wr_regl(port,?S3C2410_UFCON,?cfg->ufcon);?? ?? ????return?0;?? }?? ?? static?struct?s3c24xx_uart_info?s3c6400_uart_inf?=?{?? ????.name???????=?"Samsung?S3C6400?UART",?? ????.type???????=?PORT_S3C6400,?? ????.fifosize???=?64,?? ????.has_divslot????=?1,?? ????.rx_fifomask????=?S3C2440_UFSTAT_RXMASK,?? ????.rx_fifoshift???=?S3C2440_UFSTAT_RXSHIFT,?? ????.rx_fifofull????=?S3C2440_UFSTAT_RXFULL,?? ????.tx_fifofull????=?S3C2440_UFSTAT_TXFULL,?? ????.tx_fifomask????=?S3C2440_UFSTAT_TXMASK,?? ????.tx_fifoshift???=?S3C2440_UFSTAT_TXSHIFT,?? ????.get_clksrc?=?s3c6400_serial_getsource,?? ????.set_clksrc?=?s3c6400_serial_setsource,?? ????.reset_port?=?s3c6400_serial_resetport,?? };?? ?? ?? ?? static?int?s3c6400_serial_probe(struct?platform_device?*dev)?? {?? ????dbg("s3c6400_serial_probe:?dev=%p\n",?dev);?? ????return?s3c24xx_serial_probe(dev,?&s3c6400_uart_inf);?? }?? ?? static?struct?platform_driver?s3c6400_serial_driver?=?{?? ????.probe??????=?s3c6400_serial_probe,?? ????.remove?????=?__devexit_p(s3c24xx_serial_remove),?? ????.driver?????=?{?? ????????.name???=?"s3c6400-uart",?? ????????.owner??=?THIS_MODULE,?? ????},?? };?? ?? s3c24xx_console_init(&s3c6400_serial_driver,?&s3c6400_uart_inf);?? ?? static?int?__init?s3c6400_serial_init(void)?? {?? ????return?s3c24xx_serial_init(&s3c6400_serial_driver,?&s3c6400_uart_inf);?? }?? ?? static?void?__exit?s3c6400_serial_exit(void)?? {?? ????platform_driver_unregister(&s3c6400_serial_driver);?? }?? ?? module_init(s3c6400_serial_init);?? module_exit(s3c6400_serial_exit);?? ?? MODULE_AUTHOR("muge0913");?? MODULE_LICENSE("GPL?v2");?? MODULE_ALIAS("platform:s3c6400-uart"); ?
總結(jié)
以上是生活随笔為你收集整理的6410 实现 linux 串口驱动详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。