最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

【i.MX6ULL】驅(qū)動開發(fā)4——點亮LED(寄存器版)

2021-10-07 00:09 作者:碼農(nóng)愛學(xué)習(xí)-B站  | 我要投稿

上篇文章(【i.MX6ULL】驅(qū)動開發(fā)3--GPIO寄存器配置原理),介紹了i.MX6ULL芯片的GPIO的工作原理與寄存器配置。

本篇,就要來實際操作一下GPIO,實現(xiàn)板子上LED燈的亮滅控制。


在介紹如何通過寄存器來控制LED之前,需要先來了解一下有關(guān)Linux地址映射相關(guān)的知識。

1 地址映射

Linux或是STM32,對于硬件的控制,本質(zhì)都是操作寄存器,在對應(yīng)的地址進行數(shù)據(jù)的讀寫。若是在裸機開發(fā)中,可以控制CPU直接操作寄存器的地址,實現(xiàn)相應(yīng)的功能,其過程是這樣的:

linux環(huán)境,一般是不會直接訪問物理內(nèi)存,因為如果用戶不小心修改了內(nèi)存中的數(shù)據(jù),很有可能造成錯誤甚至系統(tǒng)崩潰。為了避免這些問題,linux內(nèi)核便引入了MMU和TLB進行內(nèi)存地址映射,通過訪問虛擬地址實現(xiàn)對實際物理地址的讀寫:

1.1 MMU介紹

MMU,Memory Manage Unit,即內(nèi)存管理單元,它提供統(tǒng)一的內(nèi)存空間抽象,程序通過訪問虛擬內(nèi)存中的地址,MMU將虛擬地址(Virtual Address)翻譯成實際的物理地址(Physical Address) ,之后CPU即可操作實際的物理地址。

MMU具有如下功能:

  • 保護內(nèi)存: MMU給一些指定的內(nèi)存塊設(shè)置了讀、寫以及可執(zhí)行的權(quán)限,這些權(quán)限存儲在頁表當中,MMU會檢查CPU當前所處的是特權(quán)模式還是用戶模式,只有和操作系統(tǒng)所設(shè)置的權(quán)限匹配才可以訪問。

  • 提供方便統(tǒng)一的內(nèi)存空間抽象,實現(xiàn)虛擬地址到物理地址的轉(zhuǎn)換:CPU可以運行在虛擬的內(nèi)存當中,虛擬內(nèi)存一般要比實際的物理內(nèi)存大很多,使得CPU可以運行比較大的應(yīng)用程序。

1.2 TLB介紹

TLB,Translation Lookaside Buffer,即轉(zhuǎn)譯后備緩沖器,也稱頁表緩存,里面存放的是一些頁表文件(虛擬地址到物理地址的轉(zhuǎn)換表),又稱為快表技術(shù)。

當CPU第一次查找一個虛擬地址時,硬件通過3級頁表(page table)得到最終的PPN(Physical Page Number),TLB會保存虛擬地址到物理地址的映射關(guān)系。這樣在下一次訪問同一個虛擬地址時,處理器通過查看TLB來直接返回物理地址,而不需要通過page table得到結(jié)果,從而提高地址轉(zhuǎn)換的效率。

1.3 I/O映射函數(shù)

Linux內(nèi)核啟動的時候會初始化MMU,設(shè)置好內(nèi)存映射,設(shè)置好以后CPU訪問的都是虛擬地址。

那在程序編寫的時候,如何進行物理內(nèi)存和虛擬內(nèi)存之間的轉(zhuǎn)換呢?這就需要用到兩個函數(shù):ioremap和iounmap。

ioremap()

ioremap函數(shù)用將物理地址映射為虛擬地址。

iounmap()

iounmap函數(shù)的作用是釋放掉ioremap函數(shù)所做的映射,即反向操作,在卸載驅(qū)動的時候需要調(diào)用。

1.4 I/O內(nèi)存訪問函數(shù)

