如果不曾相逢 也許 心緒永遠不會沉重 如果真的失之交臂 恐怕一生也不得輕松 一個眼神 便足以讓心海 掠過颶風
在貧瘠的土地上 更深地懂得風景 一次遠行 便足以憔悴了一顆 羸弱的心
每望一眼秋水微瀾 便恨不得 淚水盈盈 死怎能不 從容不迫 愛又怎能 無動於衷
只要彼此愛過一次 就是無憾的人生
也許 也許,永遠沒有那一天 前程如朝霞般絢爛 也許,永遠沒有那一天
成功如燈火般輝煌 也許,只能是這樣 攀援卻達不到峰頂 也許,只能是這樣 奔流卻掀不起波浪
也許,我們能給予你的 只有一顆 飽經滄桑的心 和滿臉風霜
也許有些事情早已經寫好,也許一顆心早已經注定,只是在騙自己,她還在愛着你~
DMA概述
DMA是一種無需CPU的參加就可以讓外設與系統內存之間進行雙向數據傳輸的硬件機制。它可以使系統CPU從實際的I/O數據傳輸過程中擺脫出來,大大提高系統的吞吐率,並且在傳輸期間,CPU還可以並發執行其他任務。
DMA與cache的一致性
cache用作CPU針對內存的緩存,避免CPU每一次都要與相對來說慢點的內存交互數據,從而來提高數據的訪問速率,而DMA可以用作內存與外設之間傳輸數據的方式,數據不需要經過CPU周轉。
“假設設備驅動程序把一些數據填充到內存緩沖區中,然后立刻命令硬件設備利用DMA傳送方式讀取該數據。如果DMA訪問這些物理RAM內存單元,而相應的硬件高速緩存行的內容還沒有寫入RAM中,那么硬件設備所讀取的至就是內存緩沖區中的舊值。”
alloc_pages(gfp_mask,order) 返回第一個所分配頁框描述符的地址,或者如果分配失敗則返回NULL。 __get_free_pages(gfp_mask,order) 類似於alloc_pages(),但它返回第一個所分配頁的線性地址。如果需要獲得線性地址對應的頁框號,那么需要調用virt_to_page(addr)宏產生線性地址。
釋放函數:
__free_pages(page,order) 這里主要強調page是要釋放緩沖區的線性首地址所在的頁框號 free_pages(page,order) 這個函數類似於__free_pages(page,order),但是它接收的參數為要釋放的第一個頁框的線性地址addr
DMA驅動主要數據結構:
1)DMA單個內核緩沖區數據結構:
typedef struct dma_buf_s { int size; /* buffer size:緩沖大小 */ dma_addr_t dma_start; /* starting DMA address :緩沖區起始物理地址*/ int ref; /* number of DMA references 緩沖區起始虛擬地址*/ void *id; /* to identify buffer from outside 標記 */ int write; /* 1: buf to write , 0: buf to read DMA讀還是寫*/ struct dma_buf_s *next; /* next buf to process 指向下一個緩沖區結構*/ } dma_buf_t;
2)DMA寄存器數據結構:
/* DMA control register structure */ typedef struct { volatile u_long DISRC;/源地址寄存器 volatile u_long DISRCC;//源控制寄存器 volatile u_long DIDST;//目的寄存器 volatile u_long DIDSTC;//目的控制寄存器 volatile u_long DCON;//DMA控制寄存器 volatile u_long DSTAT;//狀態寄存器 volatile u_long DCSRC;//當前源 volatile u_long DCDST;//當前目的 volatile u_long DMASKTRIG;//觸發掩碼寄存器 } dma_regs_t;
3)DMA設備數據結構
/* DMA device structre */ typedef struct { dma_callback_t callback;//DMA操作完成后的回調函數,在中斷處理例程中調用 u_long dst;//目的寄存器內容 u_long src;//源寄存器內容 u_long ctl;//此設備的控制寄存器內容 u_long dst_ctl;//目的控制寄存器內容 u_long src_ctl;//源控制寄存器內容 } dma_device_t;
4)DMA通道數據結構
/* DMA channel structure */ typedef struct { dmach_t channel;//通道號:可為0,1,2,3 unsigned int in_use; /* Device is allocated 設備是否已*/ const char *device_id; /* Device name 設備名*/ dma_buf_t *head; /* where to insert buffers 該DMA通道緩沖區鏈表頭*/ dma_buf_t *tail; /* where to remove buffers該DMA通道緩沖區鏈表尾*/ dma_buf_t *curr; /* buffer currently DMA'ed該DMA通道緩沖區鏈表中的當前緩沖區*/ unsigned long queue_count; /* number of buffers in the queue 鏈表中緩沖區個數*/ int active; /* 1 if DMA is actually processing data 該通道是否已經在使用*/ dma_regs_t *regs; /* points to appropriate DMA registers 該通道使用的DMA控制寄存器*/ int irq; /* IRQ used by the channel //通道申請的中斷號*/ dma_device_t write; /* to write //執行讀操作的DMA設備*/ dma_device_t read; /* to read 執行寫操作的DMA設備*/ } s3c2410_dma_t;
DMA驅動主要函數功能分析:
寫一個DMA驅動的主要工作包括:DMA通道申請、DMA中斷申請、控制寄存器設置、掛入DMA等待隊列、清除DMA中斷、釋放DMA通道.
int s3c2410_request_dma(const char *device_id, dmach_t channel, dma_callback_t write_cb, dma_callback_t read_cb) (s3c2410_dma_queue_buffer);
函數描述:申請某通道的DMA資源,填充s3c2410_dma_t 數據結構的內容,申請DMA中斷。
輸入參數:device_id DMA 設備名;channel 通道號;
write_cb DMA寫操作完成的回調函數;read_cb DMA讀操作完成的回調函數
輸出參數:若channel通道已使用,出錯返回;否則,返回0
int s3c2410_dma_queue_buffer(dmach_t channel, void *buf_id, dma_addr_t data, int size, int write) (s3c2410_dma_stop);
函數描述:這是DMA操作最關鍵的函數,它完成了一系列動作:分配並初始化一個DMA內核緩沖區控制結構,並將它插入DMA等待隊列,設置DMA控制寄存器內容,等待DMA操作觸發
輸入參數: channel 通道號;buf_id,緩沖區標識
dma_addr_t data DMA數據緩沖區起始物理地址;size DMA數據緩沖區大小;write 是寫還是讀操作
輸出參數:操作成功,返回0;否則,返回錯誤號
int s3c2410_dma_stop(dmach_t channel)
函數描述:停止DMA操作。
int s3c2410_dma_flush_all(dmach_t channel)
函數描述:釋放DMA通道所申請的所有內存資源
void s3c2410_free_dma(dmach_t channel)
函數描述:釋放DMA通道
因為各函數功能強大,一個完整的DMA驅動程序中一般只需調用以上3個函數即可。可在驅動初始化中調用s3c2410_request_dma,開始DMA傳輸前調用s3c2410_dma_queue_buffer,釋放驅動模塊時調用s3c2410_free_dma。
版權所有,轉載請注明轉載地址:http://www.cnblogs.com/lihuidashen/p/4470678.html