當前位置:首頁 > 公眾號精選 > 嵌入式案例Show
[導讀]學STM32我們從點燈開始,學Linux驅(qū)動我們自然也要點個燈來玩玩,盡量在從這些基礎例程中榨取知識,細摳、細摳,為之后更復雜的知識打好基礎。

01

前言

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

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

02

與硬件無關的LED驅(qū)動

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

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

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

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

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

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

LED應用程序:

LED驅(qū)動程序:

加載led驅(qū)動模塊及運行應用程序:

03

與硬件有關的LED驅(qū)動

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

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

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

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

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

操作系統(tǒng)根據(jù)物理地址來給我們生成一個虛擬地址,我們的led驅(qū)動操控這個地址就是間接的操控物理地址。

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

這個函數(shù)在內(nèi)核文件arch/arm/include/asm/io.h  中:

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

  • size:要映射的內(nèi)存空間大小。

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

與ioremap函數(shù)相對應的函數(shù)為:

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來說,以數(shù)字來給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;

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

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

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

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

此時我們可以把上一節(jié)的led_init函數(shù)led_drv_write函數(shù)進行修改:

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

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

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

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

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

此時若是REG不加volatile進行修飾,則點燈操作將被優(yōu)化掉,只執(zhí)行滅燈操作。

在這里,我們也可以模仿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輸出高電平 */ 

04

LED驅(qū)動(升級版)

上一節(jié)我們分享的LED驅(qū)動是一個常規(guī)的LED驅(qū)動,只能適用于我們當前的開發(fā)版,所以是一個專用的LED驅(qū)動程序。

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

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

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

下面來簡單地梳理一下:

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

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



免責聲明:本文內(nèi)容由21ic獲得授權后發(fā)布,版權歸原作者所有,本平臺僅提供信息存儲服務。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫毥谦F公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉型技術解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務中斷的風險,如企業(yè)系統(tǒng)復雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務連續(xù)性,提升韌性,成...

關鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關鍵字: 華為 12nm EDA 半導體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權最終是由生態(tài)的繁榮決定的。

關鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務引領增長 以科技創(chuàng)新為引領,提升企業(yè)核心競爭力 堅持高質(zhì)量發(fā)展策略,塑強核心競爭優(yōu)勢...

關鍵字: 通信 BSP 電信運營商 數(shù)字經(jīng)濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術學會聯(lián)合牽頭組建的NVI技術創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術創(chuàng)新聯(lián)...

關鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關鍵字: BSP 信息技術
關閉
關閉