在使用ioremap函數(shù)將物理地址轉(zhuǎn)換成虛擬地址之后,理論上我們便可以直接讀寫 I/O 內(nèi)存,但是為了符合驅(qū)動的跨平臺以及可移植性,我們應(yīng)該使用 linux 中指定的函數(shù)(如:iowrite8()、iowrite16()、iowrite32()、ioread8()、ioread16()、ioread32() 等)去讀寫 I/O 內(nèi)存,而非直接通過映射后的指向虛擬地址的指針進行訪問。讀寫 I/O 內(nèi)存的函數(shù)如下:

對于讀I/O而言,他們都只有一個 __iomem 類型指針的參數(shù),指向被映射后的地址,返回值為讀取到的數(shù)據(jù);

對于寫I/O而言他們都有兩個參數(shù),第一個為要寫入的數(shù)據(jù),第二個參數(shù)為要寫入的地址,返回值為空。

與這些函數(shù)相似的還有writeb、writew、writel、readb、readw、readl 等

在 ARM 架構(gòu)下,writex(readx)函數(shù)與 iowritex(ioreadx)有一些區(qū)別,writex(readx)不進行端序的檢查,而 iowritex(ioreadx)會進行端序的檢查。

2 程序編寫

2.1 LED驅(qū)動程序

led驅(qū)動也是屬于字符設(shè)備驅(qū)動的,之前介紹了新舊兩種字符驅(qū)動的寫法,本篇led驅(qū)動就按照新字符設(shè)置驅(qū)動的寫法來編寫。

關(guān)于新字符設(shè)備的驅(qū)動模塊,可參考之前的文章:【i.MX6ULL】驅(qū)動開發(fā)2--新字符設(shè)備開發(fā)模板

這里再放一張新字符設(shè)備開發(fā)的模板框架

2.1.1 字符設(shè)備的基本框架

2.1.2 具體完善

1)GPIO寄存器宏定義

需要配置相關(guān)的寄存器,就要對照著LED這個GPIO的硬件按需配置。

有關(guān)GPIO的各種寄存器的使用原理介紹,請參考上篇文章的介紹。

  • CCM 是用來進行時鐘的使能,其寄存器包括CCGR0~CCGR6,因為LED用到GPIO屬于GPIO5,它對應(yīng)的時鐘配置寄存器就是CCM_CCGR1

  • MUX 是用來將IO復(fù)用為GPIO

  • PAD 是用來配置IO的基本參數(shù)(驅(qū)動能力、壓擺率、上下拉等)

  • GPIO5_DR 數(shù)據(jù)寄存器,當GPIO為輸出模式時,用來設(shè)置對應(yīng)的高低電平

  • GPIO5_GDIR 方向寄存器,用來設(shè)置輸入還是輸出

以上是先對這些需要使用的寄存器的地址聲明宏定義(這些寄存器的地址可通過查閱i.MX6ULL數(shù)據(jù)手冊得到),然后再聲明對應(yīng)的虛擬地址的指針,因為Linux開始MMU后,就不能直接對寄存器的地址直接操作了,需要使用映射后的虛擬地址。

2)GPIO硬件初始化

主要包括以下幾步:

  • 寄存器地址映射:將需要用的寄存器的物理地址映射為虛擬地址

  • 使能GPIO1時鐘:就是配置CCM_CCGR1寄存器

  • 設(shè)置GPIO5_IO03的復(fù)用功能:配置MUX和PAD寄存器

  • 設(shè)置GPIO5_IO03為輸出功能:配置GPIO5_GDIR方向寄存器

  • 初始默認關(guān)閉LED:配置GPIO5_DR數(shù)據(jù)寄存器

具體配置過程如下,主要這里使用"與"和"或"的位運算操作,來配置寄存器中對應(yīng)位的值。


3)字符設(shè)備初始化

需要定義led字符設(shè)備結(jié)構(gòu)體,來管理這個led設(shè)備。

