先把驅動裝上
開發板的廠商給的網盤中有相應的驅動下載,對應的目錄爲 06-裸機程序實驗文檔以及工具文件這一文件夾。其實裏面只有兩個簡單的例程和一個簡單的教程。
官方提供了三個版本的驅動,分別是xp,win7 32位與win7 64位,我是在win10 x64環境下使用的,選擇win7 64位實測也是可以用的。安裝這個驅動要先把win10的驅動強制簽名先給關閉掉。
驅動的文件夾裏面有一個解決驅動簽名的小軟件,我一開始也是這樣操作的,重啓了一次纔想起來win10的驅動強制簽名未關閉,所以這一步不知道是不是必須的。
前面的步驟操作完之後,打開DNW這個軟件。
點擊Configuration->Options配置串口以及USB。
這個軟件也是有點歷史了,只能從COM1-4裏面選。到設備管理器裏查看自己是串口幾,如果不是1-4的話可以右鍵USB轉串口工具-屬性-端口設置選項卡->高級,將COM端口號改爲COM4以下,貌似這裏也要重啓才能生效。
以上都沒有問題之後,將板子的串口以及USB連上PC,DNW軟件中 點擊 Serial Port -> Connect,連接成功的話會在標題欄顯示串口號及波特率。
上電啓動板子,在uboot讀秒時輸入任意鍵進入uboot命令行。
輸入dnw使板子進入 DNW模式?
這時候可以在設備管理器中看到一個名爲 SEC S3C6400X Test B/D 的未知設備,手動將其驅動更新爲前面的 win7 64位的dnw驅動,驅動安裝成功後可以看到一個名爲iTOP-4412 dnw driver的設備。
下載裸機程序
這裏主要參照的就是板子所提供的那一份簡陋的文檔。
驅動安裝完成後,重啓開發板進入uboot命令行模式。
然後輸入dnw 40008000,(意思是啓動dnw 將程序下載到0x40008000的位置上)
然後點擊USB Port->Transmit->Transmit,選擇所提供的兩個例程中的任意一個的bin文件,這一次其實是設置路徑,並沒有直接將bin文件傳送至開發板。
再一次點擊USB Port->Transmit會發現下面多了剛纔選擇的路徑,點擊這個選項將這個bin文件傳送至開發板。正常的話顯示如下。
在命令行中輸入go 0x40008000,就是我們一開始設置的地址,可以看到板子上的LED交替閃爍。這個裸機程序就成功的跑起來了。
分析一波原理
以LED這裏例程爲例子,先查看底板的原理圖,可以看到LED2和LED3是分別接到了KP_COL0和VDD50_EN這兩根線上的,當這兩個IO爲高時,Q2開啓,LED被點亮。
再查看核心板的原理圖,在覈心板原理圖中分別搜索KP_COL0和VDD50_EN
可以得知KP_COL0實際對應的引腳爲GPL2_0,VDD50_EN實際對應的引腳爲GPK1_1。
在4412 SOC的數據手冊中搜索GPL2查看GPL2端口的寄存器。
GPK1的寄存器也是類似的。
繼續查看GPL2CON這個寄存器
接上圖
基地址爲0x11000000,偏移地址爲0x0100,這是一個32爲的寄存器。我們所用到的爲GPL2_0這個端口,所以只需要配置GPL2CON[0]這一位爲OUTPUT即可,其他位保持爲0。所以 GPL2CON = 0x1即可。
繼續查看GPL2DAT這個寄存器。GPL2DAT寄存器的基地址爲0x11000000,偏移地址爲0x0104。
根據描述,當端口被配置爲OUTPUT時,管腳的狀態與對應的位相同,那麼只需要將第0位配置爲高即可點亮GPL2_0端口對應的LED。即GPL2DAT=0x1 。
GPL2的其他寄存器暫時不需要處理。
另一個LED對應的IO GPK1_1也是一樣的配置方式。
GPK1CON= 0x10
GPK1DAT = 0x2
看一看源代碼
#define GPL2CON (*(volatile unsigned long *) 0x11000100) //GPL2控制寄存器地址
#define GPL2DAT (*(volatile unsigned long *) 0x11000104) //GPL2數據寄存器地址
#define GPK1CON (*(volatile unsigned long *) 0x11000060) //GPK1控制寄存器地址
#define GPK1DAT (*(volatile unsigned long *) 0x11000064) //GPK1數據寄存器地址
//GPL2_0, GPK1_1
void delay(int r0) //一個簡單的延時函數
{
volatile int count = r0;
while (count--)
;
}
void led_blink()
{
GPL2CON = 0x00000001; //將GPL2CON的 bit 1 置爲 1,即GPL2CON[0] = OUTPUT
GPK1CON = 0x00000010; //將GPK1CON的 bit 4 置爲 1,即GPK1CON[1] = OUTPUT
while(1)
{
GPL2DAT = 1; //將GPL2DAT的 bit 0 置 1,其餘位置0
GPK1DAT = 0; //GPK1DAT 置 0
delay(0x80000);
GPL2DAT = 0; //GPL2DAT 置 0
GPK1DAT = 0x2; //將GPK1DAT的 bit 1 置 1,其餘位置0
delay(0x80000);
}
}
這是自帶例程中的led.c文件,首先定義了寄存器的地址,然後將相應的值寫入寄存器中即可。
再看makefile文件
led.bin: start.o led.o
arm-none-linux-gnueabi-ld -Ttext 0x0 -o led.elf $^
arm-none-linux-gnueabi-objcopy -O binary led.elf led.bin
arm-none-linux-gnueabi-objdump -D led.elf > led_elf.dis
%.o : %.S
arm-none-linux-gnueabi-gcc -o $@ $< -c -nostdlib
%.o : %.c
arm-none-linux-gnueabi-gcc -o $@ $< -c -nostdlib
clean:
rm *.o *.elf *.bin *.dis -f
裏面只是多條指令的合集,方便我們執行編譯操作。
嘗試編譯一下
把工程拷到ubuntu裏,直接在工程路徑文件夾執行make即可。
下方的終端裏顯示了編譯的過程
arm-none-linux-gnueabi-gcc -o led.o led.c -c -nostdlib
arm-none-linux-gnueabi-ld -Ttext 0x0 -o led.elf start.o led.o
arm-none-linux-gnueabi-objcopy -O binary led.elf led.bin
arm-none-linux-gnueabi-objdump -D led.elf > led_elf.dis
如果要對其他的IO進行操作 基本上都是一樣的套路