實驗一:OK6410開發之點亮LED
一、實驗目的
1. 掌握開發板Linux的燒錄過程,感受與單片機燒錄程序的不同
2. 熟悉Linux開發環境,學習Linux系統指令
3.從初步的點燈開始對ARM底層編寫進行更深入了解
二、實驗設備
開發機環境 操作系統:ubuntu 20.04
交叉編譯環境:arm-linux-gcc 4.3.2 6410
板子內核源碼:linux-3.0.1
目標板環境:OK6410-A linux-3.0.1
編譯驅動之前要先在 ubuntu 下編譯開發板的內核,這里用的內核版本是 linux-3.0.1 如何編譯內核,具體見上一篇實驗內容:
三、實驗內容(原理)
1. 通過SD卡一鍵燒錄Linux到OK6410開發板上
SW2引腳號 | Pin 8 | Pin 7 | Pin 8 | Pin 8 | Pin 8 | Pin 8 | Pin 2 | Pin 1 |
---|---|---|---|---|---|---|---|---|
引腳定義 | SELNAND | OM4 | OM3 | OM2 | OM1 | GPN15 | GPN14 | GPN13 |
Nandflash 啟動 | 1 | 0 | 0 | 1 | 1 | x | x | x |
SD卡啟動 | x | 1 | 1 | 1 | 1 | 0 | 0 | 0 |
注:
(1)SW2開關ON時為”1”;OFF時為”0”,”X”為高電平或者低電平
(2)OK6410開發板出廠默認設置為NAND FLASH啟動方式
從這里我們可以知道如何進行SD卡啟動進行燒錄。
2. 在Linux上編寫LED驅動文件,Makefile文件,測試文件並拷貝到開發板上進行測試運行
2.1 硬件部分:
我們先看硬件電路:
3.3v已經硬件接在PN結正極,輸出端接負極。說明當輸出端輸出低電平時LED即可導通被點亮。以下是對應引腳:
LED1 -GPM0
LED2 -GPM1
LED3 -GPM2
LED4 -GPM3
2.2 寄存器部分
我們看ARM芯片手冊,注意操作哪些寄存器可以完成LED的點亮,這里主要關注的就是芯片的GPIO章節,具體關注的就是怎么操作GPM0-GPM3 四個引腳,先來截一個圖,清楚的看到GPM的三個寄存器:控制寄存器、數據寄存器、上拉下拉寄存器,此外還給出的寄存器的地址和初始值,這里重點關注下配置寄存器和數據寄存器的地址,等下我們要通過這個地址來操作。
接下來再看下GPMCON寄存器中的每一位的作用,這里只截取了GPM0-GPM3,從下表中可以看出GPMCON寄存器的每四位對應一個GPM引腳的狀態,當設置為0000時為輸入模式,當設置為0001時為輸出模式……………其余的暫時不管。這里很明顯我們需要設置為輸出模式。
接着就是GPMDAT寄存器,這里描述的很清楚,當端口被配置為輸入模式時,我們可以直接從端口引腳獨處相應的狀態,當端口被配置為輸出模式時,端口引腳的狀態就會根據我們是定的值而發生改變,這里我們肯定是要GPM0-GPM3都輸出低電平。
看完這些我們就基本知道點燈的基本步驟了,后面程序會體現:
步驟1:
配置GPMCON寄存器為0x0001使LED0引腳為輸出模式(0x1111就是四個LED引腳為輸出模式)
步驟2:
配置GPMDAT寄存器位為0x0U輸出低電平使LED導通點亮
四、實驗步驟
1.SD卡一鍵Linux燒錄開發板
1.1 准備文件
准備好上一個實驗配置好的文件:
mmc.bin (/root/forlinx/uboot1.1.6)
uboot.bin (/root/forlinx/uboot1.1.6)
zImage (/root/forlinx/linux-3.0.1/arch/arm/boot)
mkyaffs2image-nand2g (/root/forlinx)
1.2 制作SD系統卡
首先格式化SD卡
然后以管理員身份運行SD_Writer軟件,正常情況下應該是這樣的:
我一開始沒有Format這個選項,后面查了下發現需要右鍵屬性在兼容性里勾上這個“以兼容模式運行這個程序”
點擊"Scan"軟件會自動掃描SD卡位置,我的是H。"SD_Type"選擇"Auto","OS_Type"選“Linux||Android”。
最后點擊"Select Boot",把制作好的"mmc.bin"放進去,點擊"Program"。出現"It's OK"就說明系統卡制作完成。
Quit退出。
1.3 燒錄Linux到開發板上
將准備好的四個文件(其實三個就行,mmc.bin已經不需要了)拷貝到SD上
將SD卡插到開發板SD卡槽里,撥碼開關撥成0x1f,打開電源,可以看到四盞LED均被點亮,系統正在燒錄。