具體的led字符設(shè)備初始化流程:

  • 初始化LED的GPIO(上面剛介紹)

  • 創(chuàng)建設(shè)備號

  • 初始化cdev字符設(shè)備

  • 添加cdev字符設(shè)備

  • 創(chuàng)建類

  • 創(chuàng)建設(shè)備

4)LED亮滅控制

驅(qū)動程序中,對于LED的控制,可以分為兩步。

第一步是接收和解析應(yīng)用層發(fā)來的控制數(shù)據(jù)(0或1來控制亮滅),將控制參數(shù)傳遞給具體的開關(guān)led的函數(shù):

第二步就是根據(jù)指令參數(shù),通過控制數(shù)據(jù)寄存器GPIO5_DR來實現(xiàn)GPIO的高低電平輸出,從而實現(xiàn)LED的亮滅:

5)驅(qū)動退出

驅(qū)動不再使用時,需要注銷相關(guān)的設(shè)備:

首先釋放掉這些地址映射:

具體的注銷過程:

驅(qū)動程序基本就是這些,完整的程序見我的gitee倉庫:https://gitee.com/xxpcb/imx6ull

2.2 LED應(yīng)用程序

寫完了驅(qū)動程序(BSP),還要寫對應(yīng)的應(yīng)用程序(APP)。

目前的應(yīng)用程序比較簡短,因為在Linux中,一切皆文件,所以,對于LED的控制,就是通過向文件中寫入0或1來實現(xiàn)LED的亮滅。

先來對0和1進行宏定義:

然后就是main函數(shù)了:

3 實驗測試

3.1 程序編譯與下載

再來復(fù)習(xí)一下基本步驟:

  • ubuntu中通過gcc交叉編譯器編譯出led的驅(qū)動程序和應(yīng)用程序

  • 搭建局域網(wǎng)環(huán)境(電腦和linux板子連接到同一個路由器下,Linux板子以及燒錄了鏡像文件,能夠正常運行)

  • 通過tftp服務(wù)將兩個文件發(fā)送到linux板子的對應(yīng)目錄中(/lib/modules/4.1.15目錄)

  • 進行字符設(shè)備的加載,以及文件讀寫測試(控制led亮滅)

程序的具體編譯過程與之前的類似,這里不再贅述,可參考之前的文章(如這篇:【i.MX6ULL】驅(qū)動開發(fā)2--新字符設(shè)備開發(fā)模板

3.2 實驗現(xiàn)象

首先來看一下板子上LED的位置,如下圖的電路上的標號D14處:

然后在串口中,按照之前介紹字符設(shè)備的加載流程,先加載led字符設(shè)備,然后就可以下向應(yīng)用程序?qū)?或0來控制led的亮滅了。

led點亮的效果如下:

4 總結(jié)

本篇主要介紹了如何通過操作寄存器來點亮i.MX6ULL開發(fā)板上的led,通過編寫LED對應(yīng)的驅(qū)動程序和應(yīng)用程序,實現(xiàn)程序設(shè)計的分層。

因為Linux使用了MMU進行虛擬地址管理,因此在操作寄存器時,要進行地址映射后再操作。最后通過程序的實際測試,驗證了led的亮滅功能。

本篇的完整程序見我的gitee倉庫:https://gitee.com/xxpcb/imx6ull?



【i.MX6ULL】驅(qū)動開發(fā)4——點亮LED(寄存器版)的評論 (共 條)

分享到微博請遵守國家法律
宁德市| 赤城县| 黄浦区| 厦门市| 裕民县| 七台河市| 珠海市| 色达县| 鄯善县| 怀远县| 夹江县| 克拉玛依市| 根河市| 古田县| 甘孜县| 禄劝| 交城县| 靖宇县| 博爱县| 大英县| 贵阳市| 华坪县| 璧山县| 防城港市| 宁南县| 南江县| 雷山县| 金堂县| 大英县| 麻栗坡县| 台中县| 类乌齐县| 三亚市| 南昌市| 吉安县| 阿城市| 额敏县| 辰溪县| 阿拉善左旗| 仪征市| 木里|