前面的兩篇Linux驅動文章
【i.MX6ULL】驅動開發1--字符設備開發模板
【i.MX6ULL】驅動開發2--新字符設備開發模板
介紹了字符設備驅動的兩種新舊開發方式,并使用一個虛擬的字符驅動來學習字符設備的開發的流程。
本篇起,就要來操作Linux開發板的硬件,首先當然是通過經典的點亮LED燈程序,來學習Linux IO口操作的字符設備開發流程。
對比STM32的點燈程序,有寄存器操作與庫函數操作兩種,但其本質都是在配置寄存器。
同樣,i.MX6ULL也有多種點燈方式:
跑Linux系統:字符驅動LED點燈、設備樹驅動LED點燈
究其本質,最終都是要操作i.MX6ULL的寄存器。比如,在控制GPIO引腳實現LED亮滅時,會進行類似如下的寄存器配置:
/* 寄存器物理地址 */
#define CCM_CCGR1_BASE (0X020C406C)
#define SW_MUX_SNVS_TAMPER3_BASE (0X02290014)
#define SW_PAD_SNVS_TAMPER3_BASE (0X02290058)
#define GPIO5_DR_BASE (0X020AC000)
#define GPIO5_GDIR_BASE (0X020AC004)
那這些寄存器都是什么作用呢?這些地址是怎么確定的呢?
所以,在學習GPIO控制LED點燈之前,需要先了解清楚有關GPIO的寄存器配置。
既然是要操作硬件,首先就來看一下i.MX6ULL這個芯片的IO口基本信息。
1 認識Linux開發板的GPIO口
首先要明確:IO與GPIO是兩個概念,GPIO是屬于IO的一部分。
IO: Input Output,用于CPU與外界進行信息交互。例如CPU 讀內存數據需要 I/O 系統,CPU 輸出數據到屏幕顯示出來也需要 I/O 系統,信息在 I/O 系統上傳輸有串行或并行。
GPIO: General-Purpose IO ports,即通用I/O口,在微控制器芯片上一般都會提供一個“通用可編程I/O接口”。接口至少有兩個寄存器——數據寄存器與控制寄存器。數據寄存器的各位直接引到芯片外部,控制寄存器則是對數據寄存器中每一位進行獨立的設置。
1.1 板子LED硬件原理圖
在開始介紹i.MX6ULL的GPIO之前,先來看一下板子的原理中對于LED的標注。
我這塊板子(野火EBF6ULL S1 Pro)的原理圖中關于LED電路的部分,如下圖所示。
這里出現了兩種標注:SNVS_TAMPER3與GPIO5_IO03,先對這兩個名稱有個印象,下面就來介紹其含義。
另外,從原理圖可以看出,低電平時LED燈會亮起。

1.2 GPIO邏輯結構
下圖為i.MX6ULL的GPIO硬件結構框圖,其中①和⑤的PAD表示i.MX6ULL芯片引出的GPIO引腳,其余部件都位于芯片內部。
① PAD:它代表了i.MX6ULL芯片的一個GPIO引腳。
② IOMUX復用選擇器:與STM32的引腳復用功能類似,i.MX6ULL芯片的每個IO通過IOMUXC中的MUX寄存器和PAD寄存器設置,可以支持多種功能(如GPIO、IIC、USART...)。
③ Block外設功能控制塊:例如具有PWM輸出功能的引腳,它需要PWM外設的支持。
④ GPIO外設:GPIO模塊是每個IO都具有的外設, 它是IO控制的基本功能, 如輸出高低電平、 檢測電平輸入等。當需要使用引腳的GPIO功能時,就要配置GPIO外設中的各個寄存器(DR、GDIR、PSR...)。
⑤ 與其它引腳的連接:這里是另一個引腳PAD2,它與PAD1有一根信號線連接,表示部分引腳的輸出可以作為另一個引腳的輸入。

1.2.1 PAD配置
PAD代表示i.MX6ULL 的GPIO引腳。其左側是一系列信號通道及控制線:
input_on控制輸入開關
Dir 控制引腳的輸入輸出方向
Data_out 控制引腳輸出高低電平
Data_in 作為信號輸入
這些信號都經過一個IOMUX器件連接到左側的寄存器。

另外,對于每個引腳都有很多關于屬性的配置:

