1、第四章 S3C2410A的I/O口从这一章开始,就进入了S3C2410A底层驱动程序开发的学习过程中了。在第一章已经介绍了ARM系统开发的层级结构,本课程的内容符合层次结构中的第二层底层驱动开发,但是这里不包含启动代码的编写和操作系统移植。一般来讲ARM开发系统如广州友善之臂的micro2440开发板,英贝特公司的开发板,在加上达盛公司的实验系统等等,出厂时各类底层的相关驱动程序和应用的操作系统移植都已经编写测试完毕,其中ARM的启动代码是现成可以使用的,不需要重新编写。另外,出厂时的底层驱动代码都是可以直接使用的,这些代码可以提供给使用者自学时参考,当然如果觉得这些代码在结构上表达上都不尽如
2、人意,读者随时都可以自行修改。达盛公司的实验系统的底层驱动程序也是现成可以使用的,但是鉴于教学需要,本课程会引导读者在理解底层硬件的基础上对这些程序进行修改或者重写编写部分驱动程序,以便使读者能够熟练掌握S3C2410A底层的驱动开发。4.1 S3C2410A的GPIO1. S3C2410A CPU有117个多功能复用的I/O口,共分为8组。(1)16bit I/O端口为:Port C、Port D、Port E和Port G(2)11bit I/O端口为:Port B和Port H(3)23bit I/O端口为:Port A(4)8bit I/O端口为:Port F(5)在这里需要说明几个问
3、题: 端口的bit数是什么意思?例如,Port C为16bit I/O端口,即Port C共有16位,从Port C0到Port C15都可以应用。 多功能复用是什么意思?ARM7和ARM9这些CPU的I/O口都可以配置成不同的功能,也就是说这些端口可以作为普通的输入输出端口使用,也可以配置成UART使用,还可以配置成I2C、SPI和SSI等总线信号使用。(6)如何操作这些I/O端口?用配置和访问S3C2410A的功能寄存器的方法可以操作S3C2410A的硬件资源。2. I/O端口的控制寄存器下面这些宏定义摘自头文件2410ADDR.H,这些通过这些寄存器就可以控制S3C2410A的I/O端口
4、了。还有一些功能寄存器在这里没有列出,读者可自行在2410ADDR.H这个文件中查找学习。/ I/O PORT #define rGPACON (*(volatile unsigned *)0x56000000) /Port A control#define rGPADAT (*(volatile unsigned *)0x56000004) /Port A data#define rGPBCON (*(volatile unsigned *)0x56000010) /Port B control#define rGPBDAT (*(volatile unsigned *)0x56000014
5、) /Port B data#define rGPBUP (*(volatile unsigned *)0x56000018) /Pull-up control B#define rGPCCON (*(volatile unsigned *)0x56000020) /Port C control#define rGPCDAT (*(volatile unsigned *)0x56000024) /Port C data#define rGPCUP (*(volatile unsigned *)0x56000028) /Pull-up control C#define rGPDCON (*(vo
6、latile unsigned *)0x56000030) /Port D control#define rGPDDAT (*(volatile unsigned *)0x56000034) /Port D data#define rGPDUP (*(volatile unsigned *)0x56000038) /Pull-up control D#define rGPECON (*(volatile unsigned *)0x56000040) /Port E control#define rGPEDAT (*(volatile unsigned *)0x56000044) /Port E
7、 data#define rGPEUP (*(volatile unsigned *)0x56000048) /Pull-up control E#define rGPFCON (*(volatile unsigned *)0x56000050) /Port F control#define rGPFDAT (*(volatile unsigned *)0x56000054) /Port F data#define rGPFUP (*(volatile unsigned *)0x56000058) /Pull-up control F#define rGPGCON (*(volatile un
8、signed *)0x56000060) /Port G control#define rGPGDAT (*(volatile unsigned *)0x56000064) /Port G data#define rGPGUP (*(volatile unsigned *)0x56000068) /Pull-up control G#define rGPHCON (*(volatile unsigned *)0x56000070) /Port H control#define rGPHDAT (*(volatile unsigned *)0x56000074) /Port H data#def
9、ine rGPHUP (*(volatile unsigned *)0x56000078) /Pull-up control H在这里,我们以Port G为例来说明如何对I/O端口进行控制。和Port G有关的寄存器有:#define rGPGCON (*(volatile unsigned *)0x56000060) /Port G control#define rGPGDAT (*(volatile unsigned *)0x56000064) /Port G data#define rGPGUP (*(volatile unsigned *)0x56000068) /Pull-up co
10、ntrol GrGPGCON、rGPGDAT和rGPGUP为寄存器的名称,0x56000060、0x56000064和0x56000068为寄存器在S3C2410A中的硬件地址。即用名称来代替地址来操作。与寄存器描述相关的表格如下:表4.1说明: 地址0x5600006C为保留地址,其功能没有定义。 寄存器GPGCON为可读可写的寄存器(R/W),其描述为配置port G的引脚,其复位值为0x0(Reset Value)。 寄存器GPGDAT为可读可写的寄存器(R/W),其描述为port G的数据寄存器,复位值没有定义。 寄存器GPGUP为可读可写的寄存器(R/W),其描述为port G的上拉
11、功能禁止寄存器。 表4.2 表在下页说明: 从表4. 2可以看出寄存器GPGCON是32位的。 GPGCON的每2bit对应16bit端口G中的一个。比如GPGCON31:30对应于GPG15。 端口GPG10GPG8是可以允许5V电平输入的。 以GPG15为例说明利用GPGCON是如何进行端口配置的。GPGCON31:30这2bit用来对port G中的GPG15进行配置:表4. 3GPGCON31:30配置值GPG15的功能00Input(输入)01Output(输出)10外部中断2311触摸屏Y轴加操作开关控制信号表4. 4说明: GPGDAT寄存器是16bit寄存器。 具体功能为:当端
12、口被配置为输入端口时,来自外部数据源的数据将会被读入到相对应的管脚中去,即GPGDAT是作为缓冲区用的。当端口被配置为输出端口时,写入这个寄存器中的数据将会被发送到相应的端口上去。当端口被配置为功能管脚时,在端口上会读到未定义的值。表4. 5说明:GPGUP15:0对应着GPG15:0,如果GPGUP15:0的某一位为“0”,则相对应的GPG管脚的上拉功能就被使能了;如果GPGUP15:0的某一位为“1”,则相对应的GPG管脚的上拉功能就被禁止了。在S3C2410A上电的时候,GPGUP15:11默认数值为“1”,也即GPG15:11的上拉功能是禁止的。这里说明一下什么是上拉功能,附带再说明一
13、下相对应的下拉功能。一般,上拉和下拉功能只在数字电路中有效。上拉如图4.1所示:图4.1上拉就是在数字芯片的管脚上通过一个电阻连接到电源上,一般可用的电阻值为3.3K、4.7K、5.1K或者10K,电阻值不易过大。具体作用是在引脚没有输出的情况下给该引脚一个确定的电平(高电平),另外还可以增加该管脚对外的驱动电流。如果引脚是输入作用的,那么在该引脚开路时,上拉操作也会给该引脚一个确定的高电平。下拉如图4. 2所示:图4. 2下拉就是在数字芯片的管脚上通过一个电阻连接到地上,一般可用的电阻值为3.3K、4.7K、5.1K或者10K,电阻值不易过大。具体作用是在引脚没有输出的情况下给该引脚一个确定
14、的电平(低电平)。如果引脚是输入作用的,那么在该引脚开路时,下拉操作也会给该引脚一个确定的低电平。4.2 S3C2410A GPIO寄存器这里只列举各个端口的控制寄存器和其他相关寄存器,各个端口的数据寄存器和上拉寄存器基本功能都是相同的,这里就不再重复列出了。1. PortA端口A只有控制寄存器和数据寄存器而没有上拉寄存器。数据寄存器位宽为23bit。控制寄存器的具体内容定义详见S3C2410A的数据手册,这里不再详细说明。2. PortB端口B的控制寄存器只有22bit有效。其数据寄存器和上拉寄存器只有11bit有效。3. PortC端口C的数据寄存器和上拉寄存器只有16bit有效。4. P
15、ortD端口D的数据寄存器和上拉寄存器只有16bit有效。5. PortE端口D的数据寄存器和上拉寄存器只有16bit有效。6. PortF端口F的数据寄存器和上拉寄存器只有8bit有效。7. PortG端口G的数据寄存器和上拉寄存器只有16bit有效。8. PortH端口H的数据寄存器和上拉寄存器只有11bit有效。9. MISCCR寄存器这个寄存器主要和USB Host和USB Device有关。10. DCLKCON寄存器这个寄存器定了DCLKn信号,这个信号可以作为外部设备的时钟源使用。这个寄存器只在CLKOUT1:0被置位而发送DCLKn信号时才能正常工作。11. 通用状态寄存器(G
16、STATUSn)鉴于篇幅,与外部中断相关的寄存器就不在本文中列出了,有兴趣的读者可以详细参阅S3C2410A的数据手册。4.3 I/O编程实验1. 实验要求使目标板上的两个LED(LED1和LED2)交替闪亮。LED1和LED2是共阳极连接。LED1接到了S3C2410A的G端口的第8位上,LED2接到了S3C2410A的G端口的第9位上。2. 实验设备(1) EL-ARM-830教学实验箱,PentiumII以上的PC机,仿真调试电缆。(2) PC操作系统WIN98或WIN2000或WINXP,ADS1.2集成开发环境,仿真调试驱动程序。3. 实验分析已知两个LED分别接到了G端口的第8和第
17、9位上,那么这两位需要设置成输出端口。LED是共阳极连接,那么高电平熄灭,低电平点亮。开机后,两个LED就交替闪亮,那么改程序必须是死循环程序。要实现交替闪亮就需要有亮灭的延时功能。4. 实验原理S3C2410A CPU 共有117个多功能复用输入输出口,分为8组端口: 4个16位的I/O端口 (PORT C、PORT D、PORT E、PORT G) 2个11位的I/O端口 (PORT B 和PORT H) 1个8位的I/O端口(PORT F) 1个23位的I/O端口(PORT A)这些通用的GPI/O接口,是可配置的, PORTA除功能口外,它们仅用作输出使用,剩下的PORTB、PORTC
18、、PORTD、PORTE、PORTF、PORTG均可作为输入输出口使用。配置这些端口,是通过一些寄存器来实现的,这些寄存器均有各自的地址,位长32位。往该地址中写入相应的数据,即可实现功能及数据配置。GPACON (0x56000000) /Port A controlGPADAT (0x56000004) /Port A dataGPBCON (0x56000010) /Port B controlGPBDAT (0x56000014) /Port B dataGPBUP (0x56000018) /Pull-up control BGPCCON (0x56000020) /Port C c
19、ontrolGPCDAT (0x56000024) /Port C dataGPCUP (0x56000028) /Pull-up control CGPDCON (0x56000030) /Port D controlGPDDAT (0x56000034) /Port D dataGPDUP (0x56000038) /Pull-up control DGPECON (0x56000040) /Port E controlGPEDAT (0x56000044) /Port E dataGPEUP (0x56000048) /Pull-up control EGPFCON (0x5600005
20、0) /Port F controlGPFDAT (0x56000054) /Port F dataGPFUP (0x56000058) /Pull-up control FGPGCON (0x56000060) /Port G controlGPGDAT (0x56000064) /Port G dataGPGUP (0x56000068) /Pull-up control GGPHCON (0x56000070) /Port H controlGPHDAT (0x56000074) /Port H dataGPHUP (0x56000078) /Pull-up control H现用G口、
21、H口举例说明。对于G口如表4.6、表4.7、表4.8,表4.6表4.7 (见下页)表4.8也就是说,在地址0x0x56000060中,给32位的每一位赋值,那么,在CPU的管脚上就定义了管脚的功能值。当G口某管脚配置成输出端口,则在PDATG对应的地址中的对应位上,写入1,则该管脚输出为高电平,写入0,则该管脚输出为低电平。若配置为功能管脚,则该管脚变成具体的功能脚。5. 实验步骤(1)本实验使用实验教学系统的CPU板,在进行本实验时,LCD电源开关、音频的左右声道开关、AD通道选择开关、触摸屏中断选择开关等均应处在关闭状态。(2)在PC机并口和实验箱的CPU板上的JTAG接口之间,连接WIG
22、GER调试电缆。(3)检查连接是否可靠,可靠后,接入电源线,系统上电,打开H_JTAG软件检测CPU。(4)打开ADS1.2开发环境,从里面打开实验程序HARDWAREADS实验五IO.mcp项目文件,进行编译。(5)编译通过后,进入ADS1.2调试界面,加载实验程序HARDWAREADS实验二IO_DataDebug中的映象文件程序映像IO.axf。(6)在ADS调试环境下全速运行映象文件。观察CPU板左下角的LED1、LED2灯轮流的的闪烁!这是对GPIO口操作的结果。6. 具体实现过程(1)将G端口的第8和第9位设置成输出端口。程序段如下:rGPGCON = rGPGCON & 0xff
23、f0ffff | 0x00050000;上面的操作就将GPGCON17:16和GPGCON19:18设置为了“01”,也即GPG8和GPG9为输出管脚。上述程序段也可写为:rGPGCON = rGPGCON & 0xfff5ffff(2)开机后,需要给两个LED一个初始状态(全亮或全灭)。程序段如下:rGPGDAT = rGPGDAT & 0xeff | 0x300;执行这一句后,两个LED全部熄灭。上面的程序也可以写为:rGPGDAT = rGPGDAT & 0x0300;(3)延时程序这里采用循环延时的方法来处理。程序段如下:for(i=0;i4000000;i+);程序运行到这一句后,i
24、将一直计数到4000000才会推出for循环。(4)死循环在C语言里,死循环可以表示为:for(;)或者while(1)。(5)主程序代码#include .INCconfig.hvoid Main(void) int i;Target_Init();rGPGCON = rGPGCON & 0xfff0ffff | 0x00050000;rGPGDAT = rGPGDAT & 0xeff | 0x300;for(i=0;i4000000;i+);for(i=0;i4000000;i+); for(;) rGPGDAT = rGPGDAT & 0xdff | 0x100; for(i=0;i40
25、00000;i+); /延时 for(i=0;i4000000;i+); /延时 rGPGDAT = rGPGDAT & 0xeff | 0x200; for(i=0;i4000000;i+); /延时for(i=0;i4000000;i+); /延时说明:在主程序的开头,包含了一个头文件config.h,#include .INCconfig.h这种写法的意思是包含当前目录下子目录INC中的config.h文件。包含这个文件的目的是包含一些S3C2410A执行程序时的必要的头文件,这里就有头文件2410ADDR.h。在今后的程序开发过程中,基本上都要包含config.h这个文件。另外函数Target_Init()的功能是对目标板进行初始化操作,在以后的程序开发过程中都要在主程序的开头调用这个函数。