久久ER99热精品一区二区-久久精品99国产精品日本-久久精品免费一区二区三区-久久综合九色综合欧美狠狠

新聞中心

EEPW首頁 > 嵌入式系統 > 設計應用 > ISA總線的DMA技術

ISA總線的DMA技術

作者: 時間:2011-05-20 來源:網絡 收藏
5.1 通道資源的申請與釋放

本文引用地址:http://cqxgywz.com/article/150725.htm

  同I/O端口資源類似,設備驅動程序必須在一開始就調用request_dma()函數來向內核申請通道資源的使用權。而且,最好在設備驅動程序的open()方法中完成這個操作,而不是在模塊的初始化例程中調用這個函數。因為這在一定程度上可以讓多個設備共享通道資源(只要多個設備不同時使用一個DMA通道)。這種共享有點類似于進程對CPU的分時共享。

  設備使用完DMA通道后,其驅動程序應該記得調用free_dma()函數來釋放所占用的DMA通道資源。通常,最好再驅動程序的release()方法中調用該函數,而不是在模塊的卸載例程中進行調用。

  還需要注意的一個問題是:資源的申請順序。為了避免死鎖(deadlock),驅動程序一定要在申請了中斷號資源后才申請DMA通道資源。釋放時則要先釋放DMA通道,然后再釋放中斷號資源。

  使用DMA的設備驅動程序的open()方法的如下:

  int xxx_open(struct inode * inode, struct file * filp)

  {

  ┆

  if((err = request_irq(irq,xxx_ISR,SA_INTERRUPT,”YourDeviceName”,NULL))

  return err;

  if((err = request_dma(dmanr, “YourDeviceName”)){

  free_irq(irq, NULL);

  return err;

  }

  ┆

  return 0;

  }

  release()方法的范例代碼如下:

  void xxx_release(struct inode * inode, struct file * filp)

  {

  ┆

  free_dma(dmanr);

  free_irq(irq,NULL);

  ┆

  }

  5.2 申請DMA緩沖區

  由于8237 DMAC只能尋址系統RAM中低16MB物理內存,因此:設備驅動程序在申請DMA緩沖區時,一定要以GFP_DMA標志來調用kmalloc()函數或get_free_pages()函數,以便在系統內存的DMA區中分配物理內存。

  5.3 編程DMAC

  設備驅動程序可以在他的read()方法、write()方法或ISR中對DMAC進行編程,以便準備啟動一個DMA傳輸事務。一個DMA傳輸事務有兩種典型的過程:(1)用戶請求設備進行DMA傳輸;(2)硬件異步地將外部數據寫道系統中。

  用戶通過I/O請求觸發設備進行DMA傳輸的步驟如下:

  1.用戶進程通過系統調用read()/write()來調用設備驅動程序的read()方法或write()方法,然后由設備驅動程序read/write方法負責申請DMA緩沖區,對DMAC進行編程,以準備啟動一個DMA傳輸事務,最后正確地設置設備(setup device),并將用戶進程投入睡眠。

  2.DMAC負責在DMA緩沖區和I/O外設之間進行數據傳輸,并在結束后觸發一個中斷。

  3.設備的ISR檢查DMA傳輸事務是否成功地結束,并將數據從DMA緩沖區中拷貝到驅動程序的其他內核緩沖區中(對于I/O device to memory的情況)。然后喚醒睡眠的用戶進程。

  硬件異步地將外部數據寫到系統中的步驟如下:

  1.外設觸發一個中斷通知系統有新數據到達。

  2.ISR申請一個DMA緩沖區,并對DMAC進行編程,以準備啟動一個DMA傳輸事務,最后正確地設置好外設。

  3.硬件將外部數據寫到DMA緩沖區中,DMA傳輸事務結束后,觸發一個中斷。

  4. ISR檢查DMA傳輸事務是否成功地結束,然后將DMA緩沖區中的數據拷貝驅動程序的其他內核緩沖區中,最后喚醒相關的等待進程。

  網卡就是上述過程的一個典型例子。

  為準備一個DMA傳輸事務而對DMAC進行編程的典型代碼段如下:

  unsigned long flags;

  flags = claim_dma_lock();

  disable_dma(dmanr);

  clear_dma_ff(dmanr);

  set_dma_mode(dmanr,mode);

  set_dma_addr(dmanr, virt_to_bus(buf));

  set_dma_count(dmanr, count);

  enable_dma(dmanr);

  release_dma_lock(flags);

  檢查一個DMA傳輸事務是否成功地結束的代碼段如下:

  int residue;

  unsigned long flags = claim_dma_lock();

  residue = get_dma_residue(dmanr);

  release_dma_lock(flags);

  ASSERT(residue == 0);


上一頁 1 2 3 4 下一頁

關鍵詞: 技術 DMA 總線 ISA

評論


相關推薦

技術專區

關閉