学ARM之路,任重道远
时间:2008-09-18
来源:hezhiwen
- 为手持设备和通用嵌入式应用提供片上集成系统解决方案
- 采用ARM920T CPU内核,具有16/32位RISC体系结构和强大的指令集
- 增强的ARM体系结构MMU,支持WinCE、EPOC 32和Linux
- 指令Cache、数据Cache、写缓冲器和物理地址TAG RAM的使用降低了主存带宽和延时对性能的影响
- ARM920T CPU内核支持ARM测试体系结构
- 内部采用先进的微控制总线体系结构(AMBA)(AMBA2.0,AHB/APB)
2.系统管理器
- 支持小/大端方式
- 寻址空间:每bank 128MB(总共1GB)
- 每个bank支持可编程的8/16/32位数据总线带宽
- bank0~bank6都采用固定的bank起始地址
- bank7具有可编程的bank起始地址和大小
- 8个存储器bank:
--6个用于ROM、SRAM及其他
--2个用于ROM、SRAM和同步SDRAM
- 所有存储器bank的访问周期都是可编程的
-
支持使用外部等待信号来填充总线周期
-
支持掉电时的SDRAM自刷新模式
-
支持各种类型的ROM启动,包括NOR/NAND Flash和EEPROM
3.NAND Flash启动装载器
- 支持从NAND Flash存储器的启动
- 采用4KB内部缓冲器用于启动引导
- 支持启动之后NAND存储器仍然作为外部存储器使用
4.Cache存储器
- 16KB的I-Cache(指令高速存储缓冲器)和16KB的D-Cache(数据高速存储缓冲器)为64路组相联Cache
- 每行8字长度,其中每行带一个有效位和两个脏位
- 采用伪随机数和轮转替换算法
- 采用写直达或写回Cache操作来更新主存储器
- 写缓冲器可以保存16个字的数据值和4个地址值
5.时钟和电源管理
- 片上MPLL和UPLL:
--UPLL产生操作USB主机/设备的时钟
--MPLL产生操作MCU的时钟,在2.0V内核电压下时钟频率最高可达266MHz
- 通过软件可以有选择地为每个功能模块提供时钟
- 电源模式包括正常、慢速、空闲和掉电模式:
--正常模式 正常运行模式
--慢速模式 不加PLL的低时钟频率模式
--空闲模式 只停止CPU的时钟
--掉电模式 所以外设和内核的电源都切断了
- 可以通过EINT[15:0]或RTC报警中断从掉电模式中唤醒处理器
6.中断控制器
- 55个中断源(1个看门狗定时器、5个定时器、9个UART、24个外部中断、4个DMA、2个RTC、2个ADC、1个I2C、2个SPI、1个SDI、2个USB、1个LCD和1个电池故障)
- 电平/边沿触发模式的外部中断源
- 可编程的电平/边沿触发极性
- 支持为紧急中断请求提供快速中断服务(FIQ)
7.具有脉冲带宽调制(PWM)的定时器
- 4通道16位具有PWM功能的定时器,1通道16位可基于DMA或中断工作的内部定时器
- 可编程的占空比周期、频率和极性
- 能产生死区
- 支持外部时钟源
8.RTC(实时时钟)
- 完整的时钟特性:秒、分、时、日期、星期、月和年
- 32.768kHz工作频率
- 具有报警中断
- 具有时钟滴答中断
9.通用I/O口
- 24个外部中断口
- 多路复用的I/O口
10.UART
- 3通道UART,可以基于DMA模式或中断模式工作
- 支持5、6、7、或者8位串行数据发送/接收(Tx/Rx)
- 支持外部时钟作为UART的运行时钟(UEXTCLK)
- 可编程的波特率
- 支持IrDA1.0
- 支持回环(Loopback)测试模式
- 每个通道都具有内部16字节的发送FIFO和16位字节的接收FIFO
11.DMA控制器
- 4通道的DMA控制器
- 支持存储器到存储器、I/O到存储器、存储器到I/O和I/O到I/O的传送
- 采用突发传送模式来加快传送速率
12.A/D转换和触摸屏接口
- 8通道多路复用ADC
- 转换速率最大为500KSPS(Kilo Samples Per Second,千采样点每秒),10位分辨率
13.LCD控制器STN LCD显示特性
- 支持3种类型的STN LCD显示屏:4位双扫描、4位单扫描和8位单扫描显示类型
- STN LCD支持单色模式、4级灰度、16级灰度、256色和4096色
- 支持多种屏幕尺寸,典型的屏幕尺寸有:640*480,320*240,160*160
- 最大虚拟屏幕大小是4KB
- 256色模式下支持的最大虚拟屏幕尺寸是:4096*1024,2048*2048,1024*4096
14.TFT(Thin Film Transistor,薄膜场效应晶体管)彩色显示特性
- 彩色TFT支持1、2、4或8 bpp(bit per pixel,每像素所占位数)调色显示
- 支持16 bpp无调色真彩显示
- 在24 bpp模式下支持最大16M色TFT
- 支持多种屏幕尺寸,典型的屏幕尺寸有:640*480,320*240,160*160
- 最大虚拟屏幕大小是4KB
- 64色模式下支持的最大虚拟屏幕尺寸是:2048*1024
15.看门狗定时器
- 16位看门狗定时器
- 定时器溢出时发生中断请求或系统复位
16.I2C总线接口
- 1通道多主机I2C总线
- 串行、8位、双向数据传送,在标准模式下数据传送速率可达100kb/s,在快速模式可达400kb/s
17.I2S总线接口
- 1通道音频I2S总线接口,可基于DMA方式工作
- 串行,每通道8/16位数据传输
- 发送和接收具备128字节(64字节发送FIFO+64字节接收FIFO)FIFO
- 支持I2S格式和MSB-justified数据格式
18.USB主设备
- 2个USB主设备接口
- 遵从OHCI Rev1.0标准
- 兼容USB Ver1.1标准
19.SUB从设备
- 1个USB从设备接口
- 具备5个端口(Endpoint,指USB的传输通道)
- 兼容USB Ver1.1标准
20.SD主机接口
- 兼容SD存储卡协议1.0版
- 兼容SDIO卡协议1.0版
- 发送和接收采用字节FIFO
- 基于DMA或中断模式工作
- 兼容MMC卡协议2.11版
21.SPI接口
- 兼容2通道SPI协议2.11版
- 发送和接收采用2字节的移位寄存器
- 基于DMA或中断模式工作
22.工作电压
- 内核:1.8V,最高工作频率200MHz(S3C2410A-20)
2.0V, 最高工作频率266MHz(S3C2410A-26)
- 存储器和I/O:3.3V
23.封装
- 272-FBGA封装
------存储器控制器------
- 支持小端/大端(通过软件选择)
- 寻址空间:每个bank有128MB(总共有8个bank,共1GB)
- 除bank0(只能是16/32位宽)之外,其他bank都具有可编程的访问大小(可以是8/16/32位宽)
- 总共8个存储器bank(bank0~bank7):
--其中6个用于ROM、SRAM等
--另外2个用于ROM、SRAM、SDRAM等
- 7个固定的存储器bank(bank0~bank6)起始地址
- 最后一个bank(bank7)的起始地址是可调整的
- 最后两个bank(bank6和bank7)的大小是可编程的
- 所有存储器bank的访问周期都是可编程的
- 总线访问周期可以通过插入外部等待来延长
- 支持SDRAM的自刷新和掉电模式


