国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【IMX6ULL驅(qū)動開發(fā)學習】04.應用程序和驅(qū)動程序數(shù)據(jù)傳輸和交互的4種方式:非阻塞、阻塞、POLL、異步通知

這篇具有很好參考價值的文章主要介紹了【IMX6ULL驅(qū)動開發(fā)學習】04.應用程序和驅(qū)動程序數(shù)據(jù)傳輸和交互的4種方式:非阻塞、阻塞、POLL、異步通知。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

目錄

一、數(shù)據(jù)傳輸

1.1 APP和驅(qū)動?

1.2 驅(qū)動和硬件

二、APP使用驅(qū)動的4種方式

2.1 非阻塞(查詢)

2.2 阻塞(休眠+喚醒)

2.3 POLL(休眠+喚醒+超時時間)

2.3.1?POLL機制流程

2.3.2?POLL執(zhí)行流程

2.3.3?POLL應用和驅(qū)動編程?

2.4 異步通知

2.4.1 異步通知流程

2.4.1 異步通知應用和驅(qū)動編程


一、數(shù)據(jù)傳輸

【IMX6ULL驅(qū)動開發(fā)學習】04.應用程序和驅(qū)動程序數(shù)據(jù)傳輸和交互的4種方式:非阻塞、阻塞、POLL、異步通知,Linux驅(qū)動開發(fā),linux,驅(qū)動開發(fā),交互

1.1 APP和驅(qū)動?

APP和驅(qū)動之間的數(shù)據(jù)訪問是不能通過直接訪問對方的內(nèi)存地址來操作的,這里涉及Linux系統(tǒng)中的MMU(內(nèi)存管理單元)。在驅(qū)動程序中通過這兩個函數(shù)來獲得APP和傳給APP數(shù)據(jù):

  • copy_to_user
  • copy_from_user

簡單來講,應用程序與內(nèi)核/驅(qū)動程序在物理空間上是隔離開的,應用程序和驅(qū)動程序是不可能互相訪問到的。驅(qū)動程序里的copy_from_user得到應用層傳來的數(shù)據(jù),驅(qū)動程序可以使用copy_to_user把數(shù)據(jù)發(fā)給應用程序,即應用程序和驅(qū)動程序通過這兩個函數(shù)交換數(shù)據(jù)。

1.2 驅(qū)動和硬件

  • 各個子系統(tǒng)函數(shù)
  • 通過ioremap映射寄存器地址后,直接訪問寄存器

驅(qū)動程序操作硬件可以通過子系統(tǒng)的方式(調(diào)用函數(shù))來操作硬件;或者用最原始的辦法ioremap,映射寄存器的地址(不是直接操作寄存器地址),這樣在驅(qū)動程序里就可以訪問寄存器了。

二、APP使用驅(qū)動的4種方式

驅(qū)動程序:提供能力,不提供策略(驅(qū)動程序提供各種作用的函數(shù),供應用程序抉擇并使用)。

2.1 非阻塞(查詢)

如果在應用程序里open這個argv[1](設備節(jié)點)時,指定了非阻塞,表示讀數(shù)據(jù)時,如果沒有數(shù)據(jù)并且這個文件的flag是非阻塞,則立刻返回一個錯誤。APP指定了非阻塞方式,驅(qū)動程序是否判斷它的flag完全由用戶決定。

//應用程序
//O_RDWR可讀可寫,O_NONBLOCK非阻塞方式
fd = open(argv[1], O_RDWR | O_NONBLOCK);
//驅(qū)動程序的read
static ssize_t gpio_drv_read (struct file *file, char __user *buf, size_t size, loff_t *offset)
{
	int err;
	int key;

	if (is_key_buf_empty() && (file->f_flags & O_NONBLOCK))
		return -EAGAIN;
	
	wait_event_interruptible(gpio_wait, !is_key_buf_empty());
	key = get_key();
	err = copy_to_user(buf, &key, 4);	
	return 4;
}

2.2 阻塞(休眠+喚醒)

如果一開始buf里沒有數(shù)據(jù),APP調(diào)用讀函數(shù),驅(qū)動程序讀函數(shù)會進入wait_event_interruptible里休眠(放棄運行,不是死等),等待被喚醒。所以我們經(jīng)??吹絩ead函數(shù)很久沒有返回,是因為在驅(qū)動程序里休眠了。該事件會記錄在gpio_wait隊列中。