① PAD引腳
框圖最右側的PAD同樣是代表一個i.MX6ULL引腳。
② 輸出緩沖區(OBE,output buffer enable)
當輸出緩沖區使能時,引腳被配置為輸出模式。該模式又包含了如下的屬性配置:
DSE 驅動能力配置:通過調整芯片內部與引腳串聯電阻 R0 的大小,從而改變引腳的驅動能力。可以把R0的值配置為原值的1/2、1/3?1/7 等。
SRE 壓擺率配置:指電壓轉換速率,即電壓由波谷升到波峰的時間。增大壓擺率可減少輸出電壓的上升時間。
SPEED 帶寬配置:帶寬的意思是能通過這個IO口最高的信號頻率,可設置為50MHz、100MHz以及200MHz。
ODE 開漏輸出配置:開漏輸出模式常用在一些通訊總線中,如I2C。
③ 輸入緩沖區(IBE,input buffer enable)
當輸入緩沖區使能時,引腳被配置為輸入模式。該模式又包含了如下的屬性配置:
HYS 滯后使能:i.MX6ULL的輸入檢測可以使用普通的 CMOS 檢測或施密特觸發器模式(滯后模式)。
④ Pull/Keeper上下拉、保持器
引腳的控制中還包含了上下拉、保持器的功能。
PUS 上下拉配置:可選為100K歐下拉以及22K歐、47K歐及100K歐上拉。
PUE 上下拉、保持器選擇:上下拉功能和保持器功能是二選一的,可以通過PUE來選擇。
PKE 上下拉、保持器配置:上下拉功能和保持器還通過PKE來控制是否使能。
1.2.2 IOMUX復用選擇器
與STM32的引腳復用功能類似,i.MX6ULL芯片的每個GPIO通過IOMUX設置,可以支持多種功能。

IOMUX由其左側的IOMUXC提供寄存器給用戶進行配置,它又分成MUX_Mode(IO 模式控制)以及Pad Settings(Pad 配置)兩個部分:
① MUX_Mode配置:用來配置引腳的復用功能
② Pad Settings 配置:配置引腳的屬性,例如驅動能力,是否使用上下拉電阻,是否使用保持器,是否使用開漏模式以及使用施密特模式還是CMOS模式等
在IOMUXC外設中關于MUX_Mode和Pad Settings寄存器命名格式如下:
IOMUXC 控制類型 | 寄存器名稱 |
---|---|
MUX_Mode | IOMUXC_SW_MUX_CTL_PAD_XXXX |
Pad Settings | IOMUXC_SW_PAD_CTL_PAD_XXXX |
1.3 GPIO命名
1.3.1 按照GPIO分組
i.MX6ULL芯片的GPIO被分成 5 組, 并且每組GPIO的數量不盡相同,例如GPIO1有32個引腳,GPIO2有22個引腳等等:
GPIO組 | 引腳數 | 名稱 |
---|---|---|
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 |
具體可查閱數據手冊:

1.3.2 按照IO分組
此外,還有另一種命名方式,因為GPIO是屬于IO的一種,因此按照I.MX6ULL的IO分類,可以分為兩大類:SNVS域的IO和通用的IO,這兩類IO本質上是一樣的。
IO類別 | 命名類型 |
---|---|
SNVS域的IO | IOMUXC_SNVS_SW_MUX_CTL_PAD_XX_XX |
通用的IO | IOMUXC_SW_MUX_CTL_PAD_XX_XX |
SNVS域的IO: 命名形式為IOMUXC_SNVS_SW_MUX_CTL_PAD_XX_XX
XX_XX
可以是如: BOOT_MODE0、SNVS_TAMPER0、TEST_MODE等。

通用的IO: 命名形式為IOMUXC_SW_MUX_CTL_PAD_XX_XX
XX_XX
可以是如: GPIO1_IO01、UART1_TX_DATA、JTAG_MOD等。

所以,從IO名稱上,基本就可以看出該管腳的基本用途。
2 板子LED引腳配置

下面以 GPIO5_IO03引腳為例,也就是這次要控制的LED引腳,進行配置:
2.1 IO配置
2.1.1 配置MUX寄存器
從下圖可以看出,IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3的MUX寄存器,其地址為0X2290014H。
這個寄存器是32位的,但只用到了低5位,其中bit0~bit3(MUX_MODE)就是設置SNVS_TAMPER3的復用功能的。
SNVS_TAMPER3只能復用為 種功能 IO,即ALT5作為 GPIO5_IO03。

2.1.2 配置PAD寄存器
PAD 寄存器的配置項相對于MUX寄存器就更加豐富了。
從下圖可以看出,IOMUXC_SNVS_SW_PAD_CTL_PAD_SNVS_TAMPER3的PAD寄存器,其地址為0X2290058H。
這也是個32位寄存器,但是只用到了其中的低17位。

