微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > ARM学习笔记--GPIO接口

ARM学习笔记--GPIO接口

时间:11-10 来源:互联网 点击:

有地址不对齐的异常处理函数,那么上述代码将会出错。如果某个BANK的位宽被设为n,访问此BANK时,在总线上永远只会看到地址对齐的n位操作。

3)8位读操作

unsigned char *pwAddr = (unsigned char *)0x6;

unsigned char ucVal;

ucVal = *pwAddr;

CPU首先使用地址0x6对NOR Flsh发起16位的读操作,得到两个字节的数据,假设为D0、D1;然后将D0取出赋值给变量ucVal。在读操作期间,地址总线 ADDR1~ADDR20、A0~A19的信号都是1、1、0、...、0(CPU的ADDR0为0,不过ADDR0没有接到NOR Flash上)。CPU会自动丢弃D1。

4)32位读操作

unsigned int *pwAddr = (unsigned int *)0x6;

unsigned int udwVal;

udwVal = *pwAddr;

CPU首先使用地址0x6对NOR Flsh发起16位的读操作,得到两个字节的数据,假设为D0、D1;再使用地址0x8发起读操作,得到两字节的数据,假设为D2、D3;最后将这4个数据组合后赋给变量udwVal。

5)16位写操作

unsigned short *pwAddr = (unsigned short *)0x6;

*pwAddr = 0x1234;

由于NOR Flash的特性,使得NOR Flash的写操作比较复杂——比如要先发出特定的地址信号通知NOR Flash准备接收数据,然后才发出数据等。不过,其总线上的电信号与软件指令的关系与读操作类似,只是数据的传输方向相反。

2、使用软件来访问硬件

当个引脚的操作有3种:输出高低电平、检测引脚状态、中断。对某个引脚的操作一般通过读写寄存器实现

首先我们从点亮LED开始,下图选自mini2440原理图,LED1-4分别对应GPB5-8

如果要控制这些LED,那么我们首先要把GPBCON寄存器中GPB5-8对应的位设为输出功能,然后写GPBDAT寄存器的相应位,使这4个引脚输出高低电平

一般是低电平有效,即高电平时,对应LED熄灭,低电平时,对应LED点亮

访问寄存器的时候,通过S3C2440的数据手册查到GPBCON和GPBDAT寄存器的地址,附数据手册 点击下载

GPBCON为0x56000010,GPBDAT为0x56000014

通过下面的代码让GPB5输出低电平,点亮LED1

#define GPBCON (*(volatile unsigned long *) 0x56000010) //volatile修饰符确保每次去内存中读取变量的值,还不是从cache或者寄存器中

#define GPBDAT (*(volatile unsigned long *) 0x56000014)

#define GPB5_OUT (1<(5*2)) //两位控制一个引脚,那么GPB5就是GPBCON的[11:10]位,1左移10位,则[11:10]为01,表示GPB5为输出

GPBCON = GPB5_OUT;

GPBDAT &= ~(1<5); //1左移5位取反,那么第5位为0,即GPB5输出低电平,点亮LED1

二、GPIO操作实例

1、使用汇编代码点亮一个LED

先看源程序 led_on.S

.text

.global _start

_start:

LDR R0,=0x56000010 @ R0设为GPBCON寄存器

MOV R1,#0x00000400 @ 设置GPB5为输出口, 位[11:10]=0b01

STR R1,[R0]

LDR R0,=0x56000014 @ R0设为GPBDAT寄存器

MOV R1,#0x00000000 @ 此值改为0x00000020,可让LED1熄灭

STR R1,[R0] @ GPB5输出0,LED1点亮

MAIN_LOOP:

B MAIN_LOOP @无限循环

再来看程序的Makefile

led_on.bin : led_on.S

arm-linux-gcc -g -c -o led_on.o led_on.S

arm-linux-ld -Ttext 0x0000000 -g led_on.o -o led_on_elf

arm-linux-objcopy -O binary -S led_on_elf led_on.bin

clean:

rm -f led_on.bin led_on_elf *.o

led_on.S生成led_on.bin

第一行做汇编

第二行做连接,指定代码段起始地址为0x00000000

第三行把ELF格式转为二进制格式

clean用于清除编译生成的文件

2、使用c语言代码点亮LED

汇编可读性比C差,我们用C来实现

@******************************************************************************

@ File:crt0.S

@ 功能:通过它转入C程序

@******************************************************************************

.text

.global _start

_start:

ldr r0, =0x53000000 @ WATCHDOG寄存器地址

mov r1, #0x0

str r1, [r0] @ 写入0,禁止WATCHDOG,否则CPU会不断重启

ldr sp, =1024*4 @ 设置堆栈,注意:不能大于4k, 因为现在可用的内存只有4K,这4k是steppingstone,后面会介绍

@ nand flash中的代码在复位后会移到内部ram中,此ram只有4K

bl main @ 调用C程序中的main函数

halt_loop:

b halt_loop

下面是led_on_c.c

#define GPBCON (*(volatile unsigned long *)0x56000010)

#define GPBDAT (*(volatile unsigned long *)0x56000014)

int main()

{

GPBCON = 0x00000400; // 设置GPB5为输出口, 位[11:10]=0b01

GPBDAT = 0x00000000; // GPB5输出0,LED1点亮

return 0;

}

最后是Makefile

led_on_c.bin : crt0.S led_on_c.c

arm-linux-gcc -g -c

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top