一. 實驗準備?
基于正點原子 IMX6ULL-Mini 開發板,實現 LED 周期性閃爍功能,需完成環境搭建與硬件原理確認兩大核心準備工作。?
1.1 開發環境搭建?
需在Windows和Ubuntu中安裝工具,確保文件傳輸、交叉編譯、代碼編輯功能正常。
1.1.1 跨系統文件傳輸工具(FileZilla + Ubuntu FTP服務)?
用于Windows與Ubuntu之間傳輸代碼、工具鏈等文件:
1. Windows端安裝FileZilla
下載地址:[https://www.filezilla.cn/download](https://www.filezilla.cn/download),默認安裝即可。
2. Ubuntu端配置FTP服務(vsftpd)
打開Ubuntu終端,執行以下命令:
```bash # 安裝vsftpd服務 sudo apt-get install vsftpd
# 配置vsftpd.conf文件 sudo vi /etc/vsftpd.conf ``` 在配置文件中確保以下兩行**無注釋(刪除開頭的#)** : ```ini local_enable=YES # 允許本地用戶登錄 write_enable=YES # 允許寫入操作 ``` 保存退出后,重啟FTP服務:`sudo /etc/init.d/vsftpd restart`。
3. 連接測試
打開FileZilla,點擊「文件→站點管理器」,輸入Ubuntu的IP地址、用戶名、密碼,連接成功后即可互傳文件。
1.1.2 交叉編譯工具鏈安裝(Linaro GCC)
由于PC(x86架構)需編譯ARM架構(I.MX6ULL)的程序,需安裝**交叉編譯工具鏈**:
1. 下載工具? 選擇適配64位Ubuntu的版本,下載地址: [https://releases.linaro.org/components/toolchain/binaries/latest-7/arm-linux-gnueabihf/](https://releases.linaro.org/components/toolchain/binaries/latest-7/arm-linux-gnueabihf/) 文件名:`gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf.tar.xz`。
2. 解壓工具鏈到Ubuntu????????用FileZilla將工具鏈壓縮包上傳到Ubuntu家目錄,執行以下命令: ```bash # 創建安裝目錄 sudo mkdir /usr/local/arm # 拷貝壓縮包到安裝目錄 sudo cp ~/工具鏈文件名 /usr/local/arm/ -f # 解壓 sudo tar -vxf /usr/local/arm/工具鏈文件名 ```
3. 配置環境變量????????編輯`~/.bashrc`文件,在末尾添加工具鏈路徑: ```bash export PATH=$PATH:/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin ``` 保存后執行`source ~/.bashrc`使環境變量生效。
4. 驗證安裝????????終端輸入`arm-linux-gnueabihf-gcc -v`,若顯示`4.9.4`版本信息,則安裝成功。
5. 安裝依賴庫????????執行`sudo apt-get install lsb-core lib32stdc++6`,解決64位Ubuntu運行32位工具鏈的依賴問題。
?1.1.3 代碼編輯器(VSCode) 可選Windows或Ubuntu版本,用于編寫匯編、C代碼,推薦安裝`C/C++`、`ARM`插件以支持語法高亮。
1.2 開發板硬件原理確認
?1.2.1 開發板結構 IMX6ULL-Mini開發板分為**核心板**和**底板**:
- 核心板:包含IMX6ULL芯片、DDR(內存)、eMMC(存儲)等核心器件;
- 底板:包含LED、按鍵等外設。
1.2.2 LED核心控制邏輯
當GPIO1_IO03輸出**低電平(0)** 時,LED導通點亮;輸出**高電平(1)** 時,LED熄滅。
二. 代碼編寫
實驗代碼分為「匯編初始化代碼」和「C語言功能代碼」,匯編負責初始化C環境(時鐘、GPIO復用),C語言實現LED閃爍邏輯。
2.1 匯編代碼(start.s)
LED
作用:初始化系統時鐘、配置GPIO1_IO03引腳復用和電氣屬性、設置GPIO方向和初始電平,最終跳轉到C語言`main`函數。
.global _start_start:ldr pc, =_reset_handlerldr pc, =_undefine_handlerldr pc, =_svc_handlerldr pc, =_prefetch_abort_handlerldr pc, =_data_abort_handlerldr pc, =_reserved_handlerldr pc, =_irq_handlerldr pc, =_fiq_handler_undefine_handler:ldr pc, =_undefine_handler_svc_handler:ldr pc, = _svc_handler_prefetch_abort_handler:ldr pc, =_prefetch_abort_handler_data_abort_handler:ldr pc, =_data_abort_handler_reserved_handler:ldr pc, =_reserved_handler_irq_handler:ldr pc, =_irq_handler_fiq_handler:ldr pc, =_fiq_handler_reset_handler:mrs r0, cpsrbic r0, r0, #0x1Forr r0, r0, #0x12 // irq 模式msr cpsr, r0ldr sp, =0x86000000mrs r0, cpsrbic r0, r0, #0x1Forr r0, r0, #0x1F // sys 模式msr cpsr, r0ldr sp, =0x84000000bl _bss_clearb main_bss_clear:ldr r0, = __bss_startldr r2, = __bss_end
loop:mov r1, #0str r1, [r0]add r0, r0, #4cmp r0, r2blt loopbx lrfinished:b finished
說明:代碼中寄存器地址與配置邏輯參考`imx6ull裸機(v1.2).pdf`中GPIO配置流程(使能時鐘→復用配置→電氣屬性→方向/電平設置)。
?2.2 C語言功能代碼
2.2.1 頭文件(led.h)
?聲明LED控制函數,依賴NXP SDK的寄存器定義(如`MCIMX6Y2.h`):
#ifndef _LED_H_#define _LED_H_#include "MCIMX6Y2.h"/* LED初始化函數:配置GPIO1_IO03 */void init_led(void);/* LED點亮:GPIO1_IO03輸出低電平 */void led_on(void);/* LED熄滅:GPIO1_IO03輸出高電平 */void led_off(void);/* LED翻轉:GPIO1_IO03電平取反 */void led_nor(void);#endif
?2.2.2 LED功能實現(led.c)
封裝GPIO配置與LED控制邏輯,調用`fsl_iomuxc.h`中的IO復用函數:
#include "led.h"
#include "fsl_iomuxc.h"void init_led(void) {/* 1. 配置GPIO1_IO03復用為GPIO */IOMUXC_SetPinMux(IOMUXC_GPIO1_IO03_GPIO1_IO03, 0);/* 2. 配置電氣屬性:關閉HYS、上拉、200M速度 */IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO03_GPIO1_IO03, 0x10B0);/* 3. 設置為輸出模式 */GPIO1->GDIR |= (1 << 3);}void led_on(void) {GPIO1->DR &= ~(1 << 3); ?/* 低電平點亮 */}void led_off(void) {GPIO1->DR |= (1 << 3); ??/* 高電平熄滅 */}void led_nor(void) {GPIO1->DR ^= (1 << 3); ??/* 電平取反 */}
?說明:`IOMUXC_SetPinMux`和`IOMUXC_SetPinConfig`是SDK封裝的IO配置函數,用于簡化寄存器操作。
2.2.3 主函數(main.c)?
實現LED周期性閃爍(軟件延時):
#include "MCIMX6Y2.h"#include "led.h"/* 軟件延時函數:參數越大,延時越長 */void delay(unsigned int n)
{while(n--);}int main(void)
{/* 1. 使能所有外設時鐘 */CCM->CCGR0 = 0xFFFFFFFF;CCM->CCGR1 = 0xFFFFFFFF;CCM->CCGR2 = 0xFFFFFFFF;CCM->CCGR3 = 0xFFFFFFFF;CCM->CCGR4 = 0xFFFFFFFF;CCM->CCGR5 = 0xFFFFFFFF;CCM->CCGR6 = 0xFFFFFFFF;/* 2. 初始化LED */init_led();/* 3. 循環翻轉LED(周期約500ms) */while(1) {led_nor();delay(0xFFFFF);}return 0;}
三. 編譯配置(Makefile)?
編寫Makefile實現自動化編譯,避免手動輸入繁瑣命令,支持匯編、C文件的編譯與鏈接:?
target = ledcross_compiler = arm-linux-gnueabihf-cc = $(cross_compiler)gcc
ld = $(cross_compiler)ld
objcopy = $(cross_compiler)objcopy
objdump = $(cross_compiler)objdumpincdirs = bsp imx6ull
srcdirs = bsp projectinclude = $(patsubst %, -I%, $(incdirs)) cfiles = $(foreach dir, $(srcdirs), $(wildcard $(dir)/*.c))
sfiles = $(foreach dir, $(srcdirs), $(wildcard $(dir)/*.S)) cfilenodir = $(notdir $(cfiles))
sfilenodir = $(notdir $(sfiles))cobjs = $(patsubst %, obj/%, $(cfilenodir:.c=.o))
sobjs = $(patsubst %, obj/%, $(sfilenodir:.S=.o))objs = $(cobjs) $(sobjs)VPATH = $(srcdirs)$(target).bin : $(objs)$(ld) -Timx6ull.lds -o$(target).elf $^$(objcopy) -O binary -S -g $(target).elf $@$(objdump) -D $(target).elf > $(target).dis$(sobjs) : obj/%.o : %.S@mkdir -p obj$(cc) -Wall -nostdlib -c $(include) -o $@ $< $(cobjs) : obj/%.o : %.c@mkdir -p obj $(cc) -Wall -nostdlib -c $(include) -o $@ $<.PHONY : clean
clean:rm -rf $(objs) $(target).elf $(target).bin $(target).dis
說明: - 鏈接地址`0x87800000`:選擇DDR中的地址,與Uboot鏈接地址一致,避免地址沖突;
- `-Ttext`:指定.text段(代碼段)的起始地址; - `objcopy -O binary`:將ELF格式文件轉換為裸機可執行的bin文件。
四. 程序編譯與燒寫
4.1 編譯步驟
1. 執行編譯
終端進入實驗目錄,執行`make`命令,編譯成功后生成`led.bin`(最終燒寫文件)。
4.2 程序燒寫(SD卡啟動)
IMX6ULL無內部Flash,需將程序燒寫到SD卡,通過SD卡啟動。
?4.2.1 準備工具與SD卡
1. 下載imxdownload工具?NXP提供的SD卡燒寫工具,拷貝到實驗目錄并添加執行權限: ``` chmod +x imxdownload ```
2. SD卡準備 - 使用空白SD卡(建議4GB以上),備份數據; - 通過讀卡器連接Ubuntu,確保SD卡被Ubuntu識別。
?4.2.2 確認SD卡設備名
終端執行`ls /dev/sd*`,識別SD卡設備文件:
- 未插SD卡時:顯示`/dev/sda /dev/sda1`(系統磁盤);
- 插入SD卡后:新增`/dev/sdb /dev/sdb1`(SD卡,`sdb`為設備名)。
注意:務必確認設備名為`/dev/sdb`,避免燒寫到系統磁盤(`sda`)。
?4.2.3 執行燒寫
在實驗目錄執行燒寫命令: ```./imxdownload led.bin /dev/sdb ``` -
**燒寫驗證**:終端顯示燒寫大小(如3.2KB)、速度(正常幾百KB/s以內);
- 生成`load.imx`文件:imxdownload在bin文件前添加啟動頭,適配IMX6ULL啟動協議。
五. 實驗驗證
5.1 開發板啟動配置
1. 設置BOOT撥碼開關??需將開發板BOOT撥碼開關設置為? SD卡啟動? ,參考撥碼表:
撥碼位 | 狀態 | 說明 |
1 | OFF | BOOT_MODE1=0 |
2 | ON | BOOT_MODE0=1 |
3~8 | OFF | 選擇 SD 卡通道 |
2. 連接硬件- 插入燒寫好程序的SD卡; - 打開開發板電源。
5.2 上電運行
打開開發板電源開關,觀察用戶LED(LED0):
- 正常現象:LED周期性閃爍(約1秒1次);
- 異常排查:若LED不亮,檢查BOOT撥碼、SD卡燒寫、GPIO配置是否正確。
?六. 常見問題排查
問題現象 | 可能原因 | 解決方案 |
交叉編譯工具鏈未找到(command not found) | 環境變量配置錯誤 | 重新執行source ~/.bashrc,或檢查~/.bashrc中工具鏈路徑 |
燒寫速度異常(>100MB/s) | SD 卡未被正確識別 | 重新插拔 SD 卡,重啟 Ubuntu 后重試 |
LED 不亮但燒寫成功 | GPIO 配置錯誤 / BOOT 撥碼錯誤 | 1. 檢查start.s中 GPIO1_IO03 的復用與電氣屬性; |
編譯報錯(undefined reference) | 源文件缺失或 Makefile 中未添加目標文件 | 1. 確認objs變量包含所有.o 文件; |