日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

【Linux笔记】LED驱动程序

發布時間:2023/12/20 linux 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Linux笔记】LED驱动程序 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

上一篇我們分享了字符設備驅動框架:【Linux筆記】驅動基礎篇,當時分享的是hello驅動程序。

學STM32我們從點燈開始,學Linux驅動我們自然也要點個燈來玩玩,盡量在從這些基礎例程中榨取知識,細摳、細摳,為之后更復雜的知識打好基礎。

與硬件無關的LED驅動

回顧hello驅動程序,我們的根據實際需求對其進行寫字符串與讀字符串操作。這里我們當然也要根據實際來思考我們的LED驅動程序。

在STM32點燈的時候,一般輸出低電平點燈,輸出高電平滅燈。在嵌入Linux操作系統的情況下,我們自然也要想到有個寫1/0的思想。

類比我們上一篇的hello程序:

我們的LED程序自然要寫入的數據為0/1來點亮、熄滅LED。

這里我們做的實驗室與硬件無關的LED實驗:我們的驅動程序在收到應用程序發送過來的0時打印led on、收到1時打印led off。

模仿上一篇的hello程序,我們修改得到的與硬件無關的LED程序(核心部分)如下:

LED應用程序:

LED驅動程序:

加載led驅動模塊及運行應用程序:

與硬件有關的LED驅動

上面那一節分享的是與硬件無關的LED驅動實驗,主要是為了理清LED驅動的大體思路。這里我們再加入與硬件有關的相關操作以構造與硬件有關的LED驅動程序。

我們在進行STM32的裸機編程的時候,對一些外設進行配置其實就是操作一些地址的過程,這些外設地址在芯片手冊中可以看到:

這是地址映射圖,這里圖中只是列出的外設的邊界地址,每個外設又有很多寄存器,這些寄存器的地址都是對外設基地址進行偏移得到的。

同樣的,對于NXP的IMX6ULL芯片來說,也是有類似這樣的地址的:

此時我們要編寫Linux系統下的led驅動,涉及到硬件操作的地方操作的并不是這些地址(物理地址),而是操作系統給我們提供的地址(虛擬地址)。

操作系統根據物理地址來給我們生成一個虛擬地址,我們的led驅動操控這個地址就是間接的操控物理地址。

至于這兩個地址是怎么聯系起來的,里面個原理我們暫且不展開。我們從函數層面來看,內核給我們提供了ioremap 函數,這個函數可以把物理地址映射為虛擬地址。

這個函數在內核文件arch/arm/include/asm/io.h ?中:

左右滑動查看全部代碼>>>

void __iomem *ioremap(resource_size_t res_cookie, size_t size);
  • res_cookie:要映射給的物理起始地址 。

  • size:要映射的內存空間大小。

  • 返回值:指向映射后的虛擬空間首地址。

與ioremap函數相對應的函數為:

void iounmap (volatile void __iomem *addr)
  • addr:要取消映射的虛擬地址空間首地址。

地址映射完成之后,我們可以直接通過指針來訪問虛擬地址,如:

*GPIO5_DR &= ~(1 << 3); /* GPIO5_IO03輸出低電平 */ *GPIO5_DR |= (1 << 3); /* GPIO5_IO03輸出高電平 */

這里簡單介紹一下i.MX 6ULL的GPIO。對于i.MX 6ULL來說,以數字來給IO端口(組別)命令,GPIO5為第五組,所以GPIO5_IO03為第五組端口的第3個引腳。

而STM32中是以大寫字母來表示端口(組別),如PA3表示A端口的第3個引腳。

i.MX 6ULL有 5 組 GPIO(GPIO1~ GPIO5),每組引腳最多有 32 個:

GPIO1 有 32 個引腳:GPIO1_IO0~GPIO1_IO31; GPIO2 有 22 個引腳:GPIO2_IO0~GPIO2_IO21; GPIO3 有 29 個引腳:GPIO3_IO0~GPIO3_IO28; GPIO4 有 29 個引腳:GPIO4_IO0~GPIO4_IO28; GPIO5 有 12 個引腳:GPIO5_IO0~GPIO5_IO11;

地址映射完成之后,我們不僅可以通過指針來訪問虛擬地址,而且還可以使用內核給我們提供的一些讀寫函數:

