0%

Linux驱动学习日记(1) 汇编点亮一颗LED

原理分析

原理图分析

  根据原理图可以得知,连接板子LED灯珠的是GPIO1_3,当GPIO1_3输出低电平时LED被点亮。

初始化步骤

① 使能时钟(CCM模块),CCM_CCGR0到CCM_CCGR6七个寄存器控制了所有的外设时钟,查询数据手册得知CCGR1的27-26位控制了GPIO1外设的时钟

图 1 CCRG1
  在CCGR寄存器中,每两位控制了某种外设的时钟模式。
  • 00 关闭外设时钟。
  • 01 只在正常运行有时钟。
  • 10 保留不用。
  • 11 正常使用时钟
图 2 表格
  为了简单,我们将CCGR0-CCGR6七个寄存器全部写入0xFFFFFFFF,相当于使能所有的时钟。

② IO复用寄存器IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03

图 3 GPIO复用寄存器
这个寄存器的BIT3-0控制了GPIO1_IO03的功能,将其设置为5(即0101),这样GPIO1_IO03就复用为GPIO功能了。

③ 配置电气属性。IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03寄存器是设置GPIO1_3的电气属性的。重点设置压摆率、速度、驱动能力、开漏、上下拉

1
2
3
4
5
6
7
HSE     bit16       使能迟滞比较器
PUS bit15:14 上拉下拉电阻设置
PKE bit12 上拉、状态保存器开关
ODE bit11 开漏开关
SPEED bit7:6 00 50M,01 10 100M,11 200M
DSE bit5:3 设置IO口驱动能力(数值越大,驱动能力越强)
SRE bit0 设置IO口压摆率
图 4 GPIO_PIN配置寄存器
④ 配置GPIO功能,设置输入输出。设置GPIO_GDIR寄存器bit3为1(输出模式),设置GPIO1_DR寄存器bit3为0,输出低电平。
图 5 GPIO_DR配置寄存器
  当GPIO初始化为GPIO输出时,GPIOx_DR[pin]是你上次写入的值。当GPIO初始化为输入时,GPIOx_DR[pin]是引脚当前的实际电平。
图 6 GPIO_GDIR配置寄存器
  GPIOx_GDIR[pin]控制了gpio每一位的输入或输出。

汇编程序编写

  根据上面的步骤依次编写汇编代码,寄存器地址在数据手册中查询。
  ① 使能时钟模块

1
2
3
LDR R0, =0X020C406C 
LDR R1, =0XFFFFFFFF
STR R1,[R0]

  ② 复用IO口

1
2
3
LDR R0, =0X020E0068
LDR R1, =0X5
STR R1,[R0]

  ③ 配置电气属性

1
2
3
LDR R0, =0X020E02F4
LDR R1, =0X000010B0
STR R1,[R0]

  ④ 配置GPIO模块为输出模式,并设置为低电平

1
2
3
4
5
6
7
LDR R0, =0X0209C004
LDR R1, =0X0000008
STR R1,[R0]

LDR R0, =0X0209C000
LDR R1, =0
STR R1,[R0]

  最终代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
.GLOBAL _start
_start:
LDR R0, =0X020C406C
LDR R1, =0XFFFFFFFF
STR R1,[R0]

LDR R0, =0X020E0068
LDR R1, =0X5
STR R1,[R0]

LDR R0, =0X020E02F4
LDR R1, =0X000010B0
STR R1,[R0]

LDR R0, =0X0209C004
LDR R1, =0X0000008
STR R1,[R0]

LDR R0, =0X0209C000
LDR R1, =0
STR R1,[R0]

LOOP:
B LOOP

编译及运行

编译

① 使用arm-linux-gnueabihf-gcc将.c .s文件编译为.o

1
arm-linux-gnueabihf-gcc -g -c led.s -o led.o

② 将所有的.o文件链接为elf格式的可执行文件,本实验链接的时候要指定链接起始地址,起始地址是指代码运行的起始地址。对于6ULL来说,链接起始地址应该指向RAM地址。RAM分为内部RAM和外部RAM,也就是DDR。6ULL内部RAM地址范围0X9000000-0X91FFFF,也可以在外部的 DDR 中。本教程所有裸机例程的链接地址都在 DDR 中,链接起始地址为 0X87800000。

1
arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf

③ 将elf文件转为bin文件,对于I.MX来说,bin文件不能直接运行,需要添加一个头部信息,这个头部信息包含了DDR的初始化参数,I.MX系列SOC内部boot rom会从SD卡、EMMC等外部存储中读取头部信息并初始化DDR,并且将bin文件拷贝到指定地方(链接起始地址),BIN的运行地址一定要和链接起始地址一致,位置无关代码除外。

1
arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin

④ 将elf文件转为汇编(反汇编)

烧写到SD卡

1
./imxdownload <.bin file> <SD Card>

运行结果

图 7 点亮