? ?大家好,我是ST。
? ?今天主要和大家聊一聊,如何使用匯編語言來實現芯片外設的初始化功能。
第一步:硬件原理分析
? ? ?觀察開發板的原理圖,可以知道,如下圖所示:
? ? ? 從原理圖中可知,硬件時接到了GPIO1_IO03的引腳輸出低電平(0)的時候發光二極管LED0就會導通點亮,當GPIO1_IO03輸出高電平(1)的時候發光二極管LED0不會導通,因此LED0就不會亮。
第二:實驗程序編寫方法
1、使能GPIO1時鐘
? ? ?GPIO1的時鐘由CCM_CCGR1的bit27和bit26這兩個位控制,將這兩個位設置為11即可。
2、設置GPIO1_IO03的復用功能
? ? ?找到GPIO1_IO03的復用寄存器“IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03”的地址為0X020E0068,然后設置此寄存器,將GPIO1_IO03這個IO復用為GPIO功能,也就是ALT5。
3、配置GPIO1_IO03
? ? ?找到GPIO1_IO03的配置寄存器“IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03”的地址為0X020E02F4,根據實際情況,配置此寄存器。
4、設置GPIO
? ? ? 將GPIO1_IO03復用為GPIO功能,所以我們需要配置GPIO。
? ? ? ? 實驗中需要將GPIO1_IO03作為輸出功能的,因此GPIO1_GDIR的bit3要設置為1,表示輸出。
5、控制GPIO的輸出電平
? ? ?經過前面的步驟,GPIO1_IO03已經配置好了,只需要向GPIO1_DR寄存器的bit3寫入0即可控制GPIO1_IO03輸出低電平,打開 LED,向 bit3 寫入 1 可控制 GPIO1_IO03 輸出高電平,關閉 LED。
第三:匯編代碼具體實現
?
.global _start /* 全局標號 */ ? ?/* ?*?描述:?_start 函數,程序從此函數開始執行此函數完成時鐘使能、 ?* GPIO 初始化、最終控制 GPIO 輸出低電平來點亮 LED 燈。 ?*/ ?_start: ?/*?例程代碼?*/ ?/*?1、使能所有時鐘?*/ ?ldr?r0,?=0X020C4068?/*?寄存器?CCGR0?*/ ldr r1, =0XFFFFFFFF str r1, [r0] ldr r0, =0X020C406C /* 寄存器 CCGR1 */ str r1, [r0] ldr r0, =0X020C4070 /* 寄存器 CCGR2 */ str r1, [r0] ?ldr?r0,?=0X020C4074?/*?寄存器?CCGR3?*/ ?str?r1,?[r0] ldr r0, =0X020C4078 /* 寄存器 CCGR4 */ ?str?r1,?[r0]? ?ldr?r0,?=0X020C407C?/*?寄存器?CCGR5?*/ ?str?r1,?[r0] ? ?ldr?r0,?=0X020C4080?/*?寄存器?CCGR6?*/ ?str?r1,?[r0] ? ?/*?2、設置?GPIO1_IO03?復用為?GPIO1_IO03?*/ ?ldr?r0,?=0X020E0068?/*?將寄存器?SW_MUX_GPIO1_IO03_BASE?加載到?r0?中?*/ ?ldr?r1,?=0X5?/*?設置寄存器?SW_MUX_GPIO1_IO03_BASE?的?MUX_MODE?為?5?*/ str r1,[r0] ?/*?3、配置?GPIO1_IO03?的?IO?屬性? ?*bit?16:0?HYS?關閉 ?*bit?[15:14]:?00?默認下拉 ?*bit?[13]:?0?kepper?功能 ?*bit?[12]:?1?pull/keeper?使能 ?*bit?[11]:?0?關閉開路輸出 ?*bit?[7:6]:?10?速度?100Mhz ?*bit?[5:3]:?110?R0/6?驅動能力 ?*bit?[0]:?0?低轉換率 ?*/ ?ldr?r0,?=0X020E02F4?/*寄存器?SW_PAD_GPIO1_IO03_BASE?*/ ?ldr?r1,?=0X10B0 ?str?r1,[r0] ?/*?4、設置?GPIO1_IO03?為輸出?*/ ?ldr?r0,?=0X0209C004?/*寄存器?GPIO1_GDIR?*/ ldr r1, =0X0000008 ?str?r1,[r0] ?/*?5、打開?LED0 ?*?設置?GPIO1_IO03?輸出低電平 */ ?ldr?r0,?=0X0209C000?/*寄存器?GPIO1_DR?*/ ?ldr?r1,?=0? ?str?r1,[r0] ?/* ?*?描述: loop 死循環 ?*/ ?loop: ?b?loop
?
? ? 分析:第一行定義了一個全局標號_start,代碼就是從_start這個標號開始順序往下執行的。使用ldr 指令向寄存器 r0 寫入 0X020C4068,也就是 r0=0X020C4068,這個是CCM_CCGR0 寄存器的地址。使用 ldr 指令向寄存器 r1 寫入 0XFFFFFFFF,也就是 r1=0XFFFFFFFF。因為我們要開啟所有的外設時鐘。使用 str 將 r1 中的值寫入到 r0 所保存的地址中去,也就是給 0X020C4068 這個地址寫入 0XFFFFFFFF,相當于 CCM_CCGR0=0XFFFFFFFF,就是打開 CCM_CCGR0 寄存器所控制的所有外設時鐘。向 CCM_CCGRX(X=1~6)寄存器寫入 0XFFFFFFFF。這樣我就通過匯編代碼使能了芯片的所有外設時鐘。設置GPIO1_IO03的復用功能,GPIO1_IO03的復用寄存器地址為0X020E0068,寄 存 器 IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 的 MUX_MODE 設置為 5 就 是 將GPIO1_IO03 設置為 GPIO。設 置 GPIO1_IO03的 配 置 寄 存 器 , 也 就 是 寄 存 器IOMUX_SW_PAD_CTL_PAD_GPIO1_IO03 的值,此寄存器地址為 0X020E02F4,代碼里面已經給出了這個寄存器詳細的位設置。設置 GPIO1->GDIR 寄存器,將 GPIO1_IO03 設置為輸出模式,也就是寄存器的 GPIO1_GDIR 的 bit3 置 1。設置 GPIO1->DR 寄存器,也就是設置 GPIO1_IO03 的輸出,我們要點亮開發板上的 LED0,那么 GPIO1_IO03 就必須輸出低電平,所以這里設置 GPIO1_DR 寄存器為 0。
第四:編譯與下載
? ??1、arm-linux-gnueabihf-gcc 編譯文件
? 編譯出在 ARM 開發板上運行的可執行文件,需要使用到對應的交叉編譯工具。
?
arm-linux-gnueabihf-gcc -g -c led.s -o led.o
?
? ? 2、arm-linux-gnueabihf-ld 鏈接文件
? ? ? ? arm-linux-gnueabihf-ld 用來將眾多的.o 文件鏈接到一個指定的鏈接位置。可以使用 arm-linux-gnueabihf-ld 來將前面編譯出來的 led.o 文件鏈接到 0X87800000 這個地址,使用如下命令:
?
arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf
?
??led.elf 文件也不是我們最終燒寫到 SD 卡中的可執行文件,我們要燒寫的.bin 文件,因此還需要將 led.elf 文件轉換為.bin 文件,這里我們就需要用到 arm-linux-gnueabihf-objcopy 這個工具了。
3、arm-linux-gnueabihf-objcopy 格式轉換
? ?? arm-linux-gnueabihf-objcopy 更像一個格式轉換工具,我們需要用它將 led.elf 文件轉換為led.bin 文件,命令如下:
?
arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin
?
上述命令中,“-O”選項指定以什么格式輸出,后面的“binary”表示以二進制格式輸出,選項“-S”表示不要復制源文件中的重定位信息和符號信息,“-g”表示不復制源文件中的調試信息。
4、arm-linux-gnueabihf-objdump 反匯編
? ? ?C 語言寫試驗例程的,有時候需要查看其匯編代碼來調試代碼,因此就需要進行反匯編,一般可以將 elf 文件反匯編,比如如下命令:
?
arm-linux-gnueabihf-objdump -D led.elf > led.dis
?
第五:創建Makefile文件
? ? ?為了方便,使用命令進行編譯,可以把對應的編譯命令放到Makefile文件中。
?
led.bin:led.s arm-linux-gnueabihf-gcc -g -c led.s -o led.o arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin arm-linux-gnueabihf-objdump -D led.elf > led.dis clean: rm -rf *.o led.bin led.elf led.dis
?
最終編譯效果:
總結:利用匯編控制底層硬件,是非常經典的實現方式,值得交流學習。
審核編輯:湯梓紅
?
評論
查看更多