当前位置:   article > 正文

I.MX6U 学习笔记一------汇编LED驱动实验(GPIO寄存器配置,常用汇编指令,编译链接程序)_i.mx6ul gpio3 输出

i.mx6ul gpio3 输出

Cortex-A 汇编语言作用:

  1. 需要用汇编初始化一些SOC的外设。
  2. 使用汇编初始化DDR,I.MX6U不需要,其内部96K的ROM中存放了NXP自己编写的启动代码,这些启动代码可以读取DDR的配置信息,并完成DDR的初始化。
  3. 设置SP指针,一般指向DDR,设置好C语言运行环境。

I.MX6U IO端口初始化

IO介绍:I.MX6U 的 GPIO 一共有 5 组: GPIO1、 GPIO2、 GPIO3、 GPIO4 和 GPIO5, 其中 GPIO1 有 32 个 IO, GPIO2 有 22 个 IO, GPIO3 有 29 个 IO、 GPIO4 有 29 个 IO, GPIO5 最少,只有 12 个 IO,这样一共有 124 个 GPIO。

  1. 使能时钟 CCGR0 到 CCGR6 这7个寄存器控制着6ULL所有外设时钟的使能。可以一开始为了简单,直接都使能,就是都写为0xFFFFFFFF。
  2. IO复用,将寄存器IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 的bit 3-0设置为0101 = 5 ,这样GPIO1_IO03就复用为GPIO。(设置IO复用的寄存器和电气属性寄存器的区别是寄存器名称的第三个字段,MUX是设置复用,PAD是设置电气属性)
  3. 电气属性设置寄存器IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03
    下面简单说明了此寄存器的位含义,加粗的表示IO一般需要配置的。

SRE:压摆率,作为高速通信的话IO要配置高压摆率,上升和下降沿越陡。自己理解的与Speed的区别是,压摆率是控制上升和下降时间,Speed控制IO响应翻转的速度。
DSE:当IO用作输出的时候用来设置IO的驱动能力,000驱动关闭
SPEED:设置IO速度
ODE:控制开启和关闭开漏输出
PKE:上拉保持
PUS:设置上拉和下拉

  1. 配置GPIO功能,设置输入输出。设置GPIO1_GDIR寄存器bit3 为1,设置GPIO1_IO03为输出。设置GPIO1_DR寄存器的bit3为1表示输出为高电平。

GPIO1_DR:电平控制寄存器,可以读引脚电平和写引脚电平。GPIO1- GPIO5
GPIO1_GDIR:方向控制,需要与DR寄存器配合使用,一个bit代表一个位。GPIO1- GPIO5
GPIO1_PSR:只读状态寄存器。
GPIO1_ICR1:中断配置寄存器,边缘触发和跳边沿触发,一组ICR寄存器最多配置16个IO,一组GPIO最多有32个IO,因此需要两个ICR,也就是ICR1和ICR2。
GPIO_ISR:中断状态寄存器,判断中断有没有发生

汇编指令

为什么要用汇编:芯片一上电还没有准备好C语言运行环境,需要用汇编准备好堆栈(C语言跳转函数时需要的堆栈保护现场),SP栈指针等C语言运行环境。设置SP指针指向一段地址。

存储器访问指令RAM

ARM处理器不能直接读取RAM寄存器里的数据,必须借助通用寄存器R0-R15
Cortex-A寄存器组(内核寄存器组,不是外设寄存器),ARM架构提供了16个32位的通用寄存器供软件使用,前15个可以用做通用的数据存储,最后一个是程序计数器PC,用来保存将要执行的指令。一般用R0-R7。9种运行模式,每一种都有一组与之对应的寄存器组。

LDR:从RAM里面读数据

LDR	R0, =  0x0209c004     @将寄存器地址加载到R0中,即R0=0x0209c004
LDR	R1,	[R0]              @读取地址 0X0209C004 中的数据到 R1 寄存器中
  • 1
  • 2

STR:从RAM里面读数据

LDR R0, =0X0209C004 @将寄存器地址 0X0209C004 加载到 R0 中,即 R0=0X0209C004
LDR R1, =0X20000002 @R1 保存要写入到寄存器的值,即 R1=0X20000002
STR R1, [R0] @将 R1 中的值写入到 R0 中所保存的地址中
  • 1
  • 2
  • 3

驱动编写

  • 新建工程文件夹,新建 .s 文件,打开所有时钟,寻找时钟寄存器的地址,写入数据。

  • 配置IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 = 0x05

  • 配置IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03 = 0x10b0

  • 配置GPIO功能 引脚复用、电气属性、输出、低电平

编译程序

  1. 将 .c .s 文件变为.o ,用gcc,命令arm-linux-gnueabihf-gcc -g -c led.s -o led.o
  2. 将所有的 .o 文件链接为 elf 格式的可执行文件,命令arm-linux-gnueabihf-ld -Ttext 0x87800000 led.o -o led.elf
  3. 将 elf 文件转为 bin 文件,命令arm-linux-gnueabihf-objcopy -O binary -g -S led.elf led.bin
  4. 将 elf 文件转为汇编,反汇编操作,命令arm-linux-gnueabihf-objdump -D led.elf > led.dis

链接:就是将所有的.o文件链接在一起,并且链接到指定的地方,本实验链接的时候要指定链接起始地址。链接起始地址就是代码运行的起始地址。
对于6ull来说,链接起始地址应该指向RAM地址。RAM分为内部RAM(128K 0x900000-0x91FFFF)和外部RAM,也就是DDR。6ull的内部RAM地址范围0x900000-0x91FFFF。也可以放到外部DDR中,对于512MB字节DDR核心板,DDR范围就是0x80000000-0x9FFFFFFF。对于256MB的DDR来说就是0x80000000-0x8FFFFFFF。
bin文件不能直接烧写到SD卡、EMMC、NAND等外置存储中,然后从这些外置存储中运行,使用JLINK将bin文件直接下载到内部RAM中还是可以运行的。
对于将bin文件直接烧写到SD卡中是不能运行的,需要添加一个头部,这个头部信息包含了DDR的初始化参数。
I.MX系列SOC内部boot rom会从SD卡,EMMC等外置存储中读取头部信息,然后初始化DDR,并且将bin文件拷贝到指定的地方(链接其实地址)。bin文件运行地址一定要和链接起始地址一致。位置无关代码除外。
链接起始地址选择0x87800000

烧写bin文件

6ULL支持SD卡,EMMC,NAND,等等位置启动。裸机例程烧写到SD卡中启动。
烧写bin文件到SD卡,是将bin文件烧写到SD卡绝对地址上。对于I.MX而言,需要在bin文件前面添加 头部。需要借助imxdownload软件,将该软件复制到工程目录。
检查SD卡指令:ls /dev/sd* -l
给与imxdownload软件可执行权限:chmod 777 imxdownload
烧写bin文件命令:./imxdownload led.bin /dev/sdf
imxdownload软件会在.bin文件中添加头部,然后生成新的 .imx 文件,然后将 .imx 文件烧写到SD中。
6ULL支持JTAG,因为没有烧写算法,所以无法烧写,但是可以通过JTAG将bin文件烧写到内部RAM中。更但是6ULL的JTAG口和SAI复用,SAI连接了WM8960音频DAC。

编写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  //elf转bin文件
	arm-linux-gnueabihf-objdump -D led.elf > led.dis   //反汇编

clean:
	rm -rf *.o led.bin led.elf led.dis
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/385609
推荐阅读
相关标签
  

闽ICP备14008679号