1.DMA(Direct Memory Access)
??即直接存儲器訪問, DMA 傳輸方式無需 CPU 直接控制傳輸,通過硬件為 RAM 、I/O 設(shè)備開辟一條直接傳送數(shù)據(jù)的通路,能使 CPU 的效率大為提高。
??學(xué)了這么多驅(qū)動,不難推出DMA的編寫套路:
??1)注冊DMA中斷,分配緩沖區(qū)
??2)注冊字符設(shè)備,并提供文件操作集合fops
?? -> 2.1)file_operations里設(shè)置DMA硬件相關(guān)操作,來啟動DMA
?由于我們是用字符設(shè)備的測試方法測試的,而本例子只是用兩個(gè)地址之間的拷貝來演示DMA的作用,所以采用字符設(shè)備方式編寫
2.驅(qū)動編寫之前,先來講如何分配釋放緩沖區(qū)、DMA相關(guān)寄存器介紹、使用DMA中斷
2.1在linux中,分配釋放DMA緩沖區(qū),常用以下幾個(gè)函數(shù)
1)
/*該函數(shù)只禁止cache緩沖,保持寫緩沖區(qū),也就是對注冊的物理區(qū)寫入數(shù)據(jù),也會更新到對應(yīng)的虛擬緩存區(qū)上*/
void *dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp);
//分配DMA緩存區(qū)
//返回值為:申請到的DMA緩沖區(qū)的虛擬地址,若為NULL,表示分配失敗,需要釋放,避免內(nèi)存泄漏
//參數(shù)如下:
//*dev:指針,這里填0,表示這個(gè)申請的緩沖區(qū)里沒有內(nèi)容
//size:分配的地址大小(字節(jié)單位)
//*handle:申請到的物理起始地址
//gfp:分配出來的內(nèi)存參數(shù),標(biāo)志定義在 //GFP_ATOMIC 用來從中斷處理和進(jìn)程上下文之外的其他代碼中分配內(nèi)存. 從不睡眠. //GFP_KERNEL 內(nèi)核內(nèi)存的正常分配. 可能睡眠. //GFP_USER 用來為用戶空間頁來分配內(nèi)存; 它可能睡眠. 2) /*該函數(shù)禁止cache緩存以及禁止寫入緩沖區(qū),從而使CPU讀寫的地址和DMA讀寫的地址內(nèi)容一致*/ void * dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp); //分配DMA緩存區(qū),返回值和參數(shù)和上面的函數(shù)一直 3) dma_free_writecombine(struct device *dev, size_t size, void *cpu_addr, dma_addr_t handle); //釋放DMA緩存,與dma_alloc_writecombine()對應(yīng) //size:釋放長度 //cpu_addr:虛擬地址, //handle:物理地址 4) dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr_t handle) //釋放DMA緩存,與dma_alloc_coherent ()對應(yīng) //size:釋放長度 //cpu_addr:虛擬地址, //handle:物理地址 (PS: dma_free_writecombine()其實(shí)就是dma_free_conherent(),只不過是用了#define重命名而已。) ?而我們之前用的內(nèi)存分配kmalloc()函數(shù),是不能用在DMA上,因?yàn)榉峙涑鰜淼膬?nèi)存在物理地址上是不連續(xù)的(在虛擬地址上連續(xù)). 2.2 那么2440開發(fā)板如何來啟動DMA,先來看2440的DMA寄存器 (PS:實(shí)際這些DMA相關(guān)的寄存器,在linux內(nèi)核中三星已封裝好了,可以直接調(diào)用,不過非常麻煩,還不如直接設(shè)置寄存器,可以參考: http://blog.csdn.net/mirkerson/article/details/6632273) 2.2.1 2440支持4個(gè)通道的DMA控制器 ?其中4個(gè)通道的DMA外設(shè)請求源,如下圖所示(通過DCONn寄存器的[26:24]來設(shè)置) (PS:如果請求源是系統(tǒng)總線上的,就只需要設(shè)置DCONn寄存器的[23]=0即可) 2.2.2 且每個(gè)通道都可以處理以下4種情況: ?1) 源和目標(biāo)都在系統(tǒng)總線上(比如:兩個(gè)物理內(nèi)存地址) ?2) 當(dāng)目標(biāo)在外設(shè)總線上時(shí),源在系統(tǒng)總線上(外設(shè)指:串口,定時(shí)器,I2C,I2S等) ?3) 當(dāng)目標(biāo)在系統(tǒng)總線上時(shí),源在外設(shè)總線上 ?4) 源和目標(biāo)都在外設(shè)總線上 2.2.3 DMA有兩種工作模式(通過DCONn寄存器的[28]來設(shè)置) ??查詢模式: ??當(dāng)DMA請求XnXDREQ為低電平時(shí),則DMA會一直傳輸數(shù)據(jù),直到DMA請求拉高,才停止 ??握手模式: ??當(dāng)DMA請求XnXDREQ有下降沿觸發(fā)時(shí),則DMA會傳輸一次數(shù)據(jù) 2.2.4 DMA有兩種傳輸模式(通過DCONn寄存器的[31]來設(shè)置) ??單元傳輸: ??指傳輸過程中,每執(zhí)行一次,則讀1次,寫1次.(如上圖所示) ??突發(fā)4傳輸: ??指傳輸過程中,每執(zhí)行一次,則讀4次,然后寫4次(如下圖所示) 2.2.5 2440中的DMA寄存器如下圖所示: ??共有4個(gè)通道的寄存器,且每個(gè)通道的寄存器內(nèi)容都一致,所以我們以DMA通道0為例: ??1)DISRC0初始源寄存器 ??[30:0] : 存放DMA源的基地址 ??2)DISRCC0初始源控制寄存器 ??[1] : 源位置選擇,0:源在系統(tǒng)總線上, 1:源在外設(shè)總線上 ??[0] : 源地址選擇,0:傳輸時(shí)源地址自動增加, 1:源地址固定 ??3)DIDST0初始目標(biāo)寄存器 ??[30:0] : 設(shè)置DMA目的的基地址 ??4)DIDSTC0初始目標(biāo)控制寄存器 ??[2] : 中斷時(shí)間選擇, 0:當(dāng)DMA傳輸計(jì)數(shù)=0,立即發(fā)生中斷 1:執(zhí)行完自動加載后再發(fā)送中斷(也就是計(jì)數(shù)為0,然后重新加載計(jì)數(shù)值) ??[1] : 目的位置選擇, 0:目的在系統(tǒng)總線上, 1:目的在外設(shè)總線上 ??[0] : 目的地址選擇, 0:傳輸時(shí)目的地址自動增加, 1:目的地址固定 ??5)DCON0控制寄存器 ??[31] : 工作模式選擇, 0:查詢模式 1:握手模式 (當(dāng)源處于外設(shè)時(shí),盡量選擇握手模式) ??[30] : 中斷請求(DREQ)/中斷回應(yīng)(DACK)的同步時(shí)鐘選擇, 0:PCLK同步 1:HCLK同步 (PS:如果有設(shè)備在HCLK上,該位應(yīng)當(dāng)設(shè)為1,比如:(SDRAM)內(nèi)存數(shù)組, 反之當(dāng)這些設(shè)備在PCLK上,應(yīng)當(dāng)設(shè)為0,比如:ADC,IIS,I2C,UART) ??[29] : DMA傳輸計(jì)數(shù)中斷使能/禁止 0:禁止中斷 1:當(dāng)傳輸完成后,產(chǎn)生中斷 ??[28] : 傳輸模式選擇, 0:單元傳輸 1:突發(fā)4傳輸 ??[27] : 傳輸服務(wù)模式 ??0:單服務(wù)模式,比如:有2個(gè)DMA請求,它們會被順序執(zhí)行一次(單元傳輸/突發(fā)4傳輸)后停止,然后直到有下一次DMA請求,再重新開始另一次循環(huán)。 ??1:全服務(wù)模式,指該DMA若有請求,則會占用DMA總線,一直傳輸,期間若有其它DMA請求,只有等待傳輸計(jì)數(shù)TC為0,才會執(zhí)行其它DMA請求 ??[26:24] : DMA外設(shè)請求源選擇 ??[23] : 軟件/硬件請求源選擇 0:軟件請求 1:硬件請求(還需要設(shè)置[26:24]來選擇外設(shè)源) ??[22] : 重新加載開關(guān)選項(xiàng) 為0即可 ??[21:20] : 傳輸數(shù)據(jù)大小 為00(8位)即可 ??[19:0] : 設(shè)置DMA傳輸?shù)挠?jì)數(shù)TC ??6)DSTAT0狀態(tài)寄存器 ??[21:20] : DMA狀態(tài) 00:空閑 01:忙 ??[19:0] : 傳輸計(jì)數(shù)當(dāng)前值CURR_TC 為0表示傳輸結(jié)束 ??7)DCSRC0當(dāng)前源寄存器 ??[30:0] : 存放DMA當(dāng)前的源基地址 ??8)DCDST0當(dāng)前目標(biāo)寄存器 ??[30:0] : 存放DMA當(dāng)前的目的基地址 ??9)DMASKTRIG0觸發(fā)屏蔽寄存器 ??[2] : 停止STOP 該位寫1,立刻停止DMA當(dāng)前的傳輸 ??[1] : DMA通道使能 0:關(guān)閉DMA的通道0(禁止DMA請求) 1:開啟DMA的通道0(開啟DMA請求) ??[0] : 軟件請求觸發(fā) 1:表示啟動一次軟件請求DMA,只有DCONn[23]=0和DMASKTRIGn[1]=1才有效,DMA傳輸時(shí),該位自動清0 2.3接下來就開始講linux注冊DMA中斷 ??首先,DMA的每個(gè)通道只能有一個(gè)源- >目的,所以輸入命令 cat /proc/interrupts ,找到DMA3中斷未被使用 ??所以在linux中使用: request_irq(IRQ_DMA3, s3c_dma_irq, NULL, "s3c_dma", 1);// s3c_dma_irq:中斷服務(wù)函數(shù),這里注冊DMA3中斷服務(wù)函數(shù) //NULL:中斷產(chǎn)生類型, 不需要,所以填NULL //1:表示中斷時(shí),傳入中斷函數(shù)的參數(shù),本節(jié)不需要所以填1,切記不能填0,否則注冊失敗 3.接下來,我們便來寫一個(gè)DMA的字符設(shè)備驅(qū)動 步驟如下: ??1) 注冊DMA中斷,分配兩個(gè)DMA緩沖區(qū)(源、目的) ??2) 注冊字符設(shè)備,并提供文件操作集合fops ??-> 2.1) 通過ioctl的cmd來判斷是使用DMA啟動兩個(gè)地址之間的拷貝,還是直接兩個(gè)地址之間的拷貝 ??-> 2.2)若是DMA啟動,則設(shè)置DMA的相關(guān)硬件,并啟動DMA傳輸 #include #include #include #include #include #include #include #include #include #include #include #include #define S3C_DMA_SIZE 512*1024 //DMA傳輸長度 512KB #define NORMAL_COPY 0 //兩個(gè)地址之間的正??截?p>#define DMA_COPY 1 //兩個(gè)地址之間的DMA拷貝 /*函數(shù)聲明*/ static DECLARE_WAIT_QUEUE_HEAD(s3c_dma_queue); //聲明等待隊(duì)列 static int s3c_dma_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long flags); /* * 定義中斷事件標(biāo)志 * 0:進(jìn)入等待隊(duì)列 1:退出等待隊(duì)列 */ static int s3c_dma_even=0; static unsigned char *source_virt; //源虛擬地址 static unsigned int source_phys; //源物理地址 static unsigned char *dest_virt; //目的虛擬地址 static unsigned int dest_phys; //目的虛擬地址 /*DMA3寄存器*/ struct S3c_dma3_regs{ unsigned int disrc3 ; //0x4b0000c0 unsigned int disrcc3 ; unsigned int didst3 ; unsigned int didstc3 ; unsigned int dcon3 ; unsigned int dstat3 ; unsigned int dcsrc3 ; unsigned int dcdst3 ; unsigned int dmasktrig3; //0x4b0000e0 }; static volatile struct S3c_dma3_regs *s3c_dma3_regs; /*字符設(shè)備操作*/ static struct file_operations s3c_dma_fops={ .owner = THIS_MODULE, .ioctl = s3c_dma_ioctl, }; /*中斷服務(wù)函數(shù)*/ static irqreturn_t s3c_dma_irq (int irq, void *dev_id) { s3c_dma_even=1; //退出等待隊(duì)列 wake_up_interruptible(&s3c_dma_queue); //喚醒 中斷 return IRQ_HANDLED; } /*ioctl函數(shù)*/ static int s3c_dma_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long flags) { int i; memset(source_virt, 0xAA, S3C_DMA_SIZE); memset(dest_virt, 0x55, S3C_DMA_SIZE); switch(cmd) { case NORMAL_COPY: //正常拷貝 for(i=0;i if(memcmp(dest_virt, source_virt, S3C_DMA_SIZE)==0) { printk("NORMAL_COPY OKn"); return 0; } else { printk("NORMAL_COPY ERRORn"); return -EAGAIN; } case DMA_COPY: //DMA拷貝 s3c_dma_even=0; //進(jìn)入等待隊(duì)列 /*設(shè)置DMA寄存器,啟動一次DMA傳輸 */ /* 源的物理地址 */ s3c_dma3_regs->disrc3 = source_phys; /* 源位于AHB總線, 源地址遞增 */ s3c_dma3_regs->disrcc3 = (0<<1) | (0<<0); /* 目的的物理地址 */ s3c_dma3_regs->didst3 = dest_phys; /* 目的位于AHB總線, 目的地址遞增 */ s3c_dma3_regs->didstc3 = (0<<2) | (0<<1) | (0<<0); /* 使能中斷,單個(gè)傳輸,軟件觸發(fā), */ s3c_dma3_regs->dcon3=(1<<30)|(1<<29)|(0<<28)|(1<<27)|(0<<23)|(0<<20)|(S3C_DMA_SIZE<<0); //啟動一次DMA傳輸 s3c_dma3_regs->dmasktrig3 = (1<<1) | (1<<0); wait_event_interruptible(s3c_dma_queue, s3c_dma_even); //進(jìn)入睡眠,等待DMA傳輸中斷到來才退出 if(memcmp(dest_virt, source_virt, S3C_DMA_SIZE)==0) { printk("DMA_COPY OKn");
上一篇:27.3.4.2內(nèi)核下的I2C驅(qū)動(二)
下一篇:25.Linux-實(shí)現(xiàn)U盤自動掛載
推薦閱讀
史海拾趣
設(shè)計(jì)資源 培訓(xùn) 開發(fā)板 精華推薦
- 神經(jīng)形態(tài)芯片可能是革新機(jī)器人實(shí)時(shí)電機(jī)控制的未來
- 從三個(gè)方面理解ARM嵌入式系統(tǒng)
- 自動報(bào)警 基于MCU的家庭防盜報(bào)警系統(tǒng)的設(shè)計(jì)
- 存儲控制器及其訪問外設(shè)的原理
- 基于51系列單片機(jī)的智能照明控制系統(tǒng)設(shè)計(jì)方案
- 基于STM32的四旋翼飛行器控制系統(tǒng)
- 單片機(jī)應(yīng)用編程技巧解析
- 基于89C52的教室智能節(jié)能照明系統(tǒng)設(shè)計(jì)
- 一種新型的雨量光照傳感器的設(shè)計(jì)
- 孚能科技全固態(tài)電池中試線年底建成,能量密度超400Wh/kg
- 比亞迪新專利:電池尺寸不變,續(xù)航大幅提升
- 豐田子公司37億大連建廠首次在中國生產(chǎn)純電汽車電池
- 博泰車聯(lián)網(wǎng)沖刺港股:上海灘走出的汽車智能化隱形冠軍
- 從自動駕駛到具身智能,激光雷達(dá)緣何一邊被嫌棄,一邊被追捧?
- 軟件定義車輛改變汽車行業(yè)的3種方式
- 混合動力汽車也是超級跑車:強(qiáng)調(diào)性能,而不是里程
- 人形機(jī)器人風(fēng)口下,六維力傳感器成為國產(chǎn)廠商“卡位”關(guān)鍵點(diǎn)
- AURIX? TC4x虛擬化技術(shù)詳解
- 從荔枝的“鮮和煎”,看英特爾銳炫Pro B60的AI空間折疊魔術(shù)
- 英特爾芯片的高管Jim Keller離任
- 批評澳大利亞5G部署,華為:無計(jì)劃為澳提供全國性5G
- 智慧存儲芯片公司,英韌科技獲新一輪融資
- 仍外購大量芯片,銀河微電“科創(chuàng)”屬性在哪里?
- 印度代工廠產(chǎn)能下降,小米和OPPO等或從國內(nèi)調(diào)貨
- 集微指數(shù)下跌1.01% 高通創(chuàng)投再投3家中國公司
- 兼顧高性能與低功耗,華米第二款自研芯片將來?
- 面板公司的專利戰(zhàn),惠科無效天馬液晶互連組件專利
- 華為手機(jī)芯片被“封印”,聯(lián)發(fā)科會否受益?
- 加拿大安全情報(bào)局前負(fù)責(zé)人:禁止華為對加拿大影響有限