//應用程序
//O_RDWR可讀可寫,不設置非阻塞
fd = open(argv[1], O_RDWR);
//驅(qū)動程序的read
static ssize_t gpio_drv_read (struct file *file, char __user *buf, size_t size, loff_t *offset)
{
	int err;
	int key;

	if (is_key_buf_empty() && (file->f_flags & O_NONBLOCK))
		return -EAGAIN;
	
	wait_event_interruptible(gpio_wait, !is_key_buf_empty());
	key = get_key();
	err = copy_to_user(buf, &key, 4);	
	return 4;
}

通常配合中斷+定時器的方式來喚醒該隊列里面等待喚醒的進程/線程。

//中斷函數(shù)
static irqreturn_t gpio_key_isr(int irq, void *dev_id)
{
	struct gpio_desc *gpio_desc = dev_id;
	printk("gpio_key_isr key %d irq happened\n", gpio_desc->gpio);
	//定時器 用來消除抖動
    //修改定時器的超時時間= jiffies(當前時間) + 赫茲/5
	mod_timer(&gpio_desc->key_timer, jiffies + HZ/5);
	return IRQ_HANDLED;//成功處理
}
//定時器超時函數(shù)
static void key_timer_expire(unsigned long data)
{
	struct gpio_desc *gpio_desc = (struct gpio_desc *)data;
	int val;
	int key;

	val = gpio_get_value(gpio_desc->gpio);
    key = (gpio_desc->key) | (val<<8);
	put_key(key);//按鍵值放入環(huán)形緩沖區(qū)
    
    //喚醒隊列中的進程/線程
	wake_up_interruptible(&gpio_wait);
	kill_fasync(&button_fasync, SIGIO, POLL_IN);
}

2.3 POLL(休眠+喚醒+超時時間)

2.3.1?POLL機制流程

使用休眠-喚醒的方式等待某個事件發(fā)生時,有一個缺點: 等待的時間可能很久。我們可以加上一個超時時間,這時就可以使用 poll 機制。poll機制流程如下6步:

①APP不知道驅(qū)動程序中是否有數(shù)據(jù),可以先調(diào)用poll函數(shù)查詢一下,poll函數(shù)可以傳入超時時間;

②APP進入內(nèi)核態(tài),調(diào)用到驅(qū)動程序的poll函數(shù),如果有數(shù)據(jù)的話立刻返回;

③如果發(fā)現(xiàn)沒有數(shù)據(jù)時就休眠一段時間;

④當有數(shù)據(jù)時,比如當按下按鍵時,驅(qū)動程序的中斷服務程序和定時器超時函數(shù)被調(diào)用,它會記錄數(shù)據(jù)、喚醒APP;

⑤當超時時間到了之后,內(nèi)核也會喚醒APP;

⑥APP根據(jù)poll函數(shù)的返回值就可以知道是否有數(shù)據(jù),如果有數(shù)據(jù)就調(diào)用read得到數(shù)據(jù)。

2.3.2?POLL執(zhí)行流程

【IMX6ULL驅(qū)動開發(fā)學習】04.應用程序和驅(qū)動程序數(shù)據(jù)傳輸和交互的4種方式:非阻塞、阻塞、POLL、異步通知,Linux驅(qū)動開發(fā),linux,驅(qū)動開發(fā),交互

?????????????????????????????????????????????????????????????????圖1 poll機制

函數(shù)執(zhí)行流程如上圖①~⑧所示,重點從③開始看。假設一開始無按鍵數(shù)據(jù):

③APP調(diào)用poll之后,進入內(nèi)核態(tài);

④在循環(huán)中執(zhí)行程序,致驅(qū)動程序的drv_poll被調(diào)用;注意,drv_poll要把自己這個線程掛入等待隊列 wq 中!,并沒有休眠,且無數(shù)據(jù)返回0,有數(shù)據(jù)返回POLLIN;

⑤當前沒有數(shù)據(jù),則在內(nèi)核態(tài)中休眠一會,等待超時內(nèi)核喚醒中斷+定時器喚醒;

中斷+定時器喚醒情況:

⑥過程中,按下了按鍵,發(fā)生了中斷+定時器超時函數(shù),在定時器超時函數(shù)里記錄了按鍵值,并且從gpio_wait隊列中把線程喚醒了;

⑦從休眠中被喚醒,繼續(xù)執(zhí)行 for 循環(huán),再次調(diào)用 drv_poll,在drv_poll中返回數(shù)據(jù)狀態(tài)(POLLIN);