燒錄完成后的界面如下:

此時會出現蜂鳴器響和流水燈提示燒錄完成,有些板子蜂鳴器壞了可能不會響。
關閉電源,將撥碼開關撥成0x19,重啟就可以看到系統已經在板子上運行了。

2. LED程序編寫
2.1 driver_led.c 驅動文件編寫
主要是如實驗原理說的GPMCON寄存器與GPMDAT寄存器的配置
2.1.1 GPMCON寄存器配置
//GPMCON寄存器配置
unsigned tmp;
tmp = readl(S3C64XX_GPMCON);
tmp = (tmp & ~(0x7U<<1))|(0x1U);
writel(tmp, S3C64XX_GPMCON);
先讀取GPMCON寄存器的值,將tmp變成0x01再寫到GPMCON寄存器上,使LED0的GPM端為輸出模式。
2.1.2 GPMDAT寄存器配置
//GPMDAT寄存器
void Led_on(unsigned LEDx)?
{
unsigned tmp;
tmp = readl(S3C64XX_GPMDAT);
tmp &=~ (LEDx);
writel(tmp,S3C64XX_GPMDAT);
}
void Led_off(unsigned LEDx)
{
unsigned tmp;
tmp = readl(S3C64XX_GPMDAT);
tmp |= (LEDx);
writel(tmp,S3C64XX_GPMDAT);
}
也是一樣,先讀取GPMDAT寄存器的值,將tmp變成設置值再寫到GPMDAT寄存器上。
這里我寫了開關函數控制led開關。
2.1.3 led_write函數
//led_write函數
ssize_t led_write (struct file *filp, const char __user *buf, size_t count,loff_t *f_pos)
{
char wbuf[10];
printk("#########write######\n");
copy_from_user(wbuf,buf,count);
switch(wbuf[0])
{
case 0:
Led_on(LED0);
break;
case 1:
Led_on(LED1);
break;
case 2:
Led_on(LED2);
break;
case 3:
Led_on(LED3);
break;
case 4:
Led_off(LED0);
break;
case 5:
Led_off(LED1);
break;
case 6:
Led_off(LED2);
break;
case 7:
Led_off(LED3);
break;
}
我這里是寫了一個流水燈,其實這里是一個類似於重載函數的函數,會重載這個源碼文件的write函數,下面test.c文件會體現。
2.2 test函數編寫
//輪詢函數
while(1)
{
for(i=0;i<8;++i)
{
write(fd,&buf[i],1);
sleep(1);
}
}
這里的write其實是之前驅動文件的led_write函數,會按順序實現led_write里流水燈的功能,copy_from_user(wbuf,buf,count);就是去打開文件重載。
2.3 Makefile文件編寫
這里不贅述了,主要關注這個:
KDIR := /root/forlinx/linux-3.0.1
這里是把驅動文件包含的意思,導入這里的驅動文件。
3. 編譯程序
Linux下打開自己寫的led程序位置
cd led
make
arm-linux-gcc test.c -o test
編譯好后大致這個樣子,我之前已經編譯過了,第一次的make會長一點。

4. 運行程序
將led程序make跟gcc編譯后所有文件拷貝到SD卡,再將SD卡插到開發板上。
打開開發板上的終端
然后在里面輸入
cd sdcard/ #打開SD卡文件夾
insmod driver_led.ko #加載驅動
mknod /dev/my_led c 240 0 #創建設備文件
./test #運行測試
我們就可以看到流水燈了。
五、實驗程序(包括流程圖)
5.1 流程圖

5.2 實驗代碼
具體實驗代碼文件見我的github:
六、實驗演示
6.1 點燈演示:

6.2 流水燈演示:
視頻我也在GitHub上傳了:
七、心得體會
此次實驗無論是從硬件驅動底層還是上位機系統管理都有了很深刻的學習,簡單的點燈讓我熟悉了Linux開發環境,簡單學習Linux系統指令,同時對ARM的底層有了學習,總之學到很多,收獲頗豐。