2.2 GPIO配置
上面的MUX和PAD這兩種寄存器都是配置IO的,當把IO配置為了GPIO功能后,還有繼續對GPIO外設的各種寄存器進行配置:

2.2.1 配置DR寄存器
DR(data register),即數據寄存器,它是32位的,一個GPIO組最大只有32個IO,因此DR寄存器中的每個位都對應一個 GPIO。
當GPIO被配置為輸出模式后,向指定的位寫入數據那么相應的IO就會輸出相應的高低電平,例如,要設置GPIO5_IO03輸出低電平,那么就應該設置 GPIO5.DR=0x08。
當 GPIO被配置為輸入模式后,此寄存器就保存著對應IO的電平值,每個位對對應一個GPIO,例如,當GPIO5_IO03這個引腳接地的話,那么 GPIO5.DR 的bit3就是0。

2.2.2 配置GDIR寄存器
GDIR(GPIO direction register),即方向寄存器,也是32位的,用來設置某個GPIO的工作方向的,即輸入/輸出。
同樣的,每個IO對應一個位,如果要設置GPIO為輸入,就設置相應的位為0,如果要設置為輸出,就設置為 1。
比如要設置 GPIO5_IO03 為輸出,那么 GPIO5.GDIR=0x00;

2.2.3 配置PSR寄存器
PSR(Pad Status Register),即狀態寄存器,也是32位的。
注意它是一個只讀寄存器,每個IO對應一個位,讀取相應的位即可獲取對應的GPIO的狀(高低電平值),功能和輸入狀態下的DR寄存器一樣。
這個寄存器使用ipg_clk_s時鐘,這意味著只有在訪問這個位時才對輸入信號進行采樣。所以,為了同步訪問這個寄存器都需要兩個等待狀態。

2.2.4 配置ICR1寄存器
ICR1(interrupt configuration register1)和ICR2,都是中斷控制寄存器, ICR1用于配置低16個GPIO,ICR2 用于配置高16 個GPIO。
ICR1寄存器中一個GPIO用兩個位,這兩個位用來配置中斷的觸發方式:
位設置 | 中斷觸發方式 |
---|---|
00 | 低電平觸發 |
01 | 高電平觸發 |
10 | 上升沿觸發 |
11 | 下降沿觸發 |
以GPIO1_IO15為例, 若要設置該引腳為上升沿觸發中斷, 需要配置為:GPIO1.ICR1=2<<30。

2.2.5 配置ICR2寄存器
ICR1和ICR2(interrupt configuration register2),都是中斷控制寄存器, ICR1用于配置低16個GPIO,ICR2 用于配置高16 個GPIO。
若要設置GPIO1的IO16~31的話就需要設置ICR2寄存器了,設置方式參考上面的ICR1。下面這個圖與ICR1類似,只截取部分顯示。

2.2.6 配置IMR寄存器
IMR(interrupt mask register),即中斷屏蔽寄存器,也是32位,每個IO對應一個位。
IMR寄存器用來控制GPIO的中斷禁止和使能,如果使能某個GPIO的中斷,那么設置相應的位為1即可,反之,如果要禁止中斷,那么就設 置相應的位為0即可。
例如,要使能GPIO1_IO00的中斷,需要配置為GPIO1.MIR=1。

2.2.7 配置ISR寄存器
ISR(interrupt status register),即中斷狀態寄存器,也是32位,每個IO對應一個位。
只要某個GPIO的中斷發生,則ISR中相應的位就會被置1。所以通過讀取ISR寄存器來判斷是否發生了中斷,類似于學習STM32用到的中斷標志位。
當中斷處理完以后,必須清除中斷標志位,清除方法就是向ISR中相應的位寫1,也就是寫1清零。
為了同步,讀訪問需要兩個等待狀態,復位需要一個等待狀態。

2.2.8 配置EDGE_SEL寄存器
EDGE_SEL(edge select register),即邊沿選擇寄存器,也是32位,每個IO對應一個位。
它用來設置邊沿中斷, 并會覆蓋ICR1和ICR2的設置。
如果相應的位被置1,則相當于設置了對應的GPIO是雙邊沿(上升沿和下降沿)觸發。例如,設置GPIO1.EDGE_SEL=1,則表示 GPIO1_IO01是雙邊沿觸發中斷,無論 GFPIO1_CR1的設置為多少。

