集成开发环境的配置说明与ARM的SDRAM、LED、中断硬件原理及源程序
一、实验目的
(1)了解S3C2410X处理器的存储空间分配,学习实验台存储器接口电路原理,并能够对存储区空间进行配置,对存储区空间进行读写访问。
(2)学习实验台地址总线和数据总线的驱动缓冲电路原理,掌握利用S3C2410X处理器地址总线扩展的I/O来点亮LED、驱动蜂鸣器。
(3)掌握S3C2410X处理器中断响应过程,学习实验台外部中断输入电路的原理,掌握ARM中断处理程序的编写方法。
二、实验设备
硬件:EMBEST实验平台,ULINK2仿真器,PC机,串口线。
软件:uVision IDE for ARM集成开发环境。
三、实验内容
编写程序,当未按下实验箱上的按键KEY1或KEY2时,LED为常灭,当用户按下实验箱上的按键KEY1或者KEY2时,进入中断服务子程序。
在中断服务子程序中进行如下操作:驱动蜂鸣器响一声,然后驱动LED按规律的点亮和熄灭,接着程序修改SDRAM存储器地址0x30E00000——0x30F00000处的内容。
LED灯具体亮灭规律如下:LED1亮 —>LED2亮—>LED3 亮—>LED4亮 ->LED1灭—>LED2灭—>LED3灭 —>LED4 灭 —> 全亮—> 全灭—>全亮—>全灭。
修改SDRAM存储器时只对每个地址高半个字处写入1234,低半个字保持原来内容不变。
四、硬件电路原理
(1) 存储控制器特点及存储器连接原理
S3C2410X存储控制器主要特性包括:
a) S3C2410X具有27位地址总线,与8 个片选信号配合可寻址1GB存储空间。
b) 1GB可寻址存储空间划分为8个Bank,每个Bank的存储空间大小为128MB。片选信号线nGCS[0]~nGCS[7]与BANK0~BANK[7]对应。
c) BANK0~BANK5可配接ROM、SRAM类型的存储器;BANK6和BANK7可配接ROM、SRAM、SDRAM类型的存储器。
d) BANK0~BANK6 的起始地址是固定,BANK7的起始地址是可变的。
e) 每个BANK的数据总线宽度可设置,其中BANK0可设置为16/32位宽度;BANK1~BANK7可设置为8/16/32位宽度。
f) 支持NAND FLASH和NOR FLASH两种启动模式,启动模式和BANK0的总线宽度由OM[1:0]引脚决定。
实验箱核心板上有3种类型的存储器, NOR FLASH(一片Am29LV160DB),NAND FALSH(一片K9F1208),SDRAM(2片HY57V561620FTP) 。
NORFLASH的特点是应用程序可以直接在FLASH闪存内运行,不必再把代码读到系统RAM中。NOR FLASH的传输效率很高,在1~4MB的小容量时具有很高的成本效益,但是很低的写入和擦除速度大大影响了它的性能。
而NAND FLASH在芯片面积、单元密度、容量、写入数据速度、功耗、使用寿命和成本等方面具有明显优势,但NAND FLASH需要特殊的管理和控制接口。
SDRAM的存储容量大、读写速度快、支持突发式读写,在本系统中两片HY57V561620FTP并联组成位宽32位、存储容量共64MB的SDRAM存储体,用作主内存。
核心板上BOOT跳线可以选择是NAND FLASH启动还是NOR FLASH启动:BOOT跳线断开时为NOR FLASH启动方式,数据总线宽度为16位;BOOT跳线合上时为NAND FLASH启动方式,数据总线宽度为8位。
NANDFLASH和NOR FLASH两种启动模式的存储空间分配如图4-1所示。
图4-1 存储空间分配图
注:(1)SROM表示存储类型为ROM或者SRAM
(2)本次实验将程序下载到NOR FLASH中运行,所以跳线断开。程序中对地址为0x30E00000——0x30F00000处的内容进行读写访问也即访问SDRAM存储器中内容。
SDRAM的电路连接原理图如图4-2所示:nGCS6(nSCS0)与片选信号相连,表明SDRAM占用BANK6,实际的物理地址为0x30E00000——0x33FFFFFF。
图4-2 SDRAM的电路连接原理图
(2) 地址总线扩展I/O
实验台上有4个状态可编程的LED灯(LED1~LED4),这四个LED的状态通过扩展的I/O接口进行控制。
所用的扩展I/O电路原理图如图4-3和4-4所示。
图4-3为S3C2410地址线和数据线经过驱动缓冲芯片74LVTH162245后,作为外设电路的总线信号。74LVTH162245芯片提高了总线的驱动能力、又隔离了外设电路。
图4-4为LED灯和BEEP蜂鸣器驱动电路原理图。
图4-3 地址总线、数据总线原理图
图4-4 LED和BEEP控制原理图
图4-4中利用3/8译码器将地址线A18-A20扩展了7个片选信号CS1-CS7 。其中 CS5 , CS6 , CS7 3 个片选信号和写使能信号WE通过 74HC32 或门输出一个选通信号OLE (低电平有效)。 OLE3 选通信号经过 74HC04 反相得到高电平连接给扩展输出芯片 74HC573 的使能端LE。
数据线DB0-DB7经过74LVTH162245驱动缓冲后再经过MC74VHC245驱动(即经过了两级驱动)后给具有锁存的D触发器74VHC573DT芯片。D触发器的输出B1-B4用于驱动4个LED,B8用于驱动蜂鸣器。
由原理图可知,芯片74HC573 DT的物理选通地址为0x21180000,当访问这个物理地址时,就可以访问其上的硬件资源了。这里可以把其理解为一个寄存器,寄存器地址是0x21180000,它的第四位控制了4个LED,它的第8位控制了蜂鸣器。
(3)按键中断
S3C2410的中断控制器可以从60个中断源接收中断请求,这些中断源可分为内部中断和外部中断。内部中断有内部外设如DMA控制器、UART、IIC等功能模块产生;外部中断有24个,输入引脚EINTn与GPF和GPG端口复用。
本次实验主要用到实验平台主板上的两路外部按键,当键被按下时,会产生按键中断信号。按键产生的中断信号经过CPLD逻辑处理后连接到CPU的中断引脚 INT9。
图4-5 按键中断框图
CPLD的内部逻辑如图4-6所示:
图4-6 CPLD中断部分逻辑原理图
如图4-6所示为CPLD 扩展中断。ISAIRQ0~ISAIRQ7 、IRQNET、IRQKEY 、EINT0 、EINT1 等信号是外部设备的中断信号, 它们作为CPLD 芯片的输入。CPLD 芯片上设计了两个中断控制器:CtrlReg0 与 CtrlReg1 , 设计了两个状态寄存器StatusReg0 与 StatusReg1 。 从图4-6可以看出,按键中断EINT0 是由中断控制器CtrlReg1 来控制的,状态寄存器 StatusReg1 每个位分别实时反映了一个外部中断信号的状态,按键中断EINT0 与其它外部中断(如IRQCAN、IRQCF等)共享了CPU中断INT9,在初始状态, 这些引脚信号为高电平。
表 4-1 中断控制寄存器 CtrlReg1 (地址 0x26600000 )
BIT7 |
BIT6 |
BIT5 |
BIT4 |
BIT3 |
BIT2 |
BIT1 |
BIT0 |
IRQNET |
IRQKEY |
IRQCF |
IRQCAN |
Reserved |
EINT1 |
EINT0 |
Reserved |
中断控制寄存器 CtrlReg1 是 8 位只写寄存器。它的每个位分别控制了一个外部中断。 其中按键中断EINT1位于 BIT2 位。往寄存器相应位写 1 ,则相应中断被屏蔽;相应位清零,则相应中断被打开。
表 4-2 中断状态寄存器 StatusReg1 (地址 0x06200000 )
BIT7 |
BIT6 |
BIT5 |
BIT4 |
BIT3 |
BIT2 |
BIT1 |
BIT0 |
IRQNET |
IRQKEY |
IRQCF |
IRQCAN |
Reserved |
EINT1 |
EINT0 |
Reserved |
状态寄存器 StatusReg1 是 8 位只读寄存器。它的每个位分别实时反映了一个外部中断信号的状态,其中 BIT2 位反映了按键中断 EINT0 的状态, 比如当前按建 KEY2 没有键按下, 则中断信号引脚 EINT1为高电平, 此时寄存器 StatusReg1 的 BIT2 位也为高电平; 当有键按下, EINT1 变为低电平,则 StatusReg1 的 BIT2位也变为低电平。
五、软件部分说明
(1) 工程配置
在集成开发环境中选择project-Option for target选项进行工程配置。主要对Target配置页面、Linker配置页面、Debug配置页面以及Utilities配置页面作一说明。
图5-1 Target配置页面
图5-2 Linker配置页
Linker即链接器/定位器用于将目标模块进行段合并,并对其定位,生成程序。有三种方式配置链接器。
本此实验中勾选Use Memory Layout fromTarget Dialog选项,则MDK默认在Target中对FLASH和RAM的地址配置,编译链接时会产生一个默认的分散加载文件,最后链接器会根据此文件中的信息对目标文件进行链接,生成axf镜像文件。
图5-3 Debug配置页面
图5-4 Utilities工具选项卡配置
调试脚本文件除了可以初始化软/硬件的调试环境以外,还可以初始化Flash的烧写环境,此处的FLASH.ini调试脚本文件是在进行FLASH下载程序时,对目标板的硬件环境的配置。
(2) 程序设计
在建立工程时可以自动添加S3C2410的启动文件,该文件是用混编语言编写。主要完成系统的硬件初始化操作。用户可以利用图形化界面来进行初始化配置,修改图形界面上的内容后,MDK能自动实时更新启动文件中的内容。
图5-5 启动代码的图形配置界面
如图5-5所示,以堆栈配置为例,只要修改各堆栈对应Value一栏的值即可初始化各堆栈大小。
由于我们选择在C语言程序中进行大部分的初始化操作(时钟、中断、I/O端口初始化),所以本实验启动代码使用默认设置即可(主要是堆的设置、栈的设置、存储控制器设置)。
程序流程图如图所示:
图程序流程图
由于例程中都已经完成初始化配置,仅以时钟配置为例作说明。
时钟配置由如下两个公式给出:
Mpll配置:选择 M=0Xc3 Fin=12MHz p=0x04 s=0x01 Mpll=202.8MHz
Upll配置:选择M=0x78 Fin=12MHz p=0x02 s=0x03 Upll=48MHz
六、实验结果
(1)对SDRAM存储器地址0x30E00000——0x30F00000处的内容进行写数据操作。SDRAM中每个地址高半个字处写入1234,低半个字保持原来内容不变。
在调试窗口中观察地址从0x30e00000开始的内容,结果如图6-1所示。
图 6-1 存储器地址中的内容
(2)为了验证在脱离仿真调试模式下,对存储器写操作的正确性,程序又对0x30e00000中的内容修改为0xfffffff0,并从该地址出读出数据驱动4个LED。
图6-2 修改了0x30e00000地址处的内容
(3) LEED和BEEP蜂鸣器运行结果请看视频演示。
7.实验部分源代码
#define rCPLDIntControl (*(volatile unsigned char*)0x22600000)
#define rCPLDIntStatus (*(volatile unsigned char*)0x22200000)
#define rCPLDLEDADDR (*(volatile unsigned char*)0x21180000)
#define rCPLDBEEPADDR (*(volatile unsigned char*)0x21180000)
voidint_init(void) // 中断初始化函数
{
rSRCPND =rSRCPND; // 清楚中断请求标志
rINTPND = rINTPND; //清楚挂起寄存器
rGPGCON|= (0xf<<0);
rGPGCON &=(0xa<<0); //设置端口GPG1为INT9,GPG0为INT8
rCPLDIntControl= 0xFF;
rCPLDIntControl= 0xF9; //CPLD控制寄存器中断按键中断
pISR_EINT8_23=(UINT32T)int_int; //中断服务子程序入口地址
rEINTPEND= 0xffffff; //清楚外部中断请求标志
rEXTINT1 &=~((0x7<<4)|(0x7<<0));
rEXTINT1|= ((0x2<<4)|(0x2<<0)); //设置中断触发方式
rEINTMASK&= ~(3<<8); //允许外部中断EINT9、EINT8
rINTMSK &= ~(BIT_EINT8_23); //设置中断屏蔽寄存器允许
}
void __irqint_int(void) //中断服务子程序
{
unsigned char Status;
UINT32T*pt;
unsignedint j,k;
Status =rCPLDIntStatus;
Status =~(Status & 0x6);
rCPLDBEEPADDR=0xFF;
k=rCPLDBEEPADDR;
j=~(1<<7);
rCPLDBEEPADDR&= ~(1<<7);
j=rCPLDBEEPADDR;
delay(3000);
rCPLDBEEPADDR|=(1<<7);
j=rCPLDBEEPADDR;
led_on();
led_off();
led_on_off();
led_on_off();
pt=(UINT32T*)(_RAM_STARTADDRESS + 0x00E00000);
while((UINT32T)pt< (_RAM_STARTADDRESS + 0x00F00000))
{
j=*pt&0x0000FFFF;
*pt=0x12340000+j;
pt=pt++;
}
uart_printf("EINT1 interrupt occurred.\n");
pt=pt--;
uart_printf("\n%d",*pt);
rCPLDIntControl|= (1<<2);
rCPLDIntControl&= ~(1<<2);
rEINTPEND=(1<<9);
ClearPending(BIT_EINT8_23);
}
void led_off(void) //灯熄灭控制程序
{
inti,nOut;
nOut =0xF0;
rCPLDLEDADDR= nOut | 0x01;
for(i =0; i < 300000; i++);
rCPLDLEDADDR= nOut | 0x03;
for(i =0; i < 300000; i++);
rCPLDLEDADDR= nOut | 0x07;
for(i =0; i < 300000; i++);
rCPLDLEDADDR= nOut | 0x0F;
for(i =0; i <300000; i++);
}
void led_on(void) //灯点亮控制程序
{
inti,nOut;
nOut =0xFF;
rCPLDLEDADDR= nOut & 0xFE;
for(i =0; i < 300000; i++);
rCPLDLEDADDR= nOut & 0xFC;
for(i = 0;i < 300000; i++);
rCPLDLEDADDR= nOut & 0xF8;
for(i =0; i < 300000; i++);
rCPLDLEDADDR= nOut & 0xF0;
for(i =0; i < 300000; i++);
}
void led_on_off(void) //小灯亮灭控制
{
int i;
rCPLDLEDADDR= 0xF0;
for(i =0; i < 200000; i++);
rCPLDLEDADDR= 0xFF;
for(i =0; i < 200000; i++);
}
void int_test(void) //主程序部分
{
uart_printf("\nExternal Interrupt Test Example\n");
int_init();
rCPLDBEEPADDR=0xFF;
rCPLDLEDADDR= 0xFF;
while(1)
{
rCPLDLEDADDR = 0xFE;
}
}