⑧有數(shù)據(jù)返回到內(nèi)核態(tài),內(nèi)核態(tài)返回到應用態(tài);

⑨APP調(diào)用read函數(shù)讀數(shù)據(jù)。


超時內(nèi)核喚醒情況:接著上面的⑤

⑥在休眠過程中,一直沒有按下了按鍵,超時時間到,內(nèi)核把這個線程喚醒;

⑦線程從休眠中被喚醒,繼續(xù)執(zhí)行 for 循環(huán),再次調(diào)用 drv_poll,drv_poll返回數(shù)據(jù)狀態(tài)

⑧還是沒有數(shù)據(jù),但是超時時間到了,那從內(nèi)核態(tài)返回到應用態(tài);

⑨APP不能調(diào)用 read 函數(shù)讀數(shù)據(jù)。

需要注意一下幾點?。?!

  • drv_poll 要把線程掛入隊列g(shù)pio_wait,但是并不是在 drv_poll 中進入休眠,而是在調(diào)用 drv_poll 之后休眠
  • drv_poll 要返回數(shù)據(jù)狀態(tài)
  • APP 調(diào)用一次 poll,有可能會導致 drv_poll 被調(diào)用 2 次
  • 線程被喚醒的原因有 2個:中斷(+定時器)發(fā)生了去隊列g(shù)pio_wait中把它喚醒,超時時間到了內(nèi)核把它喚醒
  • APP 要判斷 poll 返回的原因:有數(shù)據(jù),還是超時。有數(shù)據(jù)時再去調(diào)用read函數(shù)
2.3.3?POLL應用和驅(qū)動編程?

驅(qū)動程序中的poll代碼

static unsigned int gpio_drv_poll(struct file *fp, poll_table * wait)
{
	poll_wait(fp, &gpio_wait, wait);
	return is_key_buf_empty() ? 0 : POLLIN | POLLRDNORM;
}

?驅(qū)動程序中的中斷觸發(fā)函數(shù):按鍵消抖+修改了定時器超時時間

static irqreturn_t gpio_key_isr(int irq, void *dev_id)
{
	struct gpio_desc *gpio_desc = dev_id;
	printk("gpio_key_isr key %d irq happened\n", gpio_desc->gpio);
	//定時器 用來消除抖動
	mod_timer(&gpio_desc->key_timer, jiffies + HZ/5);//修改定時器的超時時間= jiffies(當前時間) + 赫茲/5
	return IRQ_HANDLED;//成功處理
}

?定時器超時函數(shù):獲取按鍵值+儲存按鍵值+喚醒線程

static void key_timer_expire(unsigned long data)
{
	struct gpio_desc *gpio_desc = (struct gpio_desc *)data;
	int val;
	int key;

	val = gpio_get_value(gpio_desc->gpio);
	key = (gpio_desc->key) | (val<<8);
	put_key(key);//按鍵值放入環(huán)形緩沖區(qū)
	wake_up_interruptible(&gpio_wait);//喚醒隊列里的線程
	kill_fasync(&button_fasync, SIGIO, POLL_IN);
}

應用程序代碼:

struct pollfd fds[1]
int timeout_ms = 5000;
int ret;
int fd;
fds[0].fd = fd;           //查詢fd這個文件
fds[0].events = POLLIN;   //POLLIN表示查詢這個文件有沒有數(shù)據(jù)讓我讀進來 

fd = open(argv[1], O_RDWR);
if(fd == -1)
{
    printf("can not open file %s\n", argv[1]);
}

while(1)
{
    ret = poll(fds, 1, timeout_ms);
    //ret為1表示fds結(jié)構(gòu)體中有文件滿足返回條件,且返回的事件是這個文件有數(shù)據(jù)讓我讀進來POLLIN
    if((ret == 1) && (fds[0].revents & POLLIN))
    {
        read(fd, &val, 4);
        printf("get button : 0x%x\n", val);
    }
    else
    {
        printf("timeout\n");
    }

}

2.4 異步通知

2.4.1 異步通知流程

使用休眠-喚醒、POLL機制時,都需要休眠等待某個事件發(fā)生時,它們的差別在于后者可以指定休眠的時長。如果APP不想休眠怎么辦?也有類似的方法:驅(qū)動程序有數(shù)據(jù)時主動通知APP,APP收到信號后執(zhí)行信息處理函數(shù),這就是異步通知。

