一、GPIO簡(jiǎn)介
i.MX6ULL 芯片的 GPIO 被分成 5 組,并且每組 GPIO 的數(shù)量不盡相同,例如 GPIO1 擁有 32 個(gè)引腳, GPIO2 擁有 22 個(gè)引腳, 其他 GPIO 分組的數(shù)量以及每個(gè) GPIO 的功能請(qǐng)參考 《i.MX 6UltraLite Applications Processor Reference Manual》 第26章General Purpose Input/Output (GPIO)(P1133)。
通過(guò) GPIO 硬件結(jié)構(gòu)框圖,就可以從整體上深入了解 GPIO 外設(shè)及它的各種應(yīng)用模式。
1.1 IO命名
打開 i.MX6ULL 參考手冊(cè)的第 32 章“Chapter 32: IOMUX Controller(IOMUXC)”

i.MX6ULL 的 IO 分為兩類:SNVS 域的和通用的,這兩類 IO 本質(zhì)上都是一樣的。
“IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO00”的就是 GPIO 命名,命名形式就是“IOMUXC_SW_MUC_CTL_PAD_XX_XX”,后面的“XX_XX”就是 GPIO 命名,比如:GPIO1_IO01、UART1_TX_DATA、JTAG_MOD 等等。他是 根據(jù)某個(gè) IO 所擁有的功能來(lái)命名的。比如我們一看到 GPIO1_IO01 就知道這個(gè)肯定能做 GPIO,看到 UART1_TX_DATA 肯定就知道這個(gè) IO 肯定能做為 UART1 的發(fā)送引腳。
IO 復(fù)用功能。 i.MX6ULL 除了 GPIO1_IO00~GPIO1_IO09 引腳外,其它 IO 也是可以復(fù)用為 GPIO 功能。同樣的,GPIO1_IO00~GPIO_IO09 也是可以復(fù)用為其它外設(shè)引腳。
1.2 IO復(fù)用
IOMUX 譯為 IO 復(fù)用選擇器。i.MX6ULL 的芯片每個(gè) GPIO 都通過(guò) IOMUX 支持多種功能, 例如一個(gè) IO 可用于網(wǎng)絡(luò)外設(shè) ENET 的數(shù)據(jù)接收引腳,也可以被配置成 PWM 外設(shè)的輸出引腳, 這樣的設(shè)計(jì)大大增加了芯片的適用性,這樣可選的功能就是由 IOMUX 實(shí)現(xiàn)的。IOMUX 相當(dāng)于增加了多根內(nèi)部信號(hào)線與 IO 引腳相連,
最多有 8 根,也就是說(shuō)一個(gè) IO 最多可支持 8 種可選的功能。
以“IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO00”這個(gè) IO 為例,打開參考手冊(cè)的 1568 頁(yè)。

可以看到有個(gè)名為:IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO00 的寄存器,寄存器地址為 0X020E005C,這個(gè)寄存器是 32 位的,但是只用到了最低 5 位,其中 bit0~bit3(MUX_MODE) 就是設(shè)置 GPIO1_IO00 的復(fù)用功能的。GPIO1_IO00 一共可以復(fù)用為 9 種功能 IO,分別對(duì)應(yīng) ALT0~ALT8,其中 ALT5 就是作為 GPIO1_IO00。GPIO1_IO00 還可以作為 I2C2_SCL、GPT1_CAPTURE1、ANATOP_OTG1_ID 等。
1.3 IO配置
IOMUX 由其左側(cè)的 IOMUXC 控制(C表示Controler),IOMUXC 提供寄存器給用戶進(jìn)行配置, 它又分成 MUX Mode(IO模式控制) 以及 Pad Settings(Pad配置) 兩個(gè)部分:
在 IOMUXC 外設(shè)中關(guān)于 MUX Mode 和 Pad Settings 寄存器命名格式如下:
| IOMUXC控制類型 | 寄存器名稱 |
|---|---|
| MUX Mode | IOMUXC_SW_MUX_CTL_PAD_XXXX |
| Pad Settings | IOMUXC_SW_PAD_CTL_PAD_XXXX |
每個(gè)引腳都包含這兩個(gè)寄存器,表中的XXXX表示引腳的名字
1.3.1 MUX Mode配置
MUX Mode 就是用來(lái)
配置引腳的復(fù)用功能,即選擇引腳具體是用于網(wǎng)絡(luò)外設(shè) ENET 的數(shù)據(jù)接收, 還是用于 PWM 外設(shè)的輸出引腳,當(dāng)然,也可以配置成普通的 IO 口,僅用于控制輸出高低電平。
以 GPIO1_IO04 引腳為例對(duì) MUX 寄存器進(jìn)行說(shuō)明,該引腳相應(yīng)的 MUX 寄存器在參考手冊(cè)中的描述如下:
該寄存器主要有兩個(gè)配置域,分別是 SION 和 MUX_MODE。
- SION: 用于設(shè)置引腳在輸出模式下同時(shí)開啟輸入通道。
-
MUX_MODE: 使用 4 個(gè)寄存器位表示可選的 ALT0~ALT7 這 8 個(gè)模式。
- 如 ALT2 模式就是用于 USB 外設(shè)的 USB_OTG1_PWR 信號(hào);
- 若配置為 ALT5 則引腳會(huì)用作普通的 GPIO 功能, 用于輸出高、低電平。

1.3.2 Pad Settings配置
Pad Settings 用于
配置引腳的屬性,例如驅(qū)動(dòng)能力,是否使用上下拉電阻, 是否使用保持器,是否使用開漏模式以及使用施密特模式還是CMOS模式等。
以 GPIO1_IO04 引腳中 PAD 寄存器在參考手冊(cè)中的描述如下:
相對(duì)來(lái)說(shuō) PAD 寄存器的配置項(xiàng)就更豐富了,而且圖中僅是該寄存器的部分說(shuō)明,如 HYS 設(shè)置使用施密特模式的滯后功能,PUS 配置上下拉電阻的阻值, 其它的還包含PUE、PKE、ODE、SPEED、DSE 及 SRE 的配置。

1.3.3 PAD(可跳過(guò)不看)
PAD 代表了一個(gè) i.MX6ULL 的 GPIO 引腳。在它的左側(cè)是一系列信號(hào)通道及控制線,如 input_on 控制輸入開關(guān),Dir 控制引腳的輸入輸出方向,Data_out 控制引腳輸出高低電平,Data_in 作為信號(hào)輸入,這些信號(hào)都經(jīng)過(guò)一個(gè) IOMUX 的器件連接到左側(cè)的寄存器。

