<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > ARM的嵌入式Linux移植體驗之設備驅動(dòng)

ARM的嵌入式Linux移植體驗之設備驅動(dòng)

作者: 時(shí)間:2012-11-13 來(lái)源:網(wǎng)絡(luò ) 收藏
  設備驅動(dòng)程序是操作系統內核和機器硬件之間的接口,它為應用程序屏蔽硬件的細節,一般來(lái)說(shuō),Linux的設備驅動(dòng)程序需要完成如下功能:

  ·設備初始化、釋放;

  ·提供各類(lèi)設備服務(wù);

  ·負責內核和設備之間的數據交換;

  ·檢測和處理設備工作過(guò)程中出現的錯誤。

  Linux下的設備驅動(dòng)程序被組織為一組完成不同任務(wù)的函數的集合,通過(guò)這些函數使得Windows的設備操作猶如文件一般。在應用程序看來(lái),硬件設備只是一個(gè)設備文件,應用程序可以象操作普通文件一樣對硬件設備進(jìn)行操作,如open ()、close ()、read ()、write () 等。

  Linux主要將設備分為二類(lèi):字符設備和塊設備。字符設備是指設備發(fā)送和接收數據以字符的形式進(jìn)行;而塊設備則以整個(gè)數據緩沖區的形式進(jìn)行。在對字符設備發(fā)出讀/寫(xiě)請求時(shí),實(shí)際的硬件I/O一般就緊接著(zhù)發(fā)生了;而塊設備則不然,它利用一塊系統內存作緩沖區,當用戶(hù)進(jìn)程對設備請求能滿(mǎn)足用戶(hù)的要求,就返回請求的數據,如果不能,就調用請求函數來(lái)進(jìn)行實(shí)際的I/O操作。塊設備主要針對磁盤(pán)等慢速設備。

  1.內存分配

  由于Linux驅動(dòng)程序在內核中運行,因此在設備驅動(dòng)程序需要申請/釋放內存時(shí),不能使用用戶(hù)級的malloc/free函數,而需由內核級的函數kmalloc/kfree () 來(lái)實(shí)現,kmalloc()函數的原型為:

  void kmalloc (size_t size ,int priority);

  參數size為申請分配內存的字節數,kmalloc最多只能開(kāi)辟128k的內存;參數priority說(shuō)明若kmalloc()不能馬上分配內存時(shí)用戶(hù)進(jìn)程要采用的動(dòng)作:

GFP_KERNEL 表示等待,即等kmalloc()函數將一些內存安排到交換區來(lái)滿(mǎn)足你的內存需要,GFP_ATOMIC 表示不等待,如不能立即分配到內存則返回0 值;函數的返回值指向已分配內存的起始地址,出錯時(shí),返回0。

  kmalloc ()分配的內存需用kfree()函數來(lái)釋放,kfree ()被定義為:

# define kfree (n) kfree_s( (n) ,0)

  其中kfree_s () 函數原型為:

void kfree_s (void * ptr ,int size);

  參數ptr為kmalloc()返回的已分配內存的指針,size是要釋放內存的字節數,若為0 時(shí),由內核自動(dòng)確定內存的大小。

  2.中斷

  許多設備涉及到中斷操作,因此,在這樣的設備的驅動(dòng)程序中需要對硬件產(chǎn)生的中斷請求提供中斷服務(wù)程序。與注冊基本入口點(diǎn)一樣,驅動(dòng)程序也要請求內核將特定的中斷請求和中斷服務(wù)程序聯(lián)系在一起。在Linux中,用requeST_IRq()函數來(lái)實(shí)現請求:

int request_irq (unsigned int irq ,void( * handler) int ,unsigned lONg type ,char * name);

