文章目录
裸机驱动的开发步骤
看电路图
a. 找到我要控制的设备
b. 找到设备在CPU侧的控制管脚(如GPX2_7)
看芯片手册 (先看相关的中文文档,熟悉设备,再看手册)
b. 看目录找到对应的控制模块(如:6 General Purpose Input/Output (GPIO) Control)
c. 看该模块的overview 了解该模块的大概功能
d. 看控制寄存器(REGISTER DESCRIPTION) 重点,难点
注: 如果寄存器比较多什么办?
看技术支持提供的例子程序, 找到需要修改的寄存器(常常只有几个)。
部分厂商会提供配置软件,通过界面去配置功能, 我们只需使用配置好的寄存器值就可以了
编程
b. 设备初始化 (如设置GPIO为输出状态)
c. 把功能分成最基本的小块,逐个实现 如点亮灯-> 在灭灯-> 加延时->闪烁-> 跑马灯
编写LED灯闪烁的ARM裸机汇编代码
查看LED硬件电路
查看I/O口
查看芯片手册
代码
.text @代码段
@设置LED灯的配置寄存器 GPX2CON7为输出状态
ldr r0,=0x11000c40 @将GPX2CON寄存器地址写入r0
ldr r1,[r0] @将寄存器中的数据写入r1
bic r1,#0xf0000000 @将GPX2CON[7]清零
orr r1,#0x10000000 @将GPX2CON[7]设置为输出模式
str r1,[r0] @设置GPX2CON寄存器
@设置LED灯输出高、低电平 GPX2DATA[7]
ldr r0,=0x11000c44
loop:
ldr r1,[r0]
tst r1,#0x80
orreq r1,#0x80
bicne r1,#0x80
str r1,[r0]
bl delay1s
b loop
delay1s:
ldr r4,=0x1ffffff
delay1s_loop:
cmp r4,#0
beq delay1s_end
sub r4,r4,#1
b delay1s_loop
delay1s_end:
mov pc,lr
.end
编译环境搭建
安装交叉编译工具
- 拷贝交叉编译工具链gcc-4.6.4.tar.xz到linux下
- tar -vxf gcc-4.6.4.tar.xz解压后得到gcc-4.6.4
- 在bin目录下可以看到交叉编译工具arm-none-linux-gnueabi-gcc
添加环境变量
-
可以看到,编译必须使用全路径
~/gcc-4.6.4/bin/arm-none-linux-gnueabi-gcc
-
为了不每次编译都使用全路径,可以将工具路径添加到环境变量中
-
如果想要改配置永久生效,可以在启动脚本中添加该指令
linux@linux:~/gcc-4.6.4/bin$ vi ~/.bashrc
-
更新脚本:
linux@linux:~$ source ~/.bashrc
编译
makefile
CROSS = arm-none-linux-gnueabi-
CC=$(CROSS)gcc
LD=$(CROSS)ld
OBJCOPY=$(CROSS)objcopy #用来转化文件格式(把Linux文件格式进行转化)
all : led.s
$(CC) -g -c -o led.o led.s #-c表示编译进行到汇编阶段完成后停止,此时已经生成了目标文件(.o)(下一阶段是链接)
$(LD) led.o -Ttext 0x40001000 -o led.elf #-Ttext表示指定链接地址(程序中第一条指令存放的地址)(.elf文件用于Linux中在gdb下调试)
$(OBJCOPY) -O binary -S led.elf led.bin #(.elf文件中包含调试信息,通过objcopy,去掉调试信息)
$(CROSS)objdump -D led.elf > led.dis #反汇编,通过执行文件反向得到汇编程序
clea:
rm -f *.o *.elf *.bin *.dis
下载
-
连接串口线,安装串口驱动
打开超级终端 选择对应串口
串口设置为 115200 flow control = none
重上电能看到串口信息
用串口传输文件 -
串口终端里输入
loadb 40001000
再选传送-> 发送文件->选择待发送的文件
如led.bin
选协议为kermit ,点传送
5. 运行裸机程序
go 40001000
示例
.text @代码段
@设置LED2灯的配置寄存器 GPX2CON7为输出状态
ldr r0,=0x11000c40 @将GPX2CON寄存器地址写入r0
ldr r1,[r0] @将寄存器中的数据写入r1
bic r1,#0xf0000000 @将GPX2CON[7]清零
orr r1,#0x10000000 @将GPX2CON[7]设置为输出模式
str r1,[r0] @设置GPX2CON寄存器
@设置LED3灯的配置寄存器 GPX1CON0为输出状态
ldr r0,=0x11000c20
ldr r1,[r0]
bic r1,#0x0000000f
orr r1,#0x00000001
str r1,[r0]
@设置LED4灯的配置寄存器 GPF3CON4为输出状态
ldr r0,=0x114001E0
ldr r1,[r0]
bic r1,#0x000f0000
orr r1,#0x00010000
str r1,[r0]
@设置LED5灯的配置寄存器 GPF3CON5为输出状态
ldr r0,=0x114001E0
ldr r1,[r0]
bic r1,#0x00f00000
orr r1,#0x00100000
str r1,[r0]
loop:
bl LED2_ON
bl LED3_OFF
bl LED4_OFF
bl LED5_OFF
bl delay1s
bl LED3_ON
bl LED2_OFF
bl LED4_OFF
bl LED5_OFF
bl delay1s
bl LED4_ON
bl LED2_OFF
bl LED3_OFF
bl LED5_OFF
bl delay1s
bl LED5_ON
bl LED2_OFF
bl LED3_OFF
bl LED4_OFF
bl delay1s
b loop
LED2_ON:
@设置LED2灯输出高电平 GPX2DATA[7]
ldr r0,=0x11000c44
ldr r1,[r0]
orr r1,#0x80
str r1,[r0]
LED2_ON_END:
mov pc,lr
LED2_OFF:
@设置LED2灯输出低电平 GPX2DATA[7]
ldr r0,=0x11000c44
ldr r1,[r0]
bic r1,#0x80
str r1,[r0]
LED2_OFF_END:
mov pc,lr
LED3_ON:
@设置LED3灯输出高电平 GPX1DATA[0]
ldr r0,=0x11000c24
ldr r1,[r0]
orr r1,#0x01
str r1,[r0]
LED3_ON_END:
mov pc,lr
LED3_OFF:
@设置LED2灯输出低电平 GPX1DATA[0]
ldr r0,=0x11000c24
ldr r1,[r0]
bic r1,#0x01
str r1,[r0]
LED3_OFF_END:
mov pc,lr
LED4_ON:
@设置LED4灯输出高电平 GPF3DATA[4]
ldr r0,=0x114001E4
ldr r1,[r0]
orr r1,#0x10
str r1,[r0]
LED4_ON_END:
mov pc,lr
LED4_OFF:
@设置LED4灯输出低电平 GPF3DATA[4]
ldr r0,=0x114001E4
ldr r1,[r0]
bic r1,#0x10
str r1,[r0]
LED4_OFF_END:
mov pc,lr
LED5_ON:
@设置LED5灯输出高电平 GPF3DATA[4]
ldr r0,=0x114001E4
ldr r1,[r0]
orr r1,#0x20
str r1,[r0]
LED5_ON_END:
mov pc,lr
LED5_OFF:
@设置LED5灯输出低电平 GPF3DATA[4]
ldr r0,=0x114001E4
ldr r1,[r0]
bic r1,#0x20
str r1,[r0]
LED5_OFF_END:
mov pc,lr
delay1s:
ldr r4,=0x2ffffff
delay1s_loop:
cmp r4,#0
beq delay1s_end
sub r4,r4,#1
b delay1s_loop
delay1s_end:
mov pc,lr
.end
参考
https://blog.youkuaiyun.com/m0_37542524/article/details/85650128