Linux系统中使用汇编初始化外设方法

简介: 大家好,我是ST。 今天主要和大家聊一聊,如何使用汇编语言来实现芯片外设的初始化功能。

2315c00bc3264b678cfa569dbb9159fd.png

第一步:硬件原理分析

    观察开发板的原理图,可以知道,如下图所示:8f8d1a79a008966e49135a4d247532e0.png

 从原理图中可知,硬件时接到了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。

33e0a379bd087c6d438930c74716770a.png

 实验中需要将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

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

最终编译效果:

170e17ade5610ec4618ea89f0e522d20.png

总结:利用汇编控制底层硬件,是非常经典的实现方式,值得交流学习。

目录
相关文章
|
7天前
|
存储 缓存 监控
Linux缓存管理:如何安全地清理系统缓存
在Linux系统中,内存管理至关重要。本文详细介绍了如何安全地清理系统缓存,特别是通过使用`/proc/sys/vm/drop_caches`接口。内容包括清理缓存的原因、步骤、注意事项和最佳实践,帮助你在必要时优化系统性能。
121 78
|
11天前
|
Linux Shell 网络安全
Kali Linux系统Metasploit框架利用 HTA 文件进行渗透测试实验
本指南介绍如何利用 HTA 文件和 Metasploit 框架进行渗透测试。通过创建反向 shell、生成 HTA 文件、设置 HTTP 服务器和发送文件,最终实现对目标系统的控制。适用于教育目的,需合法授权。
45 9
Kali Linux系统Metasploit框架利用 HTA 文件进行渗透测试实验
|
7天前
|
存储 监控 Linux
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
57 13
|
1月前
|
Ubuntu Linux 网络安全
linux系统ubuntu中在命令行中打开图形界面的文件夹
在Ubuntu系统中,通过命令行打开图形界面的文件夹是一个高效且实用的操作。无论是使用Nautilus、Dolphin还是Thunar,都可以根据具体桌面环境选择合适的文件管理器。通过上述命令和方法,可以简化日常工作,提高效率。同时,解决权限问题和图形界面问题也能确保操作的顺利进行。掌握这些技巧,可以使Linux操作更加便捷和灵活。
32 3
|
8天前
|
Ubuntu Linux C++
Win10系统上直接使用linux子系统教程(仅需五步!超简单,快速上手)
本文介绍了如何在Windows 10上安装并使用Linux子系统。首先,通过应用商店安装Windows Terminal和Linux系统(如Ubuntu)。接着,在控制面板中启用“适用于Linux的Windows子系统”并重启电脑。最后,在Windows Terminal中选择安装的Linux系统即可开始使用。文中还提供了注意事项和进一步配置的链接。
26 0
|
1月前
|
Linux
在 Linux 系统中,`find` 命令
在 Linux 系统中,`find` 命令
37 1
|
19天前
|
存储 Oracle 安全
服务器数据恢复—LINUX系统删除/格式化的数据恢复流程
Linux操作系统是世界上流行的操作系统之一,被广泛用于服务器、个人电脑、移动设备和嵌入式系统。Linux系统下数据被误删除或者误格式化的问题非常普遍。下面北亚企安数据恢复工程师简单聊一下基于linux的文件系统(EXT2/EXT3/EXT4/Reiserfs/Xfs) 下删除或者格式化的数据恢复流程和可行性。
|
7月前
|
存储 Unix 编译器
汇编语言----X86汇编指令
汇编语言----X86汇编指令
292 2
|
2月前
|
存储 移动开发 C语言
【ARM汇编速成】零基础入门汇编语言之指令集(三)
【ARM汇编速成】零基础入门汇编语言之指令集(三)
|
2月前
|
编译器 C语言 计算机视觉
【ARM汇编速成】零基础入门汇编语言之指令集(二)
【ARM汇编速成】零基础入门汇编语言之指令集(二)
249 0