我们发现在流驱动中的s2440.h中有对IO口寄存器GPACON~GPJCON、GPADAT~GPJDAT 的地址分配 如下:
#define IOP_BASE 0xB1600000
typedef struct {
unsigned int rGPACON; // 00 怎么确定rGPACON的地址??
typedef struct {
unsigned int rGPACON; // 00 怎么确定rGPACON的地址??
unsigned int rGPADAT;
unsigned int rPAD1[2];
unsigned int rGPBCON; // 10
unsigned int rGPBDAT;
unsigned int rGPBUP;
unsigned int rPAD2;
unsigned int rGPCCON; // 20
unsigned int rGPCDAT;
unsigned int rGPCUP;
unsigned int rPAD3;
unsigned int rGPDCON; // 30
unsigned int rGPDDAT;
unsigned int rGPDUP;
unsigned int rPAD4;
unsigned int rGPECON; // 40
unsigned int rGPEDAT;
unsigned int rGPEUP;
unsigned int rPAD5;
unsigned int rGPFCON; // 50
unsigned int rGPFDAT;
unsigned int rGPFUP;
unsigned int rPAD6;
unsigned int rGPGCON; // 60
unsigned int rGPGDAT;
unsigned int rGPGUP;
unsigned int rPAD7;
unsigned int rGPHCON; // 70
unsigned int rGPHDAT;
unsigned int rGPHUP;
unsigned int rPAD8;
unsigned int rMISCCR; // 80
unsigned int rDCKCON;
unsigned int rEXTINT0;
unsigned int rEXTINT1;
unsigned int rEXTINT2; // 90
unsigned int rEINTFLT0;
unsigned int rEINTFLT1;
unsigned int rEINTFLT2;
unsigned int rEINTFLT3; // A0
unsigned int rEINTMASK;
unsigned int rEINTPEND;
unsigned int rGSTATUS0; // AC
unsigned int rGSTATUS1; // B0
unsigned int rGSTATUS2; // B4 ;;; SHL
unsigned int rGSTATUS3; // B8
unsigned int rGSTATUS4; // BC
unsigned int rFLTOUT; // C0
unsigned int rDSC0;
unsigned int rDSC1;
unsigned int rMSLCON;
unsigned int rGPJCON; // D0
unsigned int rGPJDAT;
unsigned int rGPJUP;
unsigned int rPAD9;
}IOPreg;
unsigned int rPAD1[2];
unsigned int rGPBCON; // 10
unsigned int rGPBDAT;
unsigned int rGPBUP;
unsigned int rPAD2;
unsigned int rGPCCON; // 20
unsigned int rGPCDAT;
unsigned int rGPCUP;
unsigned int rPAD3;
unsigned int rGPDCON; // 30
unsigned int rGPDDAT;
unsigned int rGPDUP;
unsigned int rPAD4;
unsigned int rGPECON; // 40
unsigned int rGPEDAT;
unsigned int rGPEUP;
unsigned int rPAD5;
unsigned int rGPFCON; // 50
unsigned int rGPFDAT;
unsigned int rGPFUP;
unsigned int rPAD6;
unsigned int rGPGCON; // 60
unsigned int rGPGDAT;
unsigned int rGPGUP;
unsigned int rPAD7;
unsigned int rGPHCON; // 70
unsigned int rGPHDAT;
unsigned int rGPHUP;
unsigned int rPAD8;
unsigned int rMISCCR; // 80
unsigned int rDCKCON;
unsigned int rEXTINT0;
unsigned int rEXTINT1;
unsigned int rEXTINT2; // 90
unsigned int rEINTFLT0;
unsigned int rEINTFLT1;
unsigned int rEINTFLT2;
unsigned int rEINTFLT3; // A0
unsigned int rEINTMASK;
unsigned int rEINTPEND;
unsigned int rGSTATUS0; // AC
unsigned int rGSTATUS1; // B0
unsigned int rGSTATUS2; // B4 ;;; SHL
unsigned int rGSTATUS3; // B8
unsigned int rGSTATUS4; // BC
unsigned int rFLTOUT; // C0
unsigned int rDSC0;
unsigned int rDSC1;
unsigned int rMSLCON;
unsigned int rGPJCON; // D0
unsigned int rGPJDAT;
unsigned int rGPJUP;
unsigned int rPAD9;
}IOPreg;
......
流驱动中的操作
volatile IOPreg *s2440IOP = (IOPreg *)IOP_BASE;
......
s2440IOP->rGPBCON = (s2440IOP->rGPBCON &~(3 << 10)) | (1<< 10);
s2440IOP->rGPBDAT=s2440IOP->rGPBDAT&~(0x1<<1);
答案如下:
1、#deifine IOP_BASE 0xB1600000,实际物理地址是:0x56000000;一个是物理地址 一个是虚拟地址,没有开启MMU用0x56000000
开启之后用0xB1600000,计算公式为: 虚拟地址=物理>>4位 + 0xac000000。 采用虚拟内存技术有以下三点好处:第一,可以根据用户的需要重新分配内存地址空间;
开启之后用0xB1600000,计算公式为: 虚拟地址=物理>>4位 + 0xac000000。 采用虚拟内存技术有以下三点好处:第一,可以根据用户的需要重新分配内存地址空间;
第二,可以隔离硬件物理地址空间的变化对软件的影响;第三,可以对存储空间引入保护机制。
2、 对I/O口的操作是通过对相关寄存器的读/写实现的。要对寄存器进行读/写操作,首先要对寄存器进行定义。结构体中在基址上内存对齐的分配寄存器的地址,
volatile IOPreg *s2440IOP = (IOPreg *)IOP_BASE;这条语句是把一个虚拟地址强行转成一个结构体,这个虚拟地址便是基址,所以再回到结构体上,需要了解的是:ARM中的存储都是以4个字节为一个单位的,所以地址都是4的整倍数。一个32位空间就存4字节数据,使用的时候分离或屏蔽其他信息即可。ARM int整也就是32位的,int temp;//32位,char achar;//8位。rGPACON的地址为0xB16000000,rGPADAT的地址为0xB16000004,rPAD1[0]的地址为0xB16000008,rPAD1[1]的地址0xB1600000C,rGPBCON的地址为0xB16000010依次类推。这样有关IO口各个寄存器的地址就这样确定了,只需在驱动程序中往IO口32位的控制寄存器和数据寄存器中写
3、s2440IOP->rGPBCON = (s2440IOP->rGPBCON &~(3 << 10)) | (1<< 10);这条语句的意思是,把GPBCON寄存器第10和11位清零,其他位不变,再把第10位置1,这样就把GPB5的状态改成输出了,通过这条语句可以对IO的功能进行定义,比如定义哪个IO口作为输入输出或其他复用功能。同样s2440IOP->rGPBDAT=s2440IOP->rGPBDAT&~(0x1<<1);这条语句的意思是把GPBDAT寄存器倒数第二位置零,其他位不变,这样就使得接在GPB1上的IO口置0了,通过这样可以完成对IO口的赋值。