日韩一区二区三区精品,欧美疯狂xxxxbbbb牲交,热99re久久免费视精品频,人妻互换 综合,欧美激情肉欲高潮视频

歷史上的今天

今天是:2025年07月21日(星期一)

2021年07月21日 | 24.Linux-2440下的DMA驅(qū)動

發(fā)布者:腦電狂徒 來源: eefocus關(guān)鍵字:Linux  DMA驅(qū)動 手機(jī)看文章 掃描二維碼
隨時(shí)隨地手機(jī)看文章

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)志定義在,常用標(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                 dest_virt[i] =  source_virt[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");

[1] [2]
關(guān)鍵字:Linux  DMA驅(qū)動 引用地址:24.Linux-2440下的DMA驅(qū)動

上一篇:27.3.4.2內(nèi)核下的I2C驅(qū)動(二)
下一篇:25.Linux-實(shí)現(xiàn)U盤自動掛載

推薦閱讀

名稱:IO口總結(jié) 說明:最近橫向?qū)W習(xí)了51單片機(jī)、STM32和S3C2440的IO口,做了幾個(gè)相關(guān)的實(shí)驗(yàn)。 我們數(shù)據(jù)結(jié)構(gòu)老師曾經(jīng)說過 ”差異就是知識“。在此,比較了這幾個(gè)芯片IO口的使用后,有些感悟,總結(jié)如下:1.IO口是芯片內(nèi)部CPU和外設(shè)之間溝通的橋梁,也是其他模塊(如I2C通訊、SPI通訊)的基礎(chǔ)。不同的芯片對IO的操作不太相同,但很類似。高級一點(diǎn)的芯片(如S...
節(jié)卡機(jī)器人億元B輪融資刷新國內(nèi)協(xié)作機(jī)器人領(lǐng)域最高單筆融資,樹根互聯(lián)5億B輪融資創(chuàng)下中國工業(yè)互聯(lián)網(wǎng)平臺融資金額的全新紀(jì)錄,曠視科技7.5億美元D輪融資成今年融資大戶。今年上半年,工業(yè)機(jī)器人融資依然熱鬧。 據(jù)不完全統(tǒng)計(jì),2019年上半年,工業(yè)機(jī)器人領(lǐng)域累計(jì)融資案例達(dá)43起,AGV、、工業(yè)互聯(lián)網(wǎng)這三個(gè)細(xì)分領(lǐng)獲得融資的企業(yè)最多,融資案例分別為11起、1...
華為旗下一款麥芒新機(jī)在工信部入網(wǎng),工信部證件照以及部分參數(shù)信息曝光?! ⊥庥^方面,從工信部網(wǎng)站放出的證件照來看,這款麥芒新機(jī)采用目前比較主流的打孔全面屏設(shè)計(jì),前置1600萬像素相機(jī)開孔位于屏幕左上角,證件照顯示的開孔直徑并不算大?! ”巢繖C(jī)身,該機(jī)后置豎排三攝,具體為6400萬像素主攝+800萬像素副攝+ 200 像素副攝的三攝組合。...
PLL OSC簡述:S12CPMU Block Diagram:S12CPMU Synthesizer Register(CPMUSYNR)PLL相關(guān)主要寄存器:CPMUPROT:時(shí)鐘配置寄存器保護(hù)Clock Configuration Registers Protection Bit — This bit protects the clock configuration registers fromaccidental overwrite (see list of affected registers above):Writing 0x26 to the...

史海拾趣

小廣播
設(shè)計(jì)資源 培訓(xùn) 開發(fā)板 精華推薦

最新單片機(jī)文章

 
EEWorld訂閱號

 
EEWorld服務(wù)號

 
汽車開發(fā)圈

 
機(jī)器人開發(fā)圈

電子工程世界版權(quán)所有 京ICP證060456號 京ICP備10001474號-1 電信業(yè)務(wù)審批[2006]字第258號函 京公網(wǎng)安備 11010802033920號 Copyright ? 2005-2025 EEWORLD.com.cn, Inc. All rights reserved