- NAND Flash模式:支持读/擦除/编程NAND Flash存储器。
- 自动启动模式:复位后,启动代码被传送到Steppingstone中。传送完毕后,启动代码在Steppingstone中执行。
- 具备硬件ECC(校验码:Error Correction Code)生成模块(硬件生成校验码,通过软件校验)
- NAND Flash启动以后,4KB的内部SRAM缓冲器Steppingstone可以作为其他用途使用。
- NAND Flash控制器不能通过DMA访问,可以使用LDM/STM指令来代替DMA操作。
自启动模式的执行步骤如下:
(1)完成复位
(2)如果自动启动模式使能,NAND Flash存储器的前4KB自动复制到Steppingstone内部缓冲器;
(3)Steppingstone映射到nGCS0;
(4)CPU在Steppingstone的4KB内部缓冲器中开始执行启动代码。
注意:在自动启动模式下,不进行ECC检测。因此,应确保NAND Flash的前4KB不能有位错误(一般NAND Flash厂家都能确保)。
NAND Flash模式需要进行以下配置:
(1)通过NFCONF寄存器设置NAND Flash配置;
(2)将NAND Flash命令写入NFCONF寄存器;
(3)将NAND Flash地址写入NFADDR寄存器;
(4)通过NFSTAT寄存器检查NAND Flash状态,并读/写数据。在读操作之前或者编程操作之后应该检查R/nB信号。
引脚配置 D[7:0] 数据/命令/地址的输入/输出口(与数据总线共享) CLE 命令锁存使能(输出) ALE 地址锁存使能(输出) nFCE NAND Flash片选使能(输出) nFRE NAND Flash读使能(输出) nFWE NAND Flash写使能(输出) R/nB NAND Flash就绪/忙(输入) 系统启动和NAND Flash所需的配置如下: (1)OM[1:0]=00b:使能NAND Flash控制器为自动启动模式; (2)NAND Flash存储器的页面大小应该为512字节; (3)NCON:NAND Flash存储器寻址步数选择。0为3步;1为4步寻址。 相关寄存器 NAND Flash配置寄存器 NFCONF 地址0x4E000000 NAND Flash命令设置寄存器 NFCMD 地址0x4E000004 NAND Flash地址设置寄存器 NFADDR 地址0x4E000008 NAND Flash数据寄存器 NFDATA 地址0x4E00000C NAND Flash操作状态寄存器 NFSTAT 地址0x4E000010 NAND Flash ECC寄存器 NFECC 地址0x4E000014 ------时钟和电源管理------ 时钟和电源管理模块包括3部分:时钟控制、USB控制和电源控制。 S3C2410A中的时钟控制逻辑能够产生CPU所需的FCLK时钟信号、AHB总线外围设备所需的HCLK时钟信号,以及APB总线外围设备所需的PCLK时钟信号。S3C2410A有两个锁相环(PLL,Phase Locked Loops):一个用于FCLK、HCLK和PCLK,另一个专门用于USB模块(48MHz)。时钟控制逻辑可以在不需要PLL的情况下产生慢速时钟,并且可以通过软件来控制时钟与每个外围模块是连接还是断开,从而降低功耗。 S3C2410A中的电源管理模块可以激活4种模式:正常模式、慢速模式、空闲模式和掉电模式。 (1)正常模式:此模式下,电源管理模块为CPU和S3C2410A中的所有外围设备都提供时钟。功耗最大。用户可以通过软件来控制外围设备是否提供时钟的操作。 (2)慢速模式:又称无PLL模式。使用外部时钟(XTlpll或EXTCLK)直接作为S3C2410A中的FCLK,而不使用PLL。 (3)空闲模式:只断开CPU内核的时钟(FCLK),但仍为所有其他外围设备提供时钟。任何中断请求都可以在空闲模式下唤醒CPU。 (4)掉电模式:电源管理模块断开内部电源。通过EINT[15:0]或者RTC报警中断可以实现从掉电模式唤醒。 时钟源选择 由OM[3:2]决定 OM[3:2] MPLL状态 UPLL状态 主时钟源 USB时钟源 00 On On 晶体 晶体 01 On On 晶体 外部 10 On On 外部 晶体 11 On On 外部 外部 相关寄存器 时间锁存计数寄存器: LOCKTIME 地址0x4C000000 PLL控制寄存器: MPLLCON 地址0x4C000004 UPLLCON 地址0x4C000008 PLLCON Bit MDIV [19:12] PDIV [9:4] SDIV [1:0] 公式:Mpll=(m*Fin)/(p*2的s次方) m=(MDIV+8),p=(PDIV+2),s=SDIV PLL值选择列表(可参考以设置PLLCON)
I/O口
S3C2410A共有117个多功能复用输入/输出口(I/O口),分为8组,即PORT A~PORT H,8组I/O口按照其位数的不同,可分为:
- 1个23位输出口(PORT A)
- 2个11位I/O口(PORT B和PORT H)
- 4个16位I/O口(PORT C、PORT D、PORT E和PORT G)
- 1个8位I/O口(PORT F)
具体的I/O口配置见S3C2410A芯片手册
在S3C2410A中,大部分引脚都是复用的,所有需要对每一个引脚定义其功能。为了使用I/O口,首先也要定义引脚的功能。配置这些端口,是通过设置一 系列寄存器来实现的。与配置I/O都相关的寄存器包括:端口控制寄存器(GPACON~GPHCON)、端口数据寄存器(GPADAT~GPHDAT)、 端口上拉寄存器(GPBUP~GPHUP)、杂项控制寄存器以及外部中断屏蔽寄存器(EXTINTN)等。所有GPIO寄存器的值在掉电模式下都会被保 存。外部中断屏蔽寄存器EINTMASK不能阻止从掉电模式唤醒,但是如果EINTMASK正在屏蔽的是EINT[15:4]中的某位,则可以实现唤醒, 不过中断源挂起寄存器SRCPND的位EINT4_7和EINT8_23在刚刚唤醒后不置1。
端口控制寄存器用于定义每个引脚的功能。如果GPF0~GPF7和GPG0~GPG7用作掉电模式下的唤醒信号,那么这些端口必须在中断模式下配置。
如果将端口配置为输出口,数据可以写入到端口数据寄存器的相应位中;如果将端口配置为输入口,则可以从端口数据寄存器的相应位中读出数据。
端口上拉寄存器用于控制每组端口的上拉电阻为禁止还是使能。如果相应位设置为0,则表示该引脚的上拉电阻使能;为1,则表示上拉电阻禁止。如果使能了端口上拉寄存器,则不论引脚配置为哪种功能,上拉电阻都会起作用。
杂项控制寄存器用于控制数据端口的上拉电阻、高阻状态、USB Pad和CLKOUT的选择。
24个外部中断通过不同的信号被请求。EXTINTn寄存器用于配置这些信号对于外部中断请求采用的是低电平触发、高电平触发、下降沿触发、上升沿触发还是双边沿触发。
下面对相关寄存器的设置分别进行描述:
1.PORT A控制寄存器:
GPACON 地址0x56000000
配置A口的引脚,使用位[22:0]
0:输出引脚
1:输入引脚
GPADAT 地址0x56000004
A口的数据寄存器,使用位[22:0]
保留 地址0x56000008
保留 地址0x5600000C
2.PORT B控制寄存器:
GPBCON 地址0x56000010
配置B口的引脚,使用位[21:0]分别对B口的相应11个位进行配置。
00:输入 01:输出
10:功能引脚 11:保留
GPBDAT 地址0x56000014
B口的数据寄存器,使用位[10:0]
GPBUP 地址0x56000018
B口的上拉电阻禁止寄存器,使用位[10:0]
1表示禁止 0表示使能
保留 地址0x5600001C
3.PORT C控制寄存器:
GPCCON 地址0x56000020
配置C口的引脚,使用位[31:0]分别对C口的相应16个位进行配置。
00:输入 01:输出
10:功能引脚 11:保留
GPCDAT 地址0x56000024
C口的数据寄存器,使用位[15:0]
GPCUP 地址0x56000028
C口的上拉电阻禁止寄存器,使用位[15:0]
1表示禁止 0表示使能
保留 地址0x5600002C
4.PORT D控制寄存器:
GPDCON 地址0x56000030
配置D口的引脚,使用位[31:0]分别对D口的相应16个位进行配置。
00:输入 01:输出
10:功能引脚 11:保留/另一功能引脚
GPDDAT 地址0x56000034
D口的数据寄存器,使用位[15:0]
GPDUP 地址0x56000038
D口的上拉电阻禁止寄存器,使用位[15:0]
1表示禁止 0表示使能
保留 地址0x5600003C
5.PORT E控制寄存器:
GPECON 地址0x56000040
配置E口的引脚,使用位[31:0]分别对E口的相应16个位进行配置。
00:输入 01:输出
10:功能引脚 11:保留/另一功能引脚
GPEDAT 地址0x56000044
E口的数据寄存器,使用位[15:0]
GPEUP 地址0x56000048
E口的上拉电阻禁止寄存器,使用位[15:0]
1表示禁止 0表示使能
保留 地址0x5600004C
6.PORT F控制寄存器:
GPFCON 地址0x56000050
配置F口的引脚,使用位[15:0]分别对F口的相应8个位进行配置。
00:输入 01:输出
10:功能引脚 11:保留
GPFDAT 地址0x56000054
F口的数据寄存器,使用位[7:0]
GPFUP 地址0x56000058
F口的上拉电阻禁止寄存器,使用位[7:0]
1表示禁止 0表示使能
保留 地址0x5600005C
7.PORT G控制寄存器:
GPGCON 地址0x56000060
配置G口的引脚,使用位[31:0]分别对G口的相应16个位进行配置。
00:输入 01:输出
10:功能引脚 11:保留/另一功能引脚
GPGDAT 地址0x56000064
G口的数据寄存器,使用位[15:0]
GPGUP 地址0x56000068
G口的上拉电阻禁止寄存器,使用位[15:0]
1表示禁止 0表示使能
保留 地址0x5600006C
8.PORT H控制寄存器:
GPHCON 地址0x56000070
配置D口的引脚,使用位[21:0]分别对D口的相应11个位进行配置。
00:输入 01:输出
10:功能引脚 11:保留/另一功能引脚
GPHDAT 地址0x56000074
H口的数据寄存器,使用位[10:0]
GPHUP 地址0x56000078
H口的上拉电阻禁止寄存器,使用位[10:0]
1表示禁止 0表示使能
保留 地址0x5600007C
9.杂项控制寄存器:
MISCCR 地址0x56000080
控制数据端口的上拉电阻、高阻状态、USB Pad和CLKOUT的选择
10.DCLK控制寄存器:
DCLKCON 地址0x56000084
DCLK0/1控制寄存器,位[27:16]控制DCLK1,位[11:0]控制DCLK0
11.外部中断控制寄存器:
EXTINT0 地址0x56000088
EXTINT1 地址0x5600008C
EXTINT2 地址0x56000090
12.外部中断滤波寄存器:
EINTFLT0 地址0x56000094
EINTFLT1 地址0x56000098
EINTFLT2 地址0x5600009C
控制EINT19~EINT16的滤波时钟和滤波宽度
EINTFLT3 地址0x560000A0
控制EINT23~EINT20的滤波时钟和滤波宽度
13.外部中断屏蔽寄存器:
EINTMASK 地址0x560000A4
使用位[23:4]分别对EINT23~EINT4设置是否屏蔽相应中断
0:使能中断 1:屏蔽中断
14.外部中断挂起寄存器:
EINTPEND 地址0x560000A8
使用位[23:4]分别对EINT23~EINT4设置是否请求中断挂起
0:不请求挂起 1:请求挂起
15.通用状态寄存器:
GSTATUS0 地址0x560000AC
外部引脚状态
GSTATUS1 地址0x560000B0
芯片ID
GSTATUS2 地址0x560000B4
复位状态
GSTATUS3 地址0x560000B8
通知(Inform)寄存器。可被复位信号nRESET或看门狗定时器清零
GSTATUS4 地址0x560000BC
通知(Inform)寄存器。可被复位信号nRESET或看门狗定时器清零
I/O口编程实例
I/O口编程实例
通过一个对G口的操作实例控制LED1和LED2实现轮流闪烁
对I/O口的操作是通过对相关寄存器的读/写实现的。要对寄存器进行读/写操作,首先要对寄存器进行定义。有关I/O相关寄存器的宏定义代码如下:
#define rGPACON (*(volatile unsigned*)0x56000000) //Port A控制寄存器
#define rGPADAT (*(volatile unsigned*)0x56000004) //Port A数据寄存器
#define rGPBCON (*(volatile unsigned*)0x56000010) //Port B控制寄存器
#define rGPBDAT (*(volatile unsigned*)0x56000014) //Port B数据寄存器
#define rGPBUP (*(volatile unsigned*)0x56000018) //Port B上拉电阻禁止寄存器
#define rGPCCON (*(volatile unsigned*)0x56000020) //Port C控制寄存器
#define rGPCDAT (*(volatile unsigned*)0x56000024) //Port C数据寄存器
#define rGPCUP (*(volatile unsigned*)0x56000028) //Port C上拉电阻禁止寄存器
#define rGPDCON (*(volatile unsigned*)0x56000030) //Port D控制寄存器
#define rGPDDAT (*(volatile unsigned*)0x56000034) //Port D数据寄存器
#define rGPDUP (*(volatile unsigned*)0x56000038) //Port D上拉电阻禁止寄存器
#define rGPECON (*(volatile unsigned*)0x56000040) //Port E控制寄存器
#define rGPEDAT (*(volatile unsigned*)0x56000044) //Port E数据寄存器
#define rGPEUP (*(volatile unsigned*)0x56000048) //Port E上拉电阻禁止寄存器
#define rGPFCON (*(volatile unsigned*)0x56000050) //Port F控制寄存器
#define rGPFDAT (*(volatile unsigned*)0x56000054) //Port F数据寄存器
#define rGPFUP (*(volatile unsigned*)0x56000058) //Port F上拉电阻禁止寄存器
#define rGPGCON (*(volatile unsigned*)0x56000060) //Port G控制寄存器
#define rGPGDAT (*(volatile unsigned*)0x56000064) //Port G数据寄存器
#define rGPGUP (*(volatile unsigned*)0x56000068) //Port G上拉电阻禁止寄存器
#define rGPHCON (*(volatile unsigned*)0x56000070) //Port H控制寄存器
#define rGPHDAT (*(volatile unsigned*)0x56000074) //Port H数据寄存器
#define rGPHUP (*(volatile unsigned*)0x56000078) //Port H上拉电阻禁止寄存器
要想实现对G口的配置,只要在地址0x56000060中给32位的每一位赋值就可以了。如果G口的某个引脚被配置为输出引脚,在PDATG对应的地址位写入1时该引脚输出高电平;写入0时该引脚输出低电平。如果该引脚被配置为功能引脚,则该引脚作为相应的功能引脚使用。
下面是实现LED1和LED2轮流闪烁的程序代码:
void Main(void){
int flag,i;
Target_Init();//进行硬件初始化操作,包括对I/O口的初始化操作
for(; ;){
if(flag==0){
for(i=0;i<1000000;i++); //延时
rGPGCON=rGPGCON&0xfff0ffff|0x00050000; //配置第8、第9位为输出引脚
rGPGDAT=rGPGDAT&0xeff|0x200; //第8位输出为低电平
//第9位输出为高电平
for(i=0;i<10000000;i++); //延时
flag=1;
}
else{
for(i=0;i<1000000;i++); //延时
rGPGCON=rGPGCON&0xfff0ffff|0x00050000; //配置第8、第9位为输出引脚
rGPGDAT=rGPGDAT&0xdff|0x100; //第8位输出为高电平
//第9位输出为低电平
for(i=0;i<10000000;i++); //延时
flag=0;
}
}
}
中断
中断编程实例
今天是愚人节,先祝大家节日快乐。哈哈~~~~~~~~~~~~~~~ 由于近段时间工作比较忙,好久没写东西了,在此给自己加油,努力努力,坚持下去,学ARM之路,任重道远!!!!!!!革命尚未成功,同志仍需努力!继续。 介绍一个通过定时器1中断控制CPU板上的LED1和LED2实现轮流闪烁的实例,需要完成的主要工作如下: (1)对定时器1初始化,并设定定时器的中断时间为1s,据代码参见Timer1_init()函数。 void Timer1_init(void){ rGPCON=rGPGCON&0xfff0ffff|0x00050000;//配置GPG口为输出口 rGPGDAT=rGPGDAT|0x300; rTCFG0=255; rTCFG1=0<<4; rTCNTB1=48828;//在pclk=50MHz下,1s的记数值rTCNTB1=50000000/4/256=48828 rTCMPB1=0x00; rTCON=(1<<11)|(1<<9)|(0<<8);//禁用定时器1,手动加载 rTCON=(1<<11)|(0<<9)|(1<<8);//启动定时器1,手动加载 } (2)为了使CPU响应中断,在中断服务子程序执行之前,必须打开ARM920T的CPSR中的I位,以及相应的中断屏蔽寄存器中的位。打开相应的中断屏蔽寄存器的位,是在Timer1INT_Init()函数中实现,具体代码如下。 void Timer1INT_Init(void){ //定时器接口使能 if((rINTPND&BIT_TIMER1)){ rSRCPND|=BIT_TIMER1; } pISR_TIMER1=(int)Timer1_ISR; //写入定时器1中断服务子程序的入口地址 rINTMSK &=~(BIT_TIMER1); //开中断 } (3)等待定时器中断,通过一个死循环如“while(1);”实现等待过程。 (4)根据设置的定时时间,产生定时器中断。中断发生后,首先进行现场保护,然后转入中断的入口代码处执行。该部分代码通常使用汇编语言编写。在执行中断服务程序之前,要确保HandleIRQ地址处保存中断分发程序IsrIRQ的入口地址,代码如下。 ldr r0,=HandleIRQ ldr r1,=IsrIRQ str r1,[r0] 接下来将执行IsrIRQ中断分发程序,具体代码如下。 IsrIRQ sub sp,sp,#4 ;为保存PC预留堆栈空间 stmfd sp!,{r8-r9} ldr r9,=INTOFFSET ldr r9,[r9] ;加载INTOFFSET寄存器值到r9 ldr r8,=HandleEINT0 ;加载中断向量表的基地址到r8 add r8,r8,r9,lsl #2 ;获得中断向量 ldr r8,[r8] ;加载中断服务程序的入口地址到r8 str r8,[sp,#8] ;保存sp,将其作为新的pc值 ldmfd sp!,{r8-r9,pc} ;跳转到新的pc处执行,即跳转到中断服务子程序执行 (5)执行中断服务子程序,该子程序实现将LED1和LED2灯熄灭或点亮。从现象中看到LED1和LED2灯闪烁一次,就说明定时器发生了一次中断。具体实现见函数Timer1_ISR(). int flag; void_ _irq Timer1_ISR(void){ if(flag==0){ rGPGDAT=rGPGDAT&0xeff|0x200; flag=1; } else{ rGPGDAT=rGPGDAT&0xdff|0x100; flag=0; } rSRCPND|=BIT_TIMER1; rINTPND|=BIT_TIMER1; } (6)从中断中返回,恢复现场,跳转到被中断的主程序继续执行,等待下一次中断的到来。
*******MEMORY CONTROLLER*******
本实验介绍如何使用SDRAM,这需要设置13个寄存器。呵呵,别担心,这些寄存器很多是类似的,并且由于我们只使用了BANK6,大部分的寄存器我们不必理会:
1.BWSCON:对应BANK0-BANK7,每BANK使用4位。这4位分别表示:
a.STx:启动/禁止SDRAM的数据掩码引脚,对于SDRAM,此位为0;对于SRAM,此位为1。
b.WSx:是否使用存储器的WAIT信号,通常设为0
c.DWx:使用两位来设置存储器的位宽:00-8位,01-16位,10-32位,11-保留。
d.比较特殊的是BANK0对应的4位,它们由硬件跳线决定,只读。
对于本开发板,使用两片容量为32Mbyte、位宽为16的SDRAM组成容量为64Mbyte、位宽为32的存储器,所以其BWSCON相应位 为:0010。对于本开发板,BWSCON可设为0x22111110:其实我们只需要将BANK6对应的4位设为0010即可,其它的是什么值没什么影 响,这个值是参考手册上给出的。
2.BANKCON0-BANKCON5:我们没用到,使用默认值0x00000700即可
3.BANKCON6-BANKCON7:设为0x00018005
在8个BANK中,只有BANK6和BANK7可以使用SRAM或SDRAM,所以BANKCON6-7与BANKCON0-5有点不同:
a.MT([16:15]):用于设置本BANK外接的是SRAM还是SDRAM:SRAM-0b00,SDRAM-0b11
b.当MT=0b11时,还需要设置两个参数:
Trcd([3:2]):RAS to CAS delay,设为推荐值0b01
SCAN([1:0]):SDRAM的列地址位数,对于本开发板使用的SDRAM HY57V561620CT-H,列地址位数为9,所以SCAN=0b01。如果使用其他型号的SDRAM,您需要查看它的数据手册来决定SCAN的取值:00-8位,01-9位,10-10位
4.REFRESH(SDRAM refresh control register):设为0x008e0000+ R_CNT
其中R_CNT用于控制SDRAM的刷新周期,占用REFRESH寄存器的[10:0]位,它的取值可如下计算(SDRAM时钟频率就是HCLK):
R_CNT = 2^11 + 1 – SDRAM时钟频率(MHz) * SDRAM刷新周期(uS)
在未使用PLL时,SDRAM时钟频率等于晶振频率12MHz;SDRAM的刷新周期在SDRAM的数据手册上有标明,在本开发板使用的SDRAM HY57V561620CT-H的数据手册上,可看见这么一行“8192 refresh cycles / 64ms”:所以,刷新周期=64ms/8192 = 7.8125 uS。
对于本实验,R_CNT = 2^11 + 1 – 12 * 7.8125 = 1955,
REFRESH=0x008e0000 + 1955 = 0x008e07a3
5.BANKSIZE:0x000000b2
位[7]=1:Enable burst operation
位[5]=1:SDRAM power down mode enable
位[4]=1:SCLK is active only during the access (recommended)
位[2:1]=010:BANK6、BANK7对应的地址空间与BANK0-5不同。BANK0-5的地址空间都是固定的128M,地址范围是 (x*128M)到(x+1)*128M-1,x表示0到5。但是BANK7的起始地址是可变的,您可以从S3C2410数据手册第5章“Table 5-1. Bank 6/7 Addresses”中了解到BANK6、7的地址范围与地址空间的关系。本开发板仅使用BANK6的64M空间,我们可以令位 [2:1]=010(128M/128M)或001(64M/64M):这没关系,多出来的空间程序会检测出来,不会发生使用不存在的内存的情况——后面 介绍到的bootloader和linux内核都会作内存检测。
位[6]、位[3]没有使用
6.MRSRB6、MRSRB7:0x00000030
能让我们修改的只有位[6:4](CL),SDRAM HY57V561620CT-H不支持CL=1的情况,所以位[6:4]取值为010(CL=2)或011(CL=3)。
只要我们设置好了上述13个寄存器,往后SDRAM的使用就很简单了。本实验先使用汇编语言设置好SDRAM,然后把程序本身从Steppingstone(还记得吗?本节开始的时候提到过,复位之后NAND Flash开头的4k代码会被自动地复制到这里)复制到SDRAM处,然后跳到SDRAM中执行。
本实验源代码在SDRAM目录中, head.s开头的代码如下:
1 bl disable_watch_dog
2 bl memsetup
3 bl copy_steppingstone_to_sdram
4 ldr pc, =set_sp @跳到SDRAM中继续执行
5 set_sp:
6 ldr sp, =0x34000000 @设置堆栈
7 bl main @跳转到C程序main函数
8 halt_loop:
9 b halt_loop
为了让程序结构简单一点,我都使用函数调用的方式。第一条指令是禁止WATCH DOG,往WTCON寄存器(地址0x53000000)写入0即可禁止WATCH DOG。第二条指令设置本节开头所描述的13个寄存器,以便使用SDRAM。往下程序做的事情就是:将Steppingstone中的代码复制到SDRAM中(起始地址为 0x30000000),然后向pc寄存器直接赋值跳到SDRAM中执行下一条指令“ldr sp, =0x34000000”。
********NAND FLASH CONTROLLER***********
当OM1、OM0都是低电平(请看数据手册198页)——即开发板插上BOOT SEL跳线时,S3C2410从NAND Flash启动:NAND Flash的开始4k代码会被自动地复制到内部SRAM中。我们需要使用这4k代码来把更多的代码从NAND Flash中读到SDRAM中去。NAND Flash的操作通过NFCONF、NFCMD、NFADDR、NFDATA、NFSTAT和NFECC六个寄存器来完成。在开始下面内容前,请打开S3C2410数据手册和NAND Flash K9F1208U0M的数据手册。
在S3C2410数据手册218页,我们可以看到读写NAND Flash的操作次序:
1. Set NAND flash configuration by NFCONF register.
2. Write NAND flash command onto NFCMD register.
3. Write NAND flash address onto NFADDR register.
4. Read/Write data while checking NAND flash status by NFSTAT register. R/nB signal should be checked before read operation or after program operation.
下面依次介绍:
1、NFCONF:设为0xf830——使能NAND Flash控制器、初始化ECC、NAND Flash片选信号nFCE=1(inactive,真正使用时再让它等于0)、设置TACLS、TWRPH0、TWRPH1。需要指出的是TACLS、 TWRPH0和TWRPH1,请打开S3C2410数据手册218页,可以看到这三个参数控制的是NAND Flash信号线CLE/ALE与写控制信号nWE的时序关系。我们设的值为TACLS=0,TWRPH0=3,TWRPH1=0,其含义 为:TACLS=1个HCLK时钟,TWRPH0=4个HCLK时钟,TWRPH1=1个HCLK时钟。请打开K9F1208U0M数据手册第13页,在 表“AC Timing Characteristics for Command / Address / Data Input”中可以看到:
CLE setup Time = 0 ns,CLE Hold Time = 10 ns,
ALE setup Time = 0 ns,ALE Hold Time = 10 ns,
WE Pulse Width = 25 ns
可以计算,即使在HCLK=100MHz的情况下,TACLS+TWRPH0+TWRPH1=6/100 uS=60 ns,也是可以满足NAND Flash K9F1208U0M的时序要求的。
2、NFCMD:
对于不同型号的Flash,操作命令一般不一样。对于本板使用的K9F1208U0M,请打开其数据手册第8页“Table 1. Command Sets”,上面列得一清二楚。
3、NFADDR:无话可说
4、NFDATA:只用到低8位
5、NFSTAT:只用到位0,0-busy,1-ready
6、NFECC:待补
现在来看一下如何从NAND Flash中读出数据,请打开K9F1208U0M数据手册第29页“PAGE READ”,跟本节的第2段是遥相呼应啊,提炼出来罗列如下(设读地址为addr):
1、NFCONF = 0xf830
2、在第一次操作NAND Flash前,通常复位一下:
NFCONF &= ~0x800 (使能NAND Flash)
NFCMD = 0xff (reset命令)
循环查询NFSTAT位0,直到它等于1
3、NFCMD = 0 (读命令)
4、这步得稍微注意一下,请打开K9F1208U0M数据手册第7页,那个表格列出了在地址操作的4个步骤对应的地址线,A8没用到:
NFADDR = addr & 0xff
NFADDR = (addr<<9) & 0xff (注意了,左移9位,不是8位)
NFADDR = (addr<<17) & 0xff (左移17位,不是16位)
NFADDR = (addr<<25) & 0xff (左移25位,不是24位)
5、循环查询NFSTAT位0,直到它等于1
6、连续读NFDATA寄存器512次,得到一页数据(512字节)
7、NFCONF |= 0x800 (禁止NAND Flash)
热门阅读
-
office 2019专业增强版最新2021版激活秘钥/序列号/激活码推荐 附激活工具
阅读:74
-
如何安装mysql8.0
阅读:31
-
Word快速设置标题样式步骤详解
阅读:28
-
20+道必知必会的Vue面试题(附答案解析)
阅读:37
-
HTML如何制作表单
阅读:22
-
百词斩可以改天数吗?当然可以,4个步骤轻松修改天数!
阅读:31
-
ET文件格式和XLS格式文件之间如何转化?
阅读:24
-
react和vue的区别及优缺点是什么
阅读:121
-
支付宝人脸识别如何关闭?
阅读:21
-
腾讯微云怎么修改照片或视频备份路径?
阅读:28
Copyright 2006-2020 php爱好者(phpfans.net) All Rights Reserved.备案号:湘ICP备2023016114号-2
本站为非盈利性网站,不接受任何广告。本站所有资源均由网友上传,如有侵权,请发邮件至 [email protected] phpfans.net