①PAD引腳
代表一個(gè)i.MX6ULL的引腳。
②輸出緩沖區(qū)
當(dāng)輸出緩沖區(qū)使能時(shí),引腳被配置為輸出模式。在輸出緩沖區(qū)中,又包含了如下的屬性配置:
-
DSE驅(qū)動(dòng)能力
當(dāng)IO用作輸出的時(shí)候用來(lái)設(shè)置IO的驅(qū)動(dòng)能力。DSE可以調(diào)整芯片內(nèi)部與引腳串聯(lián)電阻R0的大小,從而改變引腳的驅(qū)動(dòng)能力。例如,R0的初始值為260歐姆,在3.3V電壓下其電流驅(qū)動(dòng)能力為12.69mA,通過(guò)DSE可以把R0的值配置為原值的1/2、1/3…1/7等。位設(shè)置 速度 000 輸出驅(qū)動(dòng)關(guān)閉 001 R0(3.3V 下 R0 是 260Ω,1.8V 下 R0 是 150Ω,接 DDR 的時(shí)候是 240Ω) 010 R0/2 011 R0/3 100 R0/4 101 R0/5 110 R0/6 111 R0/7 SRE壓擺率配置
設(shè)置壓擺率。壓擺率是指電壓轉(zhuǎn)換速率,可理解為電壓由波谷升到波峰的時(shí)間。增大壓擺率可減少輸出電壓的上升時(shí)間。i.MX6ULL的引腳通過(guò)SRE支持低速和高速壓擺率這兩種配置。當(dāng)此位為0的時(shí)候是低壓擺率,當(dāng)為1的時(shí)候是高壓擺率。壓擺率是大信號(hào)特性,下面的帶寬是小信號(hào)特性。-
SPEED帶寬配置
設(shè)置IO的帶寬。分別可設(shè)置為50MHz、100MHz以及200MHz。帶寬的意思是能通過(guò)這個(gè)IO口最高的信號(hào)頻率,通俗點(diǎn)講就是方波不失真,如果超過(guò)這個(gè)頻率方波就變正弦波。但是這個(gè)帶寬要區(qū)別于IO的翻轉(zhuǎn)速率,IO的翻轉(zhuǎn)速率的信號(hào)來(lái)自于GPIO這個(gè)外設(shè),而IO的帶寬只是限制了IO口引腳的物理特性,IO口的信號(hào)可以來(lái)自于內(nèi)部定時(shí)器輸出的PWM信號(hào),也可以來(lái)自于GPIO翻轉(zhuǎn)輸出的信號(hào),兩者相比之下,PWM信號(hào)的頻率是遠(yuǎn)遠(yuǎn)高于GPIO翻轉(zhuǎn)輸出的信號(hào)頻率。位設(shè)置 速度 00 低速 50M 01 中速 100M 10 中速 100M 11 最大速度 200M ODE開漏輸出配置
設(shè)置引腳是否工作在開漏輸出模式。在該模式時(shí)引腳可以輸出高阻態(tài)和低電平,此位為0的時(shí)候禁止開路輸出,當(dāng)此位為1的時(shí)候就使能開路輸出功能。輸出高阻態(tài)時(shí)可由外部上拉電阻拉至高電平。開漏輸出模式常用在一些通訊總線中,如I2C。
③輸入緩沖區(qū)
當(dāng)輸入緩沖區(qū)使能時(shí),引腳被配置為輸入模式。在輸入緩沖區(qū)中,又包含了如下的屬性配置:
- HYS滯后使能
用來(lái)使能遲滯比較器。i.MX6ULL的輸入檢測(cè)可以使用普通的CMOS檢測(cè)或施密特觸發(fā)器模式(滯后模式)。施密特觸發(fā)器具有滯后效應(yīng),對(duì)正向和負(fù)向變化的輸入信有不同的閾值電壓。如果需要對(duì)輸入波形進(jìn)行整形的話可以使能此位。此位為0的時(shí)候禁止遲滯比較器,為1的時(shí)候使能遲滯比較器。常被用于電子開關(guān)、波形變換等場(chǎng)合,其轉(zhuǎn)換特性和對(duì)比如下,如檢測(cè)按鍵時(shí),使用施密特模式即可起到消抖的功能。
④Pull/Keeper上下拉、保持器
引腳的控制邏輯中還包含了上下拉、保持器的功能。芯片內(nèi)部的上拉和下拉電阻可以將不確定的信號(hào)鉗位在高、低電平,或小幅提高的電流輸出能力,上拉提供輸出電流,下拉提供輸入電流。注意這些上下拉配置只是弱拉,對(duì)于類似I2C之類的總線,還是必須使用外部上拉電阻。i.MX6ULL芯片的電源模塊中包含轉(zhuǎn)換器,當(dāng)轉(zhuǎn)換器停止工作時(shí),保持器會(huì)保持輸入輸出電壓。
上下拉、保持器可以通過(guò)如下屬性配置:
- PUS上下拉配置
設(shè)置上下拉電阻。PUS可配置項(xiàng)可選為100K歐下拉以及22K歐、47K歐及100K歐上拉。位設(shè)置 含義 00 100K 下拉 01 47K 上拉 10 100K 上拉 11 22K 上拉 - PUE上下拉、保持器選擇
上下拉功能和保持器功能是二選一的,可以通過(guò)PUE來(lái)選擇。當(dāng)IO作為輸入的時(shí)候,這個(gè)位用來(lái)設(shè)置 IO 使用上下拉還是狀態(tài)保持器。當(dāng)為0的時(shí)候使用狀態(tài)保持器,當(dāng)為1的時(shí)候使用上下拉。狀態(tài)保持器在IO作為輸入的時(shí)候才有用,顧名思義,就是當(dāng)外部電路斷電以后此IO口可以保持住以前的狀態(tài)。 - PKE上下拉、保持器配置
用來(lái)使能或者禁止上下拉/狀態(tài)保持器功能。為0時(shí)禁止上下拉/狀態(tài)保持器,為1時(shí)使能上下拉和狀態(tài)保持器。
注意,當(dāng)引腳被配置為輸出模式時(shí),不管上下拉、保持器是什么配置,它們都會(huì)被關(guān)閉。
1.4 GPIO配置
GPIO 模塊是每個(gè) IO 都具有的外設(shè),它具有 IO 控制最基本的功能,如輸出高低電平、檢測(cè)電平輸入等。 它也占用 IOMUX 分配的復(fù)用信號(hào),也就是說(shuō)使用 GPIO 模塊功能時(shí)同樣需要使用 IOMUX 選中 GPIO 外設(shè),對(duì)其 GPIO 的功能進(jìn)行配置。
1.4.1 GDIR方向寄存器
設(shè)置某個(gè) IO 的工作方向。控制一個(gè) GPIO 引腳時(shí),要先用 GDIR 方向寄存器配置該引腳用于輸出電平信號(hào)還是用作輸入檢測(cè)。 典型的例子是使用輸出模式可以控制LED燈的亮滅,輸入模式時(shí)可以用來(lái)檢測(cè)按鍵是否按下。
GDIR 寄存器的每一個(gè)數(shù)據(jù)位代表一個(gè)引腳的方向,對(duì)應(yīng)的位被設(shè)置為0時(shí)該引腳為輸入模式,被設(shè)置為1時(shí)該引腳為輸出模式。
例如,對(duì) GPIO1 的 GDIR 寄存器的 bit3 位被寫入為 1,那么 GPIO1.3 引腳的模式即為輸出。