2.3 GPIO各寄存器地址查詢表
上面介紹的有關GPIO的7種寄存器,為了方便查詢各個寄存器的地址,這里列出一張表:

2.4 時鐘配置
與ST32類似,I.MX6ULL每個外設都有一個外設時鐘,使用GPIO時,也必須先使能對應的時鐘。
2.4.1 配置CCM寄存器
CCM(Clock Controller Module)時鐘控制模塊寄存器用來使能外設時鐘。 CMM一共有CCM_CCGR0~CCM_CCGR6這 7 個寄存器,控制著I.MX6U的所有外設時鐘開關。
GPIOx | CCGRx(addr) | CGx |
---|---|---|
GPIO1_CLK_ENABLE | CCGR1(0X020C406C) | CG13 |
GPIO2_CLK_ENABLE | CCGR0(0X020C4068) | CG15 |
GPIO3_CLK_ENABLE | CCGR2(0X020C4070) | CG13 |
GPIO4_CLK_ENABLE | CCGR3(0X020C4074) | CG6 |
GPIO5_CLK_ENABLE | CCGR1(0X020C406C) | CG15 |
以CCM_CCGR0為例,它是個32位寄存器,每2位控制一個外設的時鐘,比如 bit31:30 控制著GPIO2 的外設時鐘,兩個位就有 4 種操作方式:
位設置 | 時鐘控制 |
---|---|
00 | 所有模式下都關閉外設時鐘 |
01 | 只有在運行模式下打開外設時鐘,等待模式和停止模式下均關閉外設時鐘 |
10 | 未使用(保留) |
11 | 除了停止模式以外,其他所有模式下時鐘都打開 |
若要打開GPIO2的外設時鐘,只需要設置CCM_CCGR0的bit31和bit30為1即可,即 CCM_CCGR0=3 << 30。

2.5 配置總結
使用i.MX6ULL的GPIO時,需要如下幾步配置:
使能 GPIO 對應的時鐘
配置MUX寄存器,設置IO的復用功能,使其復用為GPIO功能
配置PAD寄存器,設置 IO 的上下拉、速度等
配置GPIO的各種寄存器(DR、GDIR、...),設置輸入/輸出、是否使用中斷、默認輸出電平等
通過上面對各種寄存器的介紹,現在再來看本篇開頭提到的那幾個寄存器地址,如果理解了本篇的介紹,應該就知道這些地址大概的含義了:
/* 寄存器物理地址 */
#define CCM_CCGR1_BASE (0X020C406C)
#define SW_MUX_SNVS_TAMPER3_BASE (0X02290014)
#define SW_PAD_SNVS_TAMPER3_BASE (0X02290058)
#define GPIO5_DR_BASE (0X020AC000)
#define GPIO5_GDIR_BASE (0X020AC004)
3 總結
本篇主要介紹了i.MX6ULL有關GPIO的寄存器配置原理,本篇是i.MX6ULL操作硬件電路的基礎,了解了這些寄存器的配置原理,后續的LED輸出控制、按鍵輸入控制、IIC、SPI通信控制才能更加容易理解。
審核編輯:湯梓紅
-
寄存器
+關注
關注
31文章
5421瀏覽量
123290 -
Linux
+關注
關注
87文章
11456瀏覽量
212750 -
GPIO
+關注
關注
16文章
1270瀏覽量
53544
發布評論請先 登錄
飛凌嵌入式ElfBoard ELF 1板卡-uboot移植之IOMUX介紹
如何在i.MX6ULL睡眠時停止刷新LCD?
如何維護i.MX6ULL的安全內核?
如何在i.MX6ULL定制板上啟用IO Expander PCA6416A的控制?
嵌入式學習-飛凌嵌入式ElfBoard ELF 1板卡-Pinctrl和GPIO子系統之Pinctrl子系統
飛凌嵌入式ElfBoard ELF 1板卡-Pinctrl和GPIO子系統之Pinctrl子系統
嵌入式學習-飛凌嵌入式ElfBoard ELF 1板卡-開發板適配之USB_OTG
飛凌嵌入式ElfBoard ELF 1板卡-開發板適配之USB_OTG
ADS1298右腿驅動的寄存器應該如何配置?
【新品】i.MX6ULL工業嵌入式核心板!NXP低功耗MPU,LCD顯示

在NXP源碼基礎上如何適配ELF 1開發板的UART功能

使用TPS6521815 PMIC為NXP i.MX 6ULL、6UltraLite供電

PCA9554A具有中斷輸出和配置寄存器的遠程8位I2C和SMBus I/O擴展器數據表

評論