【IMX6ULL驅(qū)動開發(fā)學習】04.應用程序和驅(qū)動程序數(shù)據(jù)傳輸和交互的4種方式:非阻塞、阻塞、POLL、異步通知,Linux驅(qū)動開發(fā),linux,驅(qū)動開發(fā),交互
圖2 異步通知的信號流程

重點從②開始:
② APP 給 SIGIO 這個信號注冊信號處理函數(shù) func,以后 APP 收到 SIGIO信號時,這個函數(shù)會被自動調(diào)用;
③ 把 APP 的 PID(進程 ID)告訴驅(qū)動程序,這個調(diào)用不涉及驅(qū)動程序,在內(nèi)核的文件系統(tǒng)層次記錄 PID;
④ 讀取驅(qū)動程序文件 Flag;
⑤ 設置 Flag 里面的 FASYNC 位為 1:當 FASYNC 位發(fā)生變化時,會導致驅(qū)動程序的 fasync 被調(diào)用;
⑥⑦ 調(diào) 用 faync_helper , 它會根據(jù)FAYSNC的值決定是否設置button_async->fa_file=驅(qū)動文件 filp:驅(qū)動文件 filp 結(jié)構(gòu)體里面含有之前設置的 PID。
⑧ APP 可以做其他事;
⑨⑩ 按下按鍵,發(fā)生中斷,驅(qū)動程序的中斷服務程序被調(diào)用,里面調(diào)用kill_fasync 發(fā)信號;
??? APP 收到信號后,它的信號處理函數(shù)被自動調(diào)用,可以在里面調(diào)用read 函數(shù)讀取按鍵。

2.4.1 異步通知應用和驅(qū)動編程

應用程序:信號處理函數(shù)+注冊信號處理函數(shù)+打開驅(qū)動+把進程ID告訴驅(qū)動+使能驅(qū)動的FASYNC功能

static void sig_func(int sig)
{
    int val;
    read(fd, &val, 4);
    printf("get button : 0x%x\n", val);
}

signal(SIGIO, sig_func);

fd = open(argv[1], O_RDWR);
if(fd == -1)
{
    printf("can not open file %s\n", argv[1]);
}

fcntl(fd, F_SETOWN, getpid());         //告訴驅(qū)動程序,要給誰發(fā)信號
flags = fcntl(fd, F_GETFL);            //獲得之前的flags
fcntl(fd, F_SETFL, flags | FASYNC);    //這是新的flags并使能驅(qū)動的FASYNC功能(使能異步通知)

驅(qū)動程序中的fasync被調(diào)用:使能異步通知后會調(diào)用這個輔助函數(shù)來構(gòu)造結(jié)構(gòu)體,結(jié)構(gòu)體里存放進程id

//構(gòu)造button_fasync結(jié)構(gòu)體,結(jié)構(gòu)體里存放進程id
static int gpio_drv_fasync(int fd, struct file *file, int on)
{
	if (fasync_helper(fd, file, on, &button_fasync) >= 0)
		return 0;
	else
		return -EIO;
}

?驅(qū)動程序中的中斷觸發(fā)函數(shù):按鍵消抖+修改了定時器超時時間

static irqreturn_t gpio_key_isr(int irq, void *dev_id)
{
	struct gpio_desc *gpio_desc = dev_id;
	printk("gpio_key_isr key %d irq happened\n", gpio_desc->gpio);
	//定時器 用來消除抖動
	mod_timer(&gpio_desc->key_timer, jiffies + HZ/5);//修改定時器的超時時間= jiffies(當前時間) + 赫茲/5
	return IRQ_HANDLED;//成功處理
}

?定時器超時函數(shù):最后一行發(fā)送信號SIGIO給進程,button_fasync結(jié)構(gòu)體中有進程信息,發(fā)送信號后,應用程序中收到信號會打斷while循環(huán)并先執(zhí)行對應的信號處理函數(shù),再回到while循環(huán)。文章來源地址http://www.zghlxwxcb.cn/news/detail-737858.html

static void key_timer_expire(unsigned long data)
{
	struct gpio_desc *gpio_desc = (struct gpio_desc *)data;
	int val;
	int key;

	val = gpio_get_value(gpio_desc->gpio);
	key = (gpio_desc->key) | (val<<8);
	put_key(key);//按鍵值放入環(huán)形緩沖區(qū)
	wake_up_interruptible(&gpio_wait);//喚醒隊列里的線程
	kill_fasync(&button_fasync, SIGIO, POLL_IN);
}