1.4.2 DR數(shù)據(jù)寄存器
DR 數(shù)據(jù)寄存器直接代表了引腳的電平狀態(tài),它也使用 1 個(gè)數(shù)據(jù)位表示 1 個(gè)引腳的電平,每位用 1 表示高電平,用 0 表示低電平。
當(dāng) GDIR 方向寄存器設(shè)置引腳為輸出模式時(shí),寫入 DR 數(shù)據(jù)寄存器對(duì)應(yīng)的位即可控制該引腳輸出的電平狀態(tài), 如這時(shí) GPIO1 的 DR 寄存器的 bit4 被寫入為 1,則引腳為輸出高電平。
當(dāng) GDIR 方向寄存器設(shè)置引腳為輸入模式時(shí),讀取 DR 數(shù)據(jù)寄存器對(duì)應(yīng)的位即可獲取該引腳當(dāng)前的輸入電平狀態(tài),例如這里讀取 GPIO1 的DR寄存器的 bit4,得到該位的值為 0,表示當(dāng)前引腳的輸入狀態(tài)為低電平。

1.4.3 PSR引腳狀態(tài)寄存器
讀取相應(yīng)的位即可獲取對(duì)應(yīng)的 GPIO 的狀態(tài),也就是 GPIO 的高低電平值。PSR 引腳狀態(tài)寄存器相當(dāng)于 DR 寄存器的簡(jiǎn)化版,它僅在 GDIR 方向寄存器設(shè)置為輸入模式時(shí)有效,它的每個(gè)位表示一個(gè)引腳當(dāng)前的輸入電平狀態(tài)。PSR 寄存器的權(quán)限是只讀的,對(duì)它進(jìn)行寫操作是無(wú)效的。
特別地,當(dāng)引腳被配置成輸出模式時(shí),若 IOMUXC 中的 MUX 寄存器使能了 SION 功能(輸出通道回環(huán)至輸入), 可以通過(guò) PSR 寄存器讀取回引腳的狀態(tài)值。

二、引腳確定
我使用的是 野火_EBF6ULL S1 Pro 開發(fā)板

從原理圖可看到 RGB 燈的三個(gè)陰極 R、G、B 連接分別連接至標(biāo)號(hào)
GPIO_4、CSI_HSYNC、CSI_VSYNC, 這些標(biāo)號(hào)實(shí)際上與配套核心板上 i.MX6ULL 芯片的引腳相連。由于引腳功能眾多, 繪制原理圖時(shí)不可避免地?zé)o法完全表示引腳信息的所有信息。而無(wú)論是具體的引腳名還是復(fù)用功能, 我們都無(wú)法直接得知這些具體是 i.MX6ULL 芯片的哪個(gè)引腳。我們需要知道這些引腳是對(duì)應(yīng)的具體 GPIO,這樣我們才能編寫程序進(jìn)行控制。
由于還不清楚標(biāo)號(hào) GPIO_4、CSI_HSYNC、CSI_VSYNC 的具體引腳名,我們首先要在核心板原理圖中查看它與 i.MX6ULL 芯片的關(guān)系。打開 《野火_EBF6ULL S1 郵票孔核心板V1.0原理圖》,在PDF閱讀器的搜索框輸入前面的 GPIO_4、CSI_HSYNC、CSI_VSYNC 標(biāo)號(hào)。


查找到了
GPIO_4信號(hào)的具體引腳名為GPIO1_IO04。 但是當(dāng)我們使用同樣的方法查找時(shí)發(fā)現(xiàn)只能找到CSI_HSYNC、CSI_VSYNC, 并沒有我們熟悉的 GPIOx_IOx 標(biāo)注的引腳名。這兩個(gè)引腳默認(rèn)情況下不用作 GPIO,而是用作攝像頭的某一功能引腳,但是它可以復(fù)用為 GPIO,我們?cè)趺凑业綄?duì)應(yīng)的 GPIO 呢?
-
方法一:
在《i.MX 6UltraLite Applications Processor Reference Manual》的第4章 External Signals and Pin Multiplexing 搜索引腳名
-
方法二:
在官方寫好的文件 fsl_iomuxc.h(路徑:SDK文件夾/devices/MCIMX6Y2/drivers/fsl_iomuxc.h) 中搜索引腳名
經(jīng)查閱,我們把以上連接 LED 燈的各個(gè) i.MX6ULL 芯片引腳總結(jié)出如表:
| LED燈 | 原理圖的標(biāo)號(hào) | 具體引腳名 | GPIO端口及引腳編號(hào) |
|---|---|---|---|
| R燈 | GPIO_4 | GPIO1_IO04 | GPIO1_IO04 |
| G燈 | CSI_HSYNC | CSI_HSYNC | GPIO4_IO20 |
| B燈 | CSI_VSYNC | CSI_VSYNC | GPIO4_IO19 |
三、編程流程
1. 移植官方寄存器定義文件
2. 移植官方SDK引腳復(fù)用和引腳屬性定義文件
3. 移植野火PAD屬性配置文件
4. 編寫啟動(dòng)文件
5. 編寫鏈接文件
6. 編寫makefile文件
7. 編寫C語(yǔ)言代碼
(1) 開啟GPIO時(shí)鐘
(2) 設(shè)置引腳的復(fù)用功能以及引腳屬性
(3) 設(shè)置引腳方向以及輸出電平
(4) 查詢按鍵輸入控制LED
四、移植官方SDK寄存器定義文件
使用匯編語(yǔ)言和C語(yǔ)言實(shí)現(xiàn)點(diǎn)亮LED燈。需要自己查找、定義那么多寄存器。這樣做的缺點(diǎn)很明顯,易錯(cuò)、費(fèi)時(shí)、代碼可讀性差。NXP官方SDK中已經(jīng)將所有的寄存器以及所有可用引腳的復(fù)用功能定義好了。
添加官方SDK寄存器定義文件 MCIMX6Y2.h,位于 SDK_2.2_MCIM6ULL_EBF6ULL/devices/MCIMX6Y2 目錄下。

