大家好,我是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.disclean: rm -rf *.o led.bin led.elf led.dis
最终编译效果:
总结:利用汇编控制底层硬件,是非常经典的实现方式,值得交流学习。
自动驾驶商业落地现状与未来发展前景
中国移动与诺基亚达成10亿欧元合作协议,能带领5G走向新发展吗?
小米Mix抢小米Note 2风头,这次黑科技终于不用被“黑”了
气体检测仪是如何校准的,步骤是怎样的
AL5524 IO如何扩展单片机的IO引脚数量
Linux系统中汇编语言来实现芯片外设的初始化
基于STM32的红外光通信装置的设计
LG化学和三星SDI关闭在美国的电池工厂
大多数人不知道共享单车里还有颗CPU
基于深度学习方法进行时序预测的调优方案
电动滑板DIY图解
存储巨头门槛被踏破 Meta、英伟达上门求货AI存力需求获印证
为什么会跳闸?家庭电路图结构详解
奇瑞估值18个月缩水近30% 未来将广泛布局新能源
吉利成为百度电动汽车公司的战略合作伙伴
可再生能源效率的电源集成
面向可穿戴医疗设备的仿真解决方案
LED室内照明的未来发展趋势分析
国产PLC哪个好
邬贺铨院士:2016年六大IT技术新亮点不容错过