到了這里,關(guān)于【IMX6ULL驅(qū)動開發(fā)學習】04.應用程序和驅(qū)動程序數(shù)據(jù)傳輸和交互的4種方式:非阻塞、阻塞、POLL、異步通知的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關(guān)文章

  • 【IMX6ULL驅(qū)動開發(fā)學習】15.IMX6ULL驅(qū)動開發(fā)問題記錄(sleep被kill_fasync打斷)

    【IMX6ULL驅(qū)動開發(fā)學習】15.IMX6ULL驅(qū)動開發(fā)問題記錄(sleep被kill_fasync打斷)

    發(fā)現(xiàn)問題的契機: 學習異步通知的時候,自己實現(xiàn)一個功能:按鍵控制蜂鳴器,同時LED燈在閃爍 結(jié)果:LED好像也同時被按鍵控制了 最后調(diào)試結(jié)果發(fā)現(xiàn): 應用層的 sleep 被驅(qū)動層的 kill_fasync 打斷,所以sleep沒有執(zhí)行完就重新進入下一次循環(huán)了 修改代碼后解決該問題 解決邏輯就

    2024年02月13日
    瀏覽(18)
  • 【IMX6ULL驅(qū)動開發(fā)學習】08.IMX6ULL通過GPIO子系統(tǒng)函數(shù)點亮LED

    【IMX6ULL驅(qū)動開發(fā)學習】08.IMX6ULL通過GPIO子系統(tǒng)函數(shù)點亮LED

    通過GPIO子系統(tǒng)函數(shù)點亮LED 1、GPIO子系統(tǒng)函數(shù) 1.1 確定 led 的GPIO標號,查看內(nèi)核中的gpiochip 查看 gpiochip ,以正點原子的IMX6ULL阿爾法開發(fā)板為例 查看原理圖,發(fā)現(xiàn)led接的引腳是 GPIO1_IO3,對應 /sys/kernel/debug/gpio 中的 gpiochip0 組,gpiochip0 組從0開始算起, 所以 GPIO1_IO3 對應的標號就

    2024年02月10日
    瀏覽(25)
  • 【IMX6ULL驅(qū)動開發(fā)學習】03.設置IMX6ULL開發(fā)板與虛擬機在同一網(wǎng)段(設置開發(fā)板靜態(tài)IP)

    【IMX6ULL驅(qū)動開發(fā)學習】03.設置IMX6ULL開發(fā)板與虛擬機在同一網(wǎng)段(設置開發(fā)板靜態(tài)IP)

    為什么要設置IMX6ULL與虛擬機通信? 因為要把在虛擬機下編譯的文件傳到IMX6ULL開發(fā)板上運行 設置好同一網(wǎng)段,可以互ping后,可以參考這篇博客,實現(xiàn)開發(fā)板與虛擬機的文件互傳 IMX6ULL開發(fā)板與虛擬機互傳文件 一、設置windows有線網(wǎng)卡 二、配置虛擬機雙網(wǎng)卡(原本有一個NAT網(wǎng)卡

    2024年02月07日
    瀏覽(50)
  • 【IMX6ULL驅(qū)動開發(fā)學習】19.mmap內(nèi)存映射

    【IMX6ULL驅(qū)動開發(fā)學習】19.mmap內(nèi)存映射

    mmap將一個文件或者其它對象映射進內(nèi)存 ,使得應用層可以直接讀取到驅(qū)動層的數(shù)據(jù),無需通過copy_to_user函數(shù) 可以用于像LCD這樣的外設, 需要讀寫大量數(shù)據(jù)的 一、應用層 mmap用法: 用open系統(tǒng)調(diào)用打開文件, 并返回描述符fd. 用mmap建立內(nèi)存映射, 并返回映射首地址指針start. 對映

    2024年02月16日
    瀏覽(21)
  • 【IMX6ULL驅(qū)動開發(fā)學習】11.Linux之SPI驅(qū)動

    【IMX6ULL驅(qū)動開發(fā)學習】11.Linux之SPI驅(qū)動

    參考:驅(qū)動程序開發(fā):SPI設備驅(qū)動_spi驅(qū)動_鄧家文007的博客-CSDN博客 目錄 一、SPI驅(qū)動簡介 1.1 SPI架構(gòu)概述 1.2 SPI適配器(控制器)數(shù)據(jù)結(jié)構(gòu) 1.2 SPI設備數(shù)據(jù)結(jié)構(gòu) 1.3 SIP設備驅(qū)動 1.4 接口函數(shù) ?二、SPI驅(qū)動模板 SPI驅(qū)動框架和I2C驅(qū)動框架是十分相似的,不同的是因為SPI是通過片選引

    2024年02月11日
    瀏覽(32)
  • 【IMX6ULL驅(qū)動開發(fā)學習】12.Linux驅(qū)動之設備樹

    【IMX6ULL驅(qū)動開發(fā)學習】12.Linux驅(qū)動之設備樹

    承接上一篇博客 【IMX6ULL驅(qū)動開發(fā)學習】11.驅(qū)動設計之面向?qū)ο骭分層思想(學習設備樹過渡部分) 代碼獲?。?https://gitee.com/chenshao777/imx6-ull_-drivers 我后面將三個層合并了(實際上只有前兩層),合并成一個dev_drv.c了,暫時沒有加GPIO操作,只是個框架 合并前的代碼在 11.butt

    2024年02月13日
    瀏覽(48)
  • iMX6ULL驅(qū)動開發(fā) | 讓imx6ull開發(fā)板支持usb接口FC游戲手柄

    iMX6ULL驅(qū)動開發(fā) | 讓imx6ull開發(fā)板支持usb接口FC游戲手柄

    手邊有一閑置的linux開發(fā)板iMX6ULL一直在吃灰,不用來搞點事情,總覺得對不住它。業(yè)余打發(fā)時間就玩起來吧,總比刷某音強。從某多多上買來一個usb接口的游戲手柄,讓開發(fā)板支持以下它,后續(xù)就可以接著在上面玩童年經(jīng)典游戲啦。 ?我使用的是正點原子的I.MX6U-ALPHA 開發(fā)板,

    2024年02月14日
    瀏覽(39)
  • 【IMX6ULL驅(qū)動開發(fā)學習】12.Linux SPI驅(qū)動實戰(zhàn):DAC驅(qū)動設計流程

    【IMX6ULL驅(qū)動開發(fā)學習】12.Linux SPI驅(qū)動實戰(zhàn):DAC驅(qū)動設計流程

    基礎回顧:?【IMX6ULL驅(qū)動開發(fā)學習】10.Linux I2C驅(qū)動實戰(zhàn):AT24C02驅(qū)動設計流程_阿龍還在寫代碼的博客-CSDN博客 【IMX6ULL驅(qū)動開發(fā)學習】11.Linux之SPI驅(qū)動_阿龍還在寫代碼的博客-CSDN博客 查看芯片手冊,有兩種DAC數(shù)據(jù)格式,12位和16位,這里選用16位數(shù)據(jù)(2字節(jié))編寫驅(qū)動。 ?重點在

    2024年02月11日
    瀏覽(28)
  • 【IMX6ULL驅(qū)動開發(fā)學習】11.驅(qū)動設計之面向?qū)ο骭分層思想(學習設備樹過渡部分)

    【IMX6ULL驅(qū)動開發(fā)學習】11.驅(qū)動設計之面向?qū)ο骭分層思想(學習設備樹過渡部分)

    一個 可移植性好 的驅(qū)動程序,應該有三個部分組成 1、驅(qū)動框架程序(xxx_drv.c) — 對接應用層的 open read write 函數(shù),不做GPIO具體操作 2、硬件操作程序(xxx_chip_gpio.c)— 執(zhí)行具體的GPIO操作,初始化、讀寫 3、硬件資源定義程序(xxx_board.c,這在之后就過渡成了設備樹)— 為

    2024年02月11日
    瀏覽(25)
  • 【IMX6ULL驅(qū)動開發(fā)學習】14.Linux驅(qū)動開發(fā) - GPIO中斷(設備樹 + GPIO子系統(tǒng))

    【IMX6ULL驅(qū)動開發(fā)學習】14.Linux驅(qū)動開發(fā) - GPIO中斷(設備樹 + GPIO子系統(tǒng))

    代碼自取 【14.key_tree_pinctrl_gpios_interrupt】: https://gitee.com/chenshao777/imx6-ull_-drivers 主要接口函數(shù): 1. of_gpio_count (獲得GPIO的數(shù)量) 2. kzalloc (向內(nèi)核申請空間) 3. of_get_gpio (獲取GPIO子系統(tǒng)標號) 4. gpio_to_irq (根據(jù)GPIO子系統(tǒng)標號得到軟件中斷號) 5. request_irq (根據(jù)軟件中斷號

    2024年02月12日
    瀏覽(35)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包