參數irq為要中斷請求號,參數handler為指向中斷服務(wù)程序的指針,參數type 用來(lái)確定是正常中斷還是快速中斷(正常中斷指中斷服務(wù)子程序返回后,內核可以執行調度程序來(lái)確定將運行哪一個(gè)進(jìn)程;而快速中斷是指中斷服務(wù)子程序返回后,立即執行被中斷程序,正常中斷type 取值為0 ,快速中斷type 取值為SA_INTERRUPT),參數nAME是設備驅動(dòng)程序的名稱(chēng)。

  4.塊設備驅動(dòng)

  塊設備驅動(dòng)程序的編寫(xiě)是一個(gè)浩繁的工程,其難度遠超過(guò)字符設備,上千行的代碼往往只能搞定一個(gè)簡(jiǎn)單的塊設備,而數十行代碼就可能搞定一個(gè)字符設備。因此,非得有相當的基本功才能完成此項工作。下面先給出一個(gè)實(shí)例,即mtdblock塊設備的驅動(dòng)。我們通過(guò)分析此實(shí)例中的代碼來(lái)說(shuō)明塊設備驅動(dòng)程序的寫(xiě)法(由于篇幅的關(guān)系,大量的代碼被省略,只保留了必要的主干):

#include Linux/config.h>
#include Linux/devfs_fs_kernel.h>
staTIc void mtd_notify_add(struct mtd_info* mtd);
static void mtd_notify_remove(struct mtd_info* mtd);
static struct mtd_notifier notifier = {
 mtd_notify_add,
 mtd_notify_remove,
 NULL
};
static devfs_handle_t devfs_dir_handle = NULL;
static devfs_handle_t devfs_rw_handle[MAX_MTD_deviceS];

static struct mtdblk_dev {
 struct mtd_info *mtd; /* Locked */
 int count;
 struct semaphore cache_sem;
 unsigned char *cache_data;
 unsigned long cache_offset;
 unsigned int cache_size;
 enum { STATE_EMPTY, STATE_CLEAN, STATE_DIRTY } cache_state;
} *mtdblks[MAX_MTD_DEVICES];

static spinlock_t mtdblks_lock;
/* this lock is used just in kernels >= 2.5.x */
static spinlock_t mtdblock_lock;

static int mtd_sizes[MAX_MTD_DEVICES];
static int mtd_blksizes[MAX_MTD_DEVICES];

static void erase_callback(struct erase_info *done)
{
 wait_queue_head_t *wait_q = (wait_queue_head_t *)done->priv;
 wake_up(wait_q);
}

static int erase_write (struct mtd_info *mtd, unsigned long pos,
int len, const char *buf)
{
 struct erase_info erase;
 DECLARE_WAITQUEUE(wait, current);
 wait_queue_head_t wait_q;
 size_t retlen;
 int ret;

 /*
 * First, let's erase the flash block.
 */

 init_waitqueue_head(wait_q);
 erase.mtd = mtd;
 erase.callback = erase_callback;
 erase.addr = pos;
 erase.len = len;
 erase.priv = (u_long)wait_q;

 set_current_state(TASK_INTERRUPTIBLE);
 add_wait_queue(wait_q, wait);

 ret = MTD_ERASE(mtd, erase);
 if (ret) {
  set_current_state(TASK_RUNNING);
  remove_wait_queue(wait_q, wait);
  printk (KERN_WARNING "mtdblock: erase of region [0x%lx, 0x%x] " "on /"%s/" failed/n",
pos, len, mtd->name);
  return ret;
 }

 schedule(); /* Wait for erase to finish. */
 remove_wait_queue(wait_q, wait);

 /*
 * Next, writhe data to flash.
 */

 ret = MTD_WRITE (mtd, pos, len, retlen, buf);
 if (ret)
  return ret;
 if (retlen != len)
  return -EIO;
 return 0;
}

linux操作系統文章專(zhuān)題:linux操作系統詳解(linux不再難懂)

linux相關(guān)文章:linux教程



上一頁(yè) 1 2 3 下一頁(yè)

關(guān)鍵詞: ARM 嵌入式 Linux移植

評論


相關(guān)推薦

技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>