/* 寫操作函數 */ void writeb(u8 value, volatile void __iomem *addr); void writew(u16 value, volatile void __iomem *addr); void writel(u32 value, volatile void __iomem *addr); /* 讀操作函數 */ u8 readb(const volatile void __iomem *addr); u16 readw(const volatile void __iomem *addr); u32 readl(const volatile void __iomem *addr);

writeb、 writew 和 writel 這三個函數分別對應 8bit、 16bit 和 32bit 寫操作,參數 value 是要寫入的數值, addr 是要寫入的地址。

readb、 readw 和 readl 這三個函數分別對應 8bit、 16bit 和 32bit 讀操作,參數 addr 就是要讀取寫內存地址,返回值就是讀取到的數據。

此時我們可以把上一節的led_init函數led_drv_write函數進行修改:

與STM32一樣,對于i.MX 6ULL的GPIO外設來說,也有很多寄存器:

上面我們只是點一個燈,如果是要點多個燈呢?那就得操控多個GPIO。如果進行地址映射的寫法還像上面那樣,代碼就會顯得很臃腫。

回想一下我們STM32,GPIO外設通過結構體來管理它的寄存器:

這里的__IO是個宏,代表的是C語言的關鍵字volatile ,為了防止編譯器對我們的一些硬件操作進行優化,從而得不到想要的結果。比如:

/* 假設REG為寄存器的地址 */ uint32 *REG; *REG = 0;/* 點燈 */ *REG = 1;/* 滅燈 */

此時若是REG不加volatile進行修飾,則點燈操作將被優化掉,只執行滅燈操作。關于volatile關鍵字更多的解釋可以查看往期筆記:《來看一看volatile關鍵字》

在這里,我們也可以模仿STM32那樣子,用一個結構體來對i.MX 6ULL的GPIO的寄存器進行管理,如:

struct GPIO_RegDef {volatile unsigned int DR;volatile unsigned int GDIR;volatile unsigned int PSR;volatile unsigned int ICR1;volatile unsigned int ICR2;volatile unsigned int IMR;volatile unsigned int ISR;volatile unsigned int EDGE_SEL; };

結構體里的成員排序是要按照特定順序來的:

因為這些寄存器都是相對于GPIO外設的基地址作偏移得到的,比如:

不能打亂順序,否則就不能正確訪問到對應的寄存器了。用結構體進行管理之后,我們就可以用類似下面的方式進行映射:

struct GPIO_RegDef *GPIO5 = ioremap(0x20AC000, sizeof(struct GPIO_RegDef));

然后就可以向STM32那樣來操控GPIO寄存器,如:

GPIO5->DR &= ~(1 << 3); /* GPIO5_IO03輸出低電平 */ GPIO5->DR |= (1 << 3); /* GPIO5_IO03輸出高電平 */

LED驅動(升級版)

上一節我們分享的LED驅動是一個常規的LED驅動,只能適用于我們當前的開發版,所以是一個專用的LED驅動程序。

若是換了另一塊板,led所連接的gpio引腳可能不一樣了,我們就修改我們的驅動程序led_drv.c里與寄存器相關的操作。

有沒有更好的辦法不用再修改我們的led_drv.c驅動程序了?

若是led_drv.c不用再修改了,那么這個led_drv.c驅動就是一個通用的驅動程序了。具體可查看韋東山老師的《嵌入式Linux應用開發完全手冊第2版》第五篇第3~7節進行學習。

下面來簡單地梳理一下:

由于篇幅問題,具體的部分就不貼出來了。

之前的筆記中:《C語言、嵌入式重點知識:回調函數》中我們也有提到通用與專用的含義,可以了解了解加深對這兩個詞的認識。

這里我們學到了很重要的思想軟件分層的思想及技巧,但也只是點了一下,未來的路還很長,需要持續學習,繼續提高。

最后

以上就是本次的分享,如有錯誤,歡迎指出!謝謝

原創不易,如果覺得文章不錯,轉發、在看,也是我們繼續更新得動力。

參考/學習資料:

  • 百問網《嵌入式Linux應用開發完全手冊第2版》

  • 正點原子《I.MX6U嵌入式Linux驅動開發指南V1.2》

  • 野火《i.MX Linux開發實戰指南》

? 回復「?籃球的大肚子」進入技術群聊

回復「1024」獲取1000G學習資料

總結

以上是生活随笔為你收集整理的【Linux笔记】LED驱动程序的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。