在之前的章节我们已经介绍了嵌入式linux开发的准备工作,主要包括:
如果你已经具备了这些知识,那么就可以直接上手开始开发了。今天我将带领大家去点亮Mini2440开发板的LED。
一、Mini2440 LED电路图
下图是Mini2440开发板LED接线图,一共有4个LED。
Mini2440主芯片引脚图:
nlED_x与CPU接线如下表:
nLED_1 | nLED_2 | nLED_3 | nLED_4 | |
GPIO | GPB5 | GPB6 | GPB7 | GPB8 |
可复用为 | nXBACK | nXREQ | nXDACK1 | nDREQ1 |
使能 | 低电平 | 低电平 | 低电平 | 低电平 |
这里我们以点亮nLED_1为例。有原理图我们知道nLED_1对应主控芯片的GPB5引脚,且当GPB5输出低电平时,nLED_1才会被点亮。而引脚是通过寄存器控制的,因此我们需要对GPB5引脚相关寄存器进行控制。
二、GPIO控制
这里为大家准备了两份S3C2440芯片手册:
2.1 GPIO资源
关于GPI相关的内容位于手册第九章,S3C2440共有24个外部中断端口,130个多功能输入/输出引脚。具体如下:
-
端口A(GPA):25 位输出端口;
-
端口B(GPB):11 位输入/输出端口 ;
-
端口C(GPC):16 位输入/输出端口;
-
端口D(GPD):16 位输入/输出端口;
-
端口E(GPE):16 位输入/输出端口 ;
-
端口F(GPF):8 位输入/输出端口;
-
端口G(GPG):16 位输入/输出端口;
-
端口H(GPH):9 位输入/输出端口;
-
端口J(GPJ):13 位输入/输出端口;
2.2 GPIO寄存器
(1) 端口配置寄存器(GPACON 至GPJCON)
S3C2440A 中,大多数端口为复用引脚。因此要决定每个引脚选择哪项功能。PnCON(引脚控制寄存器)决 定了每个引脚使用哪项功能。
如果在掉电模式中PE0 至PE7 用于唤醒信号,这些端口必须配置为输入模式。
(2) 端口数据寄存器(GPADAT 至GPJDAT)
如果端口配置为输出端口,可以写入数据到PnDAT 的相应位。如果端口配置为输入端口,可以从PnDAT 的相 应位读取数据。
(3) 端口上拉寄存器(GPBUP 至GPJUP)
端口上拉寄存器控制每个端口组的使能/禁止上拉电阻。当相应位为0 时使能引脚的上拉电阻。当为1 时禁止 上拉电阻。
如果使能了上拉电阻,那么上拉电阻与引脚的功能设置无关(输入、输出、DATAn、EINTn 等等) 杂项控制寄存器 此寄存器控制睡眠模式,USB 引脚和CLKOUT 选择的数据端口上拉电阻。
(4) 杂项控制寄存器
此寄存器控制睡眠模式,USB 引脚和CLKOUT 选择的数据端口上拉电阻。
(5) 外部中断控制寄存器
24 个外部中断由各种信号方式触发。EXTINT 寄存器为外部中断请求配置信号触发方式为低电平触发、高电平 触发、下降沿触发、上升沿触发或双边沿触发。
由于每个外部中断引脚包含一个数字滤波器,中断控制可以确认请求信号是否长于3 个时钟。 EINT[15:0]用于唤醒源。
2.3 端口B寄存器使用 (GPBCON、GPBDAT、GPBUP)
由于nLED_1对应的引脚为GPB5,因此这里只介绍端口B相关寄存器的相关信息。
寄存器 | 地址 | R/W | 描述 |
GPBCON | 0x56000010 | R/W | 配置端口B的引脚 |
GPBDAT | 0x56000014 | R/W | 配置B的数据寄存器 |
GPBUP | 0x56000018 | R/W | 端口B的上拉使能寄存器 |
保留 | 0x5600001C | - | 保留 |
(1) GPBCON
GPBCON | 位 | 描述 | 初始状态 |
GPB10 | [21:20] | 00:输入 01:输出 10:nxDREQ0 11:保留 | 0 |
GPB9 | [19:18] | 00:输入 01:输出 10:nxDACK0 11:保留 | 0 |
GPB8 | [17:16] | 00:输入 01:输出 10:nxDREQ1 11:保留 | 0 |
GPB7 | [15:14] | 00:输入 01:输出 10:nxDACK1 11:保留 | 0 |
GPB6 | [13:12] | 00:输入 01:输出 10:nxBREQ 11:保留 | 0 |
GPB5 | [11:10] | 00:输入 01:输出 10:nxBACK 11:保留 | 0 |
GPB4 | [9:8] | 00:输入 01:输出 10:TCLK[0] 11:保留 | 0 |
GPB3 | [7:6] | 00:输入 01:输出 10:TOUT3 11:保留 | 0 |
GPB2 | [5:4] | 00:输入 01:输出 10:TOUT2 11:保留 | 0 |
GPB1 | [3:2] | 00:输入 01:输出 10:TOUT1 11:保留 | 0 |
GPB2 | [1:0] | 00:输入 01:输出 10:TOUT0 11:保留 | 0 |
由上表可知,B端口的控制寄存器可以将每个引脚配置为四种模式:
- 00:输入模式
- 01:输出模式
- 10:功能扩展模式
- 11:保留模式
若要使GPB5引脚输出低电平,须将GPB5配置为输出模式,即将Bit[11:10]配置为01。 GPBCON的地址为0x56000010,因此将0x400写入地址0x56000010即可:
# write GPBCON
ldr r1,=0x56000010
mov r0,#0x400
str r0,[r1]
(2) GPBDAT
GPBDAT | 位 | 描述 |
GPB[10:0] | [10:0] |
当端口配置为输入端口时,相应位为引脚状态。当端口配置为输出端口时,引脚状态将与相应位相同。当端口配置为功能引脚,将读取到未定义值。 |
由表可知,引脚的状态与对应的位的状态相同,因而可以通过配置GPBDAT每一位的状态从而配置引脚的状态。 将数据寄存器的bit5配置为0即可把引脚GPB5配置为低电平:
# write GPBDAT
ldr r1,=0x56000014
mov r0,#0x00
str r0,[r1]
(3) GPBUP
GPBUP | 位 | 描述 |
GPB[10:0] | [10:0] |
0:使能附加上拉功能到相应端口引脚 1:禁止附加上拉功能到相应端口引脚 |
当引脚的驱动能力不足时,需要配置上拉寄存器。由于引脚输出低电平即可点亮led,因此上拉寄存器无需配置。
2.4 总结
以上可知,配置GPB5引脚输出低电平需要两个步骤:
-
配置控制寄存器GPBCON的bit[11:10]=01,使GPB5引脚为输出模式;
-
配置数据寄存器GPBDAT的bit5=0,使GPB5引脚输出低电平;
三、编写代码
我们在samba共享文件夹下创建一个project文件夹,专门用来放置我们的测试代码。
1、纯汇编
.startS:
# nLED_1 GPB5=0
.text
.global _start
_start:
b light_led
light_led:
# write GPBCON
ldr r1,=0x56000010
mov r0,#0x400
str r0,[r1]
# write GPBDAT
ldr r1,=0x56000014
mov r0,#0x00
str r0,[r1]
b halt
halt:
b halt
Makefile:
all:start.o
# 链接
arm-linux-ld -Ttext 0x30000000 -o start.elf $^
# 转为bin -S 不从源文件中复制重定位信息和符号信息到目标文件中
arm-linux-objcopy -O binary -S start.elf start.bin
# 反汇编 -D反汇编所有段
arm-linux-objdump -D start.elf > start.dis
%.o : %.S
arm-linux-gcc -g -c $^
%.o : %.c
arm-linux-gcc -g -c $^
.PHONY: clean
clean:
rm *.o *.elf *.bin *.dis
注意:arm-linux-ld -Ttext 0x30000000将目标文件start.elf文件中的.text代码段链接到起始地址0x30000000,0x30000000是S3C2440 的SDRAM起始地址。
进入目标文件夹,使用make命令进行编译,编译成功后,我们通过MiniTools工具进行程序烧录。烧录有两种方式;
- 直接下载到RAM中,下载地址为0x30000000,下载后程序会直接运行。
- 将start.bin烧录到NAND FLASH中,下载到NAND FLASH,这样程序可以保存下来,程序烧录完成后,将Mini2440开发板调至NAND FLASH启动,然后给开发板上电,观察nLED_1是否已经点亮:
2、汇编、c混合
代码分为两个部分,一个是汇编文件,一个是c文件:
start.S
.text
.global _start
_start:
# 设置内存: sp 栈
ldr sp, =4096 /* nand启动 */
#ldr sp, =0x40000000+4096 /* nor启动 */
# 调用main
bl main
halt:
b halt
led.c:
int main()
{
unsigned int *p_con =(unsigned int *) 0x56000010;
unsigned int *p_dat =(unsigned int *) 0x56000014;
/* 配置GPB5引脚为输出模式 */
*p_con = 0x400;
while(1)
{
/* 配置GPB5引脚输出低电平*/
*p_dat = 0;
}
return 0;
}
Makefile:
all:start.o led.o
# 链接
arm-linux-ld -Ttext 0x30000000 -o led.elf $^
# 转为bin -S 不从源文件中复制重定位信息和符号信息到目标文件中
arm-linux-objcopy -O binary -S led.elf led.bin
# 反汇编 -D反汇编所有段
arm-linux-objdump -D led.elf > led.dis
%.o : %.S
arm-linux-gcc -g -c $^
%.o : %.c
arm-linux-gcc -g -c $^
.PHONY: clean
clean:
rm *.o *.elf *.bin *.dis
注意:arm-linux-ld -Ttext 0x30000000将目标文件start.elf文件中的.text代码段链接到起始地址0x30000000,进入目标文件夹,使用make命令进行编译,编译成功后,烧录程序的过程同上,这里就不重复介绍了。
参考文章:
[1] 二.mini2440点亮流水灯