在官方SDK頭文件
MCIMX6Y2.h文件多達(dá)4萬(wàn)多行,包含了i.MX6U芯片幾乎所有的寄存器定義以及中斷編號(hào)的定義。
這里只列 GPIO1相關(guān)寄存器 的部分代碼。其他寄存器定義與此類似。 添加這些定義之后我們就可以 直接使用 “GPIO1->DR” 語(yǔ)句操作GPIO1的DR寄存器。操作方法與STM32非常相似。
typedef struct {
__IO uint32_t DR; /**< GPIO data register, offset: 0x0 */
__IO uint32_t GDIR; /**< GPIO direction register, offset: 0x4 */
__I uint32_t PSR; /**< GPIO pad status register, offset: 0x8 */
__IO uint32_t ICR1; /**< GPIO interrupt configuration register1,*/
__IO uint32_t ICR2; /**< GPIO interrupt configuration register2, */
__IO uint32_t IMR; /**< GPIO interrupt mask register, offset: 0x14 */
__IO uint32_t ISR; /**< GPIO interrupt status register, offset: 0x18 */
__IO uint32_t EDGE_SEL;/**< GPIO edge select register, offset: 0x1C */
} GPIO_Type;
/*********************以下代碼省略***************************8*/
/** Peripheral GPIO1 base address */
#define GPIO1_BASE (0x209C000u)
/** Peripheral GPIO1 base pointer */
#define GPIO1 ((GPIO_Type *)GPIO1_BASE)
五、移植官方SDK引腳復(fù)用和引腳屬性定義文件
添加官方SDK引腳復(fù)用和引腳屬性定義文件 fsl_iomuxc.h,位于 SDK_2.2_MCIM6ULL_EBF6ULL/devices/MCIMX6Y2/drivers 目錄下。

使用每一個(gè)引腳之前我們都要選擇引腳的復(fù)用功能以及引腳的pad屬性。在官方SDK的頭文件
fsl_iomuxc.h中定義了所有可用引腳以及這些引腳的所有復(fù)用功能,我們需要哪種復(fù)用功能只需要選擇即可,并且官方SDK中提供了初始化函數(shù)。
-
定義引腳的復(fù)用功能
這里只列出了“GPIO1_IO00”引腳的復(fù)用功能,其他引腳類似。每個(gè)引腳對(duì)應(yīng)多個(gè)宏定義代表引腳的不同的復(fù)用功能,以宏“IOMUXC_GPIO1_IO00_I2C2_SCL”為例,它表示“GPIO1_IO00”引腳復(fù)用為“I2C2”的“SCL”引腳。這些宏定義將會(huì)用作某些函數(shù)的入口參數(shù)。
#define IOMUXC_GPIO1_IO00_I2C2_SCL \
0x020E005CU, 0x0U, 0x020E05ACU, 0x1U, 0x020E02E8U
#define IOMUXC_GPIO1_IO00_GPT1_CAPTURE1L \
0x020E005CU, 0x1U, 0x020E058CU, 0x0U, 0x020E02E8U
#define IOMUXC_GPIO1_IO00_ANATOP_OTG1_IDL \
0x020E005CU, 0x2U, 0x020E04B8U, 0x0U, 0x020E02E8U
#define IOMUXC_GPIO1_IO00_ENET1_REF_CLK1L \
0x020E005CU, 0x3U, 0x020E0574U, 0x0U, 0x020E02E8U
#define IOMUXC_GPIO1_IO00_MQS_RIGHTL \
0x020E005CU, 0x4U, 0x00000000U, 0x0U, 0x020E02E8U
#define IOMUXC_GPIO1_IO00_GPIO1_IO00L \
0x020E005CU, 0x5U, 0x00000000U, 0x0U, 0x020E02E8U
#define IOMUXC_GPIO1_IO00_ENET1_1588_EVENT0_INL \
0x020E005CU, 0x6U, 0x00000000U, 0x0U, 0x020E02E8U
#define IOMUXC_GPIO1_IO00_SRC_SYSTEM_RESETL \
0x020E005CU, 0x7U, 0x00000000U, 0x0U, 0x020E02E8U
#define IOMUXC_GPIO1_IO00_WDOG3_WDOG_BL \
0x020E005CU, 0x8U, 0x00000000U, 0x0U, 0x020E02E8U
#define IOMUXC_GPIO1_IO01_I2C2_SDAL \
0x020E0060U, 0x0U, 0x020E05B0U, 0x1U, 0x020E02ECU
#define IOMUXC_GPIO1_IO01_GPT1_COMPARE1L \
0x020E0060U, 0x1U, 0x00000000U, 0x0U, 0x020E02ECU
#define IOMUXC_GPIO1_IO01_USB_OTG1_OCL \
0x020E0060U, 0x2U, 0x020E0664U, 0x0U, 0x020E02ECU
-
引腳復(fù)用功能設(shè)置函數(shù)
IOMUXC_SetPinMux()擁有6個(gè)入口參數(shù), 但是前五個(gè)是通過(guò)上面的宏定義自動(dòng)完成設(shè)置的。而第6個(gè)入口參數(shù)“inputOnfiled”用于設(shè)置是否開啟讀回引腳電平功能。
static inline void IOMUXC_SetPinMux(uint32_t muxRegister,
uint32_t muxMode,
uint32_t inputRegister,
uint32_t inputDaisy,
uint32_t configRegister,
uint32_t inputOnfield)
{
*((volatile uint32_t *)muxRegister) =
IOMUXC_SW_MUX_CTL_PAD_MUX_MODE(muxMode) |\
IOMUXC_SW_MUX_CTL_PAD_SION(inputOnfield);
if (inputRegister)
{
*((volatile uint32_t *)inputRegister) = \
IOMUXC_SELECT_INPUT_DAISY(inputDaisy);
}
}
-
引腳PAD屬性設(shè)置函數(shù)
IOMUXC_SetPinConfig()函數(shù)共有6個(gè)入口參數(shù),其中前五個(gè)是通過(guò)上面的宏定義自動(dòng)完成設(shè)置的。而第6個(gè)參數(shù)用于設(shè)置PAD屬性,根據(jù)每個(gè)引腳擁有一個(gè)32位PAD屬性寄存器。第六個(gè)參數(shù)就是設(shè)置要填入PAD屬性寄存器的值。
static inline void IOMUXC_SetPinConfig(uint32_t muxRegister,
uint32_t muxMode,
uint32_t inputRegister,
uint32_t inputDaisy,
uint32_t configRegister,
uint32_t configValue)
{
if (configRegister)
{
*((volatile uint32_t *)configRegister) = configValue;
}
}
代碼屏蔽 #include "fsl_common.h"

六、移植野火PAD屬性配置文件
添加 pad_config.h。
通常情況下一個(gè)引腳要設(shè)置8種PAD屬性,而這些屬性只能通過(guò)數(shù)字指定。為簡(jiǎn)化PAD屬性設(shè)置野火編寫了一個(gè)PAD屬性配置文件 pad_config.h (embed_linux_driver_tutorial_imx6_code/bare_metal/led_rgb_c/pad_config.h)【源碼下載:https://gitee.com/Embedfire/embed_linux_driver_tutorial_imx6_code.git】,這里使用宏定義了引腳可選的PAD屬性值,并且通過(guò)宏定義的名字很容易知道宏代表的屬性值:
/* SPEED 帶寬配置 */
#define SPEED_0_LOW_50MHz IOMUXC_SW_PAD_CTL_PAD_SPEED(0)
#define SPEED_1_MEDIUM_100MHz IOMUXC_SW_PAD_CTL_PAD_SPEED(1)
#define SPEED_2_MEDIUM_100MHz IOMUXC_SW_PAD_CTL_PAD_SPEED(2)
#define SPEED_3_MAX_200MHz IOMUXC_SW_PAD_CTL_PAD_SPEED(3)
/* PUE 選擇使用保持器還是上下拉 */
#define PUE_0_KEEPER_SELECTED IOMUXC_SW_PAD_CTL_PAD_PUE(0)
#define PUE_1_PULL_SELECTED IOMUXC_SW_PAD_CTL_PAD_PUE(1)
/* PUS 上下拉配置 */
#define PUS_0_100K_OHM_PULL_DOWN IOMUXC_SW_PAD_CTL_PAD_PUS(0)
#define PUS_1_47K_OHM_PULL_UP IOMUXC_SW_PAD_CTL_PAD_PUS(1)
#define PUS_2_100K_OHM_PULL_UP IOMUXC_SW_PAD_CTL_PAD_PUS(2)
#define PUS_3_22K_OHM_PULL_UP IOMUXC_SW_PAD_CTL_PAD_PUS(3)
完整的代碼請(qǐng)閱讀源文件,這里只列出了文件“pad_config.h”部分代碼(embed_linux_driver_tutorial_imx6_code/bare_metal/led_rgb_c/pad_config.h)【源碼下載:https://gitee.com/Embedfire/embed_linux_driver_tutorial_imx6_code.git】。
七、編寫啟動(dòng)文件
在 Ubuntu 下創(chuàng)建 start.S 文件用于編寫啟動(dòng)文件。
在匯編文件中設(shè)置“棧地址”并執(zhí)行跳轉(zhuǎn)命令跳轉(zhuǎn)到main函數(shù)執(zhí)行C代碼。
7.1 完整代碼
/***********************第一部分*********************/
.text //代碼段
.align 2 //設(shè)置2字節(jié)對(duì)齊
.global _start //定義一個(gè)全局標(biāo)號(hào)
/*************************第二部分*************************/
_start: //程序的開始
b reset //跳轉(zhuǎn)到reset標(biāo)號(hào)處
/*************************第三部分*************************/
reset:
mrc p15, 0, r0, c1, c0, 0 /* 將 CP15 協(xié)處理器中的寄存器數(shù)據(jù)讀到 ARM 寄存器中 */
bic r0, r0, #(0x1 << 12) /* 清除第12位(I位)禁用 I Cache */
bic r0, r0, #(0x1 << 2) /* 清除第 2位(C位)禁用 D Cache */
bic r0, r0, #0x2 /* 清除第 1位(A位)禁止嚴(yán)格對(duì)齊 */
bic r0, r0, #(0x1 << 11) /* 清除第11位(Z位)分支預(yù)測(cè) */
bic r0, r0, #0x1 /* 清除第 0位(M位)禁用 MMU */
mcr p15, 0, r0, c1, c0, 0 /* 將 ARM 寄存器的數(shù)據(jù)寫入到 CP15 協(xié)處理器寄存器中 */
/***********************第四部分*********************/
ldr sp, =0x84000000 //設(shè)置棧地址64M
b main //跳轉(zhuǎn)到main函數(shù)
/***********************第五部分*******************/
/*進(jìn)入死循環(huán)*/
loop:
b loop
7.2 分析代碼
-
第一部分
.text定義代碼段。
.align 2設(shè)置字節(jié)對(duì)齊。
.global _start生命全局標(biāo)號(hào)_start。
/*************************第一部分*************************/
.text //代碼段
.align 2 //設(shè)置2字節(jié)對(duì)齊
.global _start //定義一個(gè)全局標(biāo)號(hào)
-
第二部分
_start:定義標(biāo)號(hào)_start: ,它位于匯編的最前面,說(shuō)以會(huì)首先被執(zhí)行。
b reset使用b指令將程序跳轉(zhuǎn)到reset標(biāo)號(hào)處。
/*************************第二部分*************************/
_start: //程序的開始
b reset //跳轉(zhuǎn)到reset標(biāo)號(hào)處
-
第三部分
通過(guò)修改CP15寄存器(系統(tǒng)控制寄存器)關(guān)閉 I Cache 、D Cache、MMU 等等。
我們暫時(shí)用不到的功能,如果開啟可能會(huì)影響我們裸機(jī)運(yùn)行,為避免不必要的麻煩暫時(shí)關(guān)閉這些功能。
/*************************第三部分*************************/
reset:
mrc p15, 0, r0, c1, c0, 0 /* 將 CP15 協(xié)處理器中的寄存器數(shù)據(jù)讀到 ARM 寄存器中 */
bic r0, r0, #(0x1 << 12) /* 清除第12位(I位)禁用 I Cache */
bic r0, r0, #(0x1 << 2) /* 清除第 2位(C位)禁用 D Cache */
bic r0, r0, #0x2 /* 清除第 1位(A位)禁止嚴(yán)格對(duì)齊 */
bic r0, r0, #(0x1 << 11) /* 清除第11位(Z位)分支預(yù)測(cè) */
bic r0, r0, #0x1 /* 清除第 0位(M位)禁用 MMU */
mcr p15, 0, r0, c1, c0, 0 /* 將 ARM 寄存器的數(shù)據(jù)寫入到 CP15 協(xié)處理器寄存器中 */
-
第四部分
ldr sp, =0x84000000用于設(shè)置棧指針。野火i.MX6ULL開發(fā)板標(biāo)配512M的DDR內(nèi)存,裸機(jī)開發(fā)用不了這么多。程序中我們將棧地址設(shè)置到DDR的64M地址處。 這個(gè)值也可以根據(jù)需要自行定義。
b main只用跳轉(zhuǎn)指令跳轉(zhuǎn)到main函數(shù)中執(zhí)行。
/***********************第四部分*********************/
ldr sp, =0x84000000 //設(shè)置棧地址64M
b main //跳轉(zhuǎn)到main函數(shù)
-
第五部分
b loop是“無(wú)返回”的跳轉(zhuǎn)指令。正常情況下,不會(huì)執(zhí)行第五部分代碼。
/***********************第五部分*******************/
/*進(jìn)入死循環(huán)*/
loop:
b loop
八、編寫鏈接腳本
寫好的代碼(無(wú)論是匯編還是C語(yǔ)言)都要經(jīng)過(guò)編譯、匯編、鏈接等步驟生成二進(jìn)制文件或者可供下載的文件。在編譯階編譯器會(huì)對(duì)每個(gè)源文件進(jìn)行語(yǔ)法檢查并生成對(duì)應(yīng)的匯編語(yǔ)言,匯編是將匯編文件轉(zhuǎn)化為機(jī)器碼。
使用
arm-none-eabi-gcc -g -c led.S -o led.o命令完成源碼的編譯、匯編工作,生成了.o文件。編譯和匯編是針對(duì)單個(gè)源文件,也就編譯完成后一個(gè)源文件(.c,.S或.s)對(duì)應(yīng)一個(gè).o文件。程序鏈接階段就會(huì)將這些.o鏈接成一個(gè)文件。鏈接腳本的作用就是告訴編譯器怎么鏈接這些文件,比如那個(gè)文件放在最前面,程序的代碼段、數(shù)據(jù)段、bss段分別放在什么位置等等。
在 Ubuntu 下創(chuàng)建 led.lds 鏈接腳本。
8.1 完整代碼
ENTRY(_start)
SECTIONS {
. = 0x80000000;
. = ALIGN(4);
.text :
{
start.o (.text)
*(.text)
}
. = ALIGN(4);
.data :
{
*(.data)
}
. = ALIGN(4);
.bss :
{
*(.bss)
}
}
8.2 分析代碼
-
指定程序的入口
ENTRY(_start)用于指定程序的入口,ENTRY()是設(shè)置入口地址的命令,“_start”是程序的入口,led程序的入口地址位于start.S的“_start”標(biāo)號(hào)處。
ENTRY(_start)
-
定義SECTIONS
SECTIONS可以理解為是一塊區(qū)域,我們?cè)谶@塊區(qū)域排布我們的代碼,鏈接時(shí)鏈接器就會(huì)按照這里的指示鏈接我們的代碼。
SECTIONS {
···
···
}
-
定義鏈接起始地址
“.”運(yùn)算符代表當(dāng)前位置。 我們?cè)赟ECTION的最開始使用“.= 0x80000000”就是將鏈接起始地址設(shè)置為0x80000000。
. = 0x80000000;
設(shè)置字節(jié)對(duì)齊
“. = ALIGN(4);”它表示從當(dāng)前位置開始執(zhí)行四字節(jié)對(duì)齊。假設(shè)當(dāng)前位置為0x80000001,執(zhí)行該命令后當(dāng)前地址將會(huì)空出三個(gè)字節(jié)轉(zhuǎn)到0x80000004地址處。設(shè)置代碼段
“.text :”用于定義代碼段,固定的語(yǔ)法要求,我們按照要求寫即可。在“{}”中指定那些內(nèi)容放在代碼段。
將start.o中的代碼放到代碼段的最前面。start.S是啟動(dòng)代碼應(yīng)當(dāng)首先被執(zhí)行,所以通常情況下要把它放到代碼段的最前面,其他源文件的代碼按照系統(tǒng)默認(rèn)的排放順序即可,通配符“*”在這里表示其他剩余所有的.o文件。
. = ALIGN(4);
.text :
{
start.o (.text)
*(.text)
}
-
設(shè)置數(shù)據(jù)段
同設(shè)置代碼段類似,首先設(shè)置字節(jié)對(duì)齊,然后定義代碼段。在數(shù)據(jù)段里使用“*”通配符, 將所有源文件中的代碼添加到這個(gè)數(shù)據(jù)段中。
. = ALIGN(4);
.data :
{
*(.data)
}
-
設(shè)置BSS段
設(shè)置方法與設(shè)置數(shù)據(jù)段完全相同。
. = ALIGN(4);
.bss :
{
*(.bss)
}
九、編寫makefile文件
程序編寫完成后需要依次輸入編譯、鏈接、格式轉(zhuǎn)換命令才能最終生成二進(jìn)制文件。這種編譯方式效率低、容易出錯(cuò)。
使用
makefile只需要在所在文件夾下執(zhí)行make命令,makefile工具便會(huì)自動(dòng)完成程序的編譯、鏈接、格式轉(zhuǎn)換等工作。正常情況下我們可以在當(dāng)前目錄看到生成的一些中間文件以及我們期待的.bin文件。
在 Ubuntu 下創(chuàng)建 makefile 文件。
9.1 完整代碼
all: start.o led.o
arm-none-eabi-ld -Tled.lds $^ -o led.elf
arm-none-eabi-objcopy -O binary -S -g led.elf led.bin
%.o : %.S
arm-none-eabi-gcc -g -c $^ -o start.o
%.o : %.c
arm-none-eabi-gcc -g -c $^ -o led.o
.PHONY: clean
clean:
rm *.o *.elf *.bin
9.2 分析代碼
- 添加最終目標(biāo)以及依賴文件
all: start.o led.o
-
添加鏈接命令
“-Tled.lds”表示使用led.lds鏈接腳本鏈接程序。
“$^”代表所有的依賴文件。
“-o”指定輸出文件名。
arm-none-eabi-ld -Tled.lds $^ -o led.elf
-
添加格式轉(zhuǎn)換命令
“-O binary”指定輸出二進(jìn)制文件。
“-S”不從源文件中復(fù)制重定位信息和符號(hào)信息。
“-g”不從源文件中復(fù)制可調(diào)試信息。
arm-none-eabi-objcopy -O binary -S -g led.elf led.bin
-
添加匯編文件編譯命令
“$^”替代要編譯的源文件。
%.o : %.S
arm-none-eabi-gcc -g -c $^ -o start.o
-
添加編譯C文件的命令
“$^”替代要編譯的源文件。
%.o : %.c
arm-none-eabi-gcc -g -c $^ -o led.o
-
添加清理命令
“.PHONY”定義了偽目標(biāo)“clean”。偽目標(biāo)一般沒有依賴,并且“clean”偽目標(biāo)一般放在Makefile文件的末尾。
“clean”為目標(biāo)用于刪除make生成的文件。
.PHONY: clean
clean:
rm *.o *.elf *.bin
十、編寫C語(yǔ)言代碼
在 Ubuntu 下創(chuàng)建 led.c 文件用于驅(qū)動(dòng) RGB 燈。
10.1 完整代碼
/*************************第一部分************************/
#include "MCIMX6Y2.h"
#include "fsl_iomuxc.h"
#include "pad_config.h"
/*************************第二部分************************/
/*LED GPIO端口、引腳號(hào)及IOMUXC復(fù)用宏定義*/
#define RGB_RED_LED_GPIO GPIO1
#define RGB_RED_LED_GPIO_PIN (4U)
#define RGB_RED_LED_IOMUXC IOMUXC_GPIO1_IO04_GPIO1_IO04
#define RGB_GREEN_LED_GPIO GPIO4
#define RGB_GREEN_LED_GPIO_PIN (20U)
#define RGB_GREEN_LED_IOMUXC IOMUXC_CSI_HSYNC_GPIO4_IO20
#define RGB_BLUE_LED_GPIO GPIO4
#define RGB_BLUE_LED_GPIO_PIN (19U)
#define RGB_BLUE_LED_IOMUXC IOMUXC_CSI_VSYNC_GPIO4_IO19
/*************************第三部分************************/
/* 所有引腳均使用同樣的PAD配置 */
#define LED_PAD_CONFIG_DATA (SRE_0_SLOW_SLEW_RATE| \
DSE_6_R0_6| \
SPEED_2_MEDIUM_100MHz| \
ODE_0_OPEN_DRAIN_DISABLED| \
PKE_0_PULL_KEEPER_DISABLED| \
PUE_0_KEEPER_SELECTED| \
PUS_0_100K_OHM_PULL_DOWN| \
HYS_0_HYSTERESIS_DISABLED)
/* 配置說(shuō)明 : */
/* 轉(zhuǎn)換速率: 轉(zhuǎn)換速率慢
驅(qū)動(dòng)強(qiáng)度: R0/6
帶寬配置 : medium(100MHz)
開漏配置: 關(guān)閉
拉/保持器配置: 關(guān)閉
拉/保持器選擇: 保持器(上面已關(guān)閉,配置無(wú)效)
上拉/下拉選擇: 100K歐姆下拉(上面已關(guān)閉,配置無(wú)效)
滯回器配置: 關(guān)閉 */
/*************************第四部分************************/
/*簡(jiǎn)單延時(shí)函數(shù)*/
void delay(uint32_t count)
{
volatile uint32_t i = 0;
for (i = 0; i < count; ++i)
{
__asm("NOP"); /* 調(diào)用nop空指令 */
}
}
int main()
{
/*************************第五部分************************/
CCM->CCGR1 |= CCM_CCGR1_CG13(0x3);//開啟GPIO1的時(shí)鐘
CCM->CCGR3 |= CCM_CCGR3_CG6(0x3); //開啟GPIO4的時(shí)鐘
/*************************第六部分************************/
/*設(shè)置 紅燈 引腳的復(fù)用功能以及PAD屬性*/
IOMUXC_SetPinMux(RGB_RED_LED_IOMUXC,0);
IOMUXC_SetPinConfig(RGB_RED_LED_IOMUXC, LED_PAD_CONFIG_DATA);
/*設(shè)置 綠燈 引腳的復(fù)用功能以及PAD屬性*/
IOMUXC_SetPinMux(RGB_GREEN_LED_IOMUXC,0);
IOMUXC_SetPinConfig(RGB_GREEN_LED_IOMUXC, LED_PAD_CONFIG_DATA);
/*設(shè)置 藍(lán)燈 引腳的復(fù)用功能以及PAD屬性*/
IOMUXC_SetPinMux(RGB_BLUE_LED_IOMUXC,0);
IOMUXC_SetPinConfig(RGB_BLUE_LED_IOMUXC, LED_PAD_CONFIG_DATA);
/*************************第七部分************************/
GPIO1->GDIR |= (1<<4); //設(shè)置GPIO1_04為輸出模式
GPIO1->DR |= (1<<4); //設(shè)置GPIO1_04輸出電平為高電平
GPIO4->GDIR |= (1<<20); //設(shè)置GPIO4_20為輸出模式
GPIO4->DR |= (1<<20); //設(shè)置GPIO4_20輸出電平為高電平
GPIO4->GDIR |= (1<<19); //設(shè)置GPIO4_19為輸出模式
GPIO4->DR |= (1<<19); //設(shè)置GPIO4_19輸出電平為高電平
/*************************第八部分************************/
while(1)
{
GPIO1->DR &= ~(1<<4); //紅燈亮
delay(0xFFFFF);
GPIO1->DR |= (1<<4); //紅燈滅
GPIO4->DR &= ~(1<<20); //綠燈亮
delay(0xFFFFF);
GPIO4->DR |= (1<<20); //綠燈滅
GPIO4->DR &= ~(1<<19); //藍(lán)燈亮
delay(0xFFFFF);
GPIO4->DR |= (1<<19); //藍(lán)燈滅
}
return 0;
}
10.2 分析代碼
-
第一部分:添加頭文件
文件“MCIMX6Y2.h”和“fsl_iomuxc.h”來(lái)自SDK。 文件“pad_config.h”是野火編寫的文件,在其他工程中可直接使用。
/*************************第一部分************************/
#include "MCIMX6Y2.h"
#include "fsl_iomuxc.h"
#include "pad_config.h"
- 第二部分:定義GPIO相關(guān)引腳以及復(fù)用功能
/*************************第二部分************************/
/*LED GPIO端口、引腳號(hào)及IOMUXC復(fù)用宏定義*/
#define RGB_RED_LED_GPIO GPIO1
#define RGB_RED_LED_GPIO_PIN (4U)
#define RGB_RED_LED_IOMUXC IOMUXC_GPIO1_IO04_GPIO1_IO04
#define RGB_GREEN_LED_GPIO GPIO4
#define RGB_GREEN_LED_GPIO_PIN (20U)
#define RGB_GREEN_LED_IOMUXC IOMUXC_CSI_HSYNC_GPIO4_IO20
#define RGB_BLUE_LED_GPIO GPIO4
#define RGB_BLUE_LED_GPIO_PIN (19U)
#define RGB_BLUE_LED_IOMUXC IOMUXC_CSI_VSYNC_GPIO4_IO19
-
第三部分:定義引腳的PAD屬性
PAD屬性宏定義保存在“pad_config.h”文件中,這里使用“|”運(yùn)算符將所有屬性設(shè)置“合并”在一起,后面將作為函數(shù)參數(shù)。
/*************************第三部分************************/
/* 所有引腳均使用同樣的PAD配置 */
#define LED_PAD_CONFIG_DATA (SRE_0_SLOW_SLEW_RATE| \
DSE_6_R0_6| \
SPEED_2_MEDIUM_100MHz| \
ODE_0_OPEN_DRAIN_DISABLED| \
PKE_0_PULL_KEEPER_DISABLED| \
PUE_0_KEEPER_SELECTED| \
PUS_0_100K_OHM_PULL_DOWN| \
HYS_0_HYSTERESIS_DISABLED)
/* 配置說(shuō)明 : */
/* 轉(zhuǎn)換速率: 轉(zhuǎn)換速率慢
驅(qū)動(dòng)強(qiáng)度: R0/6
帶寬配置 : medium(100MHz)
開漏配置: 關(guān)閉
拉/保持器配置: 關(guān)閉
拉/保持器選擇: 保持器(上面已關(guān)閉,配置無(wú)效)
上拉/下拉選擇: 100K歐姆下拉(上面已關(guān)閉,配置無(wú)效)
滯回器配置: 關(guān)閉 */
- 第四部分:簡(jiǎn)單的延時(shí)函數(shù)
/*************************第四部分************************/
/*簡(jiǎn)單延時(shí)函數(shù)*/
void delay(uint32_t count)
{
volatile uint32_t i = 0;
for (i = 0; i < count; ++i)
{
__asm("NOP"); /* 調(diào)用nop空指令 */
}
}
- 第五部分:開啟GPIO時(shí)鐘
/*************************第五部分************************/
CCM->CCGR1 |= CCM_CCGR1_CG13(0x3);//開啟GPIO1的時(shí)鐘
CCM->CCGR3 |= CCM_CCGR3_CG6(0x3); //開啟GPIO4的時(shí)鐘
- 第六部分:設(shè)置引腳的復(fù)用功能以及引腳PAD屬性
/*************************第六部分************************/
/*設(shè)置 紅燈 引腳的復(fù)用功能以及PAD屬性*/
IOMUXC_SetPinMux(RGB_RED_LED_IOMUXC,0);
IOMUXC_SetPinConfig(RGB_RED_LED_IOMUXC, LED_PAD_CONFIG_DATA);
/*設(shè)置 綠燈 引腳的復(fù)用功能以及PAD屬性*/
IOMUXC_SetPinMux(RGB_GREEN_LED_IOMUXC,0);
IOMUXC_SetPinConfig(RGB_GREEN_LED_IOMUXC, LED_PAD_CONFIG_DATA);
/*設(shè)置 藍(lán)燈 引腳的復(fù)用功能以及PAD屬性*/
IOMUXC_SetPinMux(RGB_BLUE_LED_IOMUXC,0);
IOMUXC_SetPinConfig(RGB_BLUE_LED_IOMUXC, LED_PAD_CONFIG_DATA);
- 第七部分:設(shè)置GPIO為輸出并設(shè)置初始電平為高電平
/*************************第七部分************************/
GPIO1->GDIR |= (1<<4); //設(shè)置GPIO1_04為輸出模式
GPIO1->DR |= (1<<4); //設(shè)置GPIO1_04輸出電平為高電平
GPIO4->GDIR |= (1<<20); //設(shè)置GPIO4_20為輸出模式
GPIO4->DR |= (1<<20); //設(shè)置GPIO4_20輸出電平為高電平
GPIO4->GDIR |= (1<<19); //設(shè)置GPIO4_19為輸出模式
GPIO4->DR |= (1<<19); //設(shè)置GPIO4_19輸出電平為高電平
- 第八部分:在while(1)中依次點(diǎn)亮紅燈、綠燈和藍(lán)燈
/*************************第八部分************************/
while(1)
{
GPIO1->DR &= ~(1<<4); //紅燈亮
delay(0xFFFFF);
GPIO1->DR |= (1<<4); //紅燈滅
GPIO4->DR &= ~(1<<20); //綠燈亮
delay(0xFFFFF);
GPIO4->DR |= (1<<20); //綠燈滅
GPIO4->DR &= ~(1<<19); //藍(lán)燈亮
delay(0xFFFFF);
GPIO4->DR |= (1<<19); //藍(lán)燈滅
}
十一、編譯下載驗(yàn)證
11.1 編譯代碼
make
執(zhí)行make命令,生成led.bin文件。
11.2 代碼燒寫
編譯成功后會(huì)在當(dāng)前文件夾下生成.bin文件,這個(gè).bin文件也不能直接放到開發(fā)板上運(yùn)行, 這次是因?yàn)樾枰?bin文件缺少啟動(dòng)相關(guān)信息。
為二進(jìn)制文件添加頭部信息并燒寫到SD卡。查看 IMX6ULL學(xué)習(xí)筆記(12)——通過(guò)SD卡啟動(dòng)官方SDK程序
進(jìn)入燒寫工具目錄,執(zhí)行 ./mkimage.sh <燒寫文件路徑> 命令,例如要燒寫的 led.bin 位于 home 目錄下,則燒寫命令為 ./mkimage.sh /home/led.bin。
執(zhí)行上一步后會(huì)列出linux下可燒寫的磁盤,選擇你插入的SD卡即可。這一步 非常危險(xiǎn)?。?!一定要確定選擇的是你插入的SD卡??!,如果選錯(cuò)很可能破壞你電腦磁盤內(nèi)容,造成數(shù)據(jù)損壞?。。?確定磁盤后SD卡以“sd”開頭,選擇“sd”后面的字符即可。例如要燒寫的sd卡是“sdb”則輸入“b”即可。
11.3 實(shí)驗(yàn)現(xiàn)象
將開發(fā)板設(shè)置為SD卡啟動(dòng),接入SD卡,開發(fā)板上電,可以看到開發(fā)板上RGB紅、綠、藍(lán)三種顏色輪流閃爍。

? 由 Leung 寫于 2022 年 12 月 25 日
? 參考:6. 完善LED程序






