学习ARM有一段时间了,现在做一个记录裸机程序,再网上看到了赵老师讲2440裸机程序的博客,写的很好,建议和我一样的初学者能好好的学习一下赵老师的博客,网址:http://blog.csdn.net/zhaocj/article/details/6118860,真心不错!给赵老师做一下广告,哈哈 ^_^
1 2440启动文件分析
由于启动文件无法仿真,可以再要判断的语句的地方加上一段点亮led小灯程序
ResetHandler ;系统上电或复位后,由0x0处的跳转指令,跳转到该处开始真正执行系统的初始化工作
2 2440外部中断
2440的外部中断引脚EINT与通用IO引脚F和G复用,要想使用中断功能,就要把相应的引脚配置成中断模式,如我们想把端口F0设置成外部中断,而其他引脚功能不变,则GPFCON=(GPFCON & ~0x3) | 0x2。配置完引脚后,还需要配置具体的中断功能。我们要打开某一中断的屏蔽,这样才能响应该中断,相对应的寄存器为INTMSK;还要设置外部中断的触发方式,如低电平、高电平、上升沿、下降沿等,相对应的寄存器为EXTINTn。另外由于EINT4到EINT7共用一个中断向量,EINT8到EINT23也共用一个中断向量,而INTMSK只负责总的中断向量的屏蔽,要具体打开某一具体的中断屏蔽,还需要设置EINTMASK。
SRCPND和INTPND
S3C2440A有两个中断挂起寄存器:源挂起寄存器(SRCPND)和中断挂起寄存器(INTPND)。这些挂起寄存器表明一个中断请求是否为挂起。当中断源请求中断服务,SRCPND寄存器的相应位被置位为1,并且同时在仲裁步骤后INTPND 寄存器仅有1位自动置位为1。如果屏蔽了中断,则SRCPND寄存器的相应位被置位为1。这并不会引起INTPND 寄存器的位的改变。当INTPND 寄存器的挂起位为置位,每当I 标志或F标志被清除为0中断服务程序将开始。SRCPND和INTPND寄存器可以被读取和写入,因此服务程序必须首先通过写1到SRCPND寄存器的相应位来清除挂起状态并且通过相同方法来清除INTPND寄存器中挂起状态
3 2440的PWM应用
s3c2440芯片中一共有5个16位的定时器,其中有4个定时器(定时器0~定时器3)具有脉宽调制功能,因此用s3c2440可以很容易地实现PWM功能。下面就具体介绍如何实现PWM功能。
1、PWM是通过引脚TOUT0~TOUT3输出的,而这4个引脚是与GPB0~GPB3复用的,因此要实现PWM功能首先要把相应的引脚配置成TOUT输出。
2、再设置定时器的输出时钟频率,它是以PCLK为基准,再除以用寄存器TCFG0配置的prescaler参数,和用寄存器TCFG1配置的divider参数。
3、然后设置脉冲的具体宽度,它的基本原理是通过寄存器TCNTBn来对寄存器TCNTn(内部寄存器)进行配置计数,TCNTn是递减的,如果减到零,则它又会重新装载TCNTBn里的数,重新开始计数,而寄存器TCMPBn作为比较寄存器与计数值进行比较,当TCNTn等于TCMPBn时,TOUTn输出的电平会翻转,而当TCNTn减为零时,电平会又翻转过来,就这样周而复始。因此这一步的关键是设置寄存器TCNTBn和TCMPBn,前者可以确定一个计数周期的时间长度,而后者可以确定方波的占空比。由于s3c2440的定时器具有双缓存,因此可以在定时器运行的状态下,改变这两个寄存器的值,它会在下个周期开始有效。
4、最后就是对PWM的控制,它是通过寄存器TCON来实现的,一般来说每个定时器主要有4个位要配置(定时器0多一个死区位):启动/终止位,用于启动和终止定时器;手动更新位,用于手动更新TCNTBn和TCMPBn,这里要注意的是在开始定时时,一定要把这位清零,否则是不能开启定时器的;输出反转位,用于改变输出的电平方向,使原先是高电平输出的变为低电平,而低电平的变为高电平;自动重载位,用于TCNTn减为零后重载TCNTBn里的值,当不想计数了,可以使自动重载无效,这样在TCNTn减为零后,不会有新的数加载给它,那么TOUTn输出会始终保持一个电平(输出反转位为0时,是高电平输出;输出反转位为1时,是低电平输出),这样就没有PWM功能了,因此这一位可以用于停止PWM。
TCFG0 = 0xFFFF00;
TCFG0 |= 0x31; //低8为时钟的分频数
TCFG1 &= ~0xF; //1/2,PCLK=50MHz,所有50MHz/25/2=500KHz
TCNTB0 = 5000;
TCMPB0 = freq;
TCON &= ~0x1F;
TCON |= 0xF; //死区无效,自动装载,电平反转,手动更新,定时器开启
TCON &= ~0x2; //手动更新位清零,PWM开始工作
4 2440的PWM应用
在s3c2440中,有2个不同的PLL,一个是MPLL,另一个是UPLL。UPLL是给USB提供48MHz。在这里,我们主要介绍MPLL。外部时钟源经过MPLL处理后能够得到三个不同的系统时钟:FCLK、HCLK和PCLK。FCLK是主频时钟,用于ARM920T内核;HCLK用于AHB总线设备,如ARM920T,内存控制,中断控制,LCD控制,DMA以及USB主模块;PCLK用于APB总线设备,如外围设备的看门狗,IIS,I2C,PWM,MMC接口,ADC,UART,GPIO,RTC以及SPI。这三个系统时钟(FCLK、HCLK和PCLK)是有一定的比例关系,这种关系是通过寄存器CLKDIVN中的HDIVN位和PDIVN位来控制的,因此我们只要知道了FCLK,再通过这两位的控制,就能确定HCLK和PCLK。而FCLK是如何得到的呢?它是通过输入时钟(即外部时钟源)的频率,经过一个计算公式(具体公式请查阅数据手册)得到的,这个计算公式还需要三个参数(MDIV、PDIV、SDIV),而这三个参数是经过寄存器MPLLCON配置得到的。最后,我们用最清晰的线路来绘制一下时钟的产生过程:外部时钟源→通过寄存器MPLLCON得到FCLK→再通过寄存器CLKDIVN得到HCLK和PCLK。这个配置过程在启动文件中就已完成。
TCFG0 :定时器配置寄存器0,配置2个8位预分频器
[23:16] :死区长度
[16:8] :precsaler1,决定定时器2,3,4预分频值
[7:0] :prescaler0,决定定时器0,1的预分频值
5 2440的UART应用
s3c2440提供了三个UART端口,它们都可以通过查询、中断和DMA方式传输数据,而且每个UART都分别有一个64个字节的接收FIFO和一个64个字节的发送FIFO。
要实现某种通信,就必须遵循该通信协议。UART的协议包括传输数据的位数,停止位的位数,以及是否进行奇偶校验,这些设置是利用ULCONn寄存器完成的。另一个很重要的地方就是设置波特率。s3c2440波特率的时钟源有三个:PCLK、FCLK/n和UEXTCLK。时钟源的选择是由UCONn的第10位和第11位来完成的。波特率的具体计算公式为:
时钟源频率÷(波特率×16)-1
RS-232C标准采用的是负逻辑方式,逻辑1对用-15到-5V,逻辑0对应5到15V
S3C2440A 的 UART(通用异步串行接口)单元提供了三个独立的异步串行 I/O 端口,每个
都可以在中断和 DMA 两种模式下进行,他们支持的最高波特率是 115.2Kbps。每个 UART 通道包含 2 个 64 字节 FIFO 分别提供个接收和发送。
GPH7 [15:14] 00 = 输入 01 = 输出 10 = RXD[2] 11 = nCTS1
GPH6 [13:12] 00 = 输入 01 = 输出 10 = TXD[2] 11 = nRTS1
GPH5 [11:10] 00 = 输入 01 = 输出 10 = RXD[1] 11 = 保留
GPH4 [9:8] 00 = 输入 01 = 输出 10 = TXD[1] 11 = 保留
GPH3 [7:6] 00 = 输入 01 = 输出 10 = RXD[0] 11 = 保留
GPH2 [5:4] 00 = 输入 01 = 输出 10 = TXD[0] 11 = 保留
6 2440的NAND Flash应用
NAND Flash引导启动模式中必须选择GPG[15:13]为输入。
当复位时,NAND Flash控制器将通过引脚状态(NCON(先进闪存), GPG13(页大小),GPG14(地址周期),GPG15(总线宽度)—请参考引脚配置)来获取连接的NAND Flash的信息,在发生掉电或系统复位后,NAND Flash控制器自动加载4K字节的BootLoader代码。在加载完BootLoader代码后,Steppingstone中的BootLoader代码已经执行了
D[7:0] : 数据/命令/地址/的输入/输出口(与数据总线共享)
CLE : 命令锁存使能 (输出)
ALE : 地址锁存使能(输出)
nFCE : NAND Flash 片选使能(输出)
nFRE : NAND Flash 读使能 (输出)
nFWE : NAND Flash 写使能 (输出)
R/nB : NAND Flash 准备好/繁忙(输入)
//-------------- s3c2440的头文件 ----------------------------
/***********************************************************************/
/* This file is part of the uVision/ARM development tools */
/* Copyright KEIL - An ARM Company 2002-2007 */
/***********************************************************************/
/* */
/* S3C2440.H: Header file for Samsung S3C2440 */
/* */
/***********************************************************************/
#ifndef __S3C2440_H
#define __S3C2440_H
// Memory Controllers
#define BWSCON (*(volatile unsigned long *) 0x48000000)
#define BANKCON0 (*(volatile unsigned long *) 0x48000004)
#define BANKCON1 (*(volatile unsigned long *) 0x48000008)
#define BANKCON2 (*(volatile unsigned long *) 0x4800000C)
#define BANKCON3 (*(volatile unsigned long *) 0x48000010)
#define BANKCON4 (*(volatile unsigned long *) 0x48000014)
#define BANKCON5 (*(volatile unsigned long *) 0x48000018)
#define BANKCON6 (*(volatile unsigned long *) 0x4800001C)
#define BANKCON7 (*(volatile unsigned long *) 0x48000020)
#define REFRESH (*(volatile unsigned long *) 0x48000024)
#define BANKSIZE (*(volatile unsigned long *) 0x48000028)
#define MRSRB6 (*(volatile unsigned long *) 0x4800002C)
#define MRSRB7 (*(volatile unsigned long *) 0x48000030)
// USB Host Controller
#define HcRevision (*(volatile unsigned long *) 0x49000000)
#define HcControl (*(volatile unsigned long *) 0x49000004)
#define HcCommonStatus (*(volatile unsigned long *) 0x49000008)
#define HcInterruptStatus (*(volatile unsigned long *) 0x4900000C)
#define HcInterruptEnable (*(volatile unsigned long *) 0x49000010)
#define HcInterruptDisable (*(volatile unsigned long *) 0x49000014)
#define HcHCCA (*(volatile unsigned long *) 0x49000018)
#define HcPeriodCuttentED (*(volatile unsigned long *) 0x4900001C)
#define HcControlHeadED (*(volatile unsigned long *) 0x49000020)
#define HcControlCurrentED (*(volatile unsigned long *) 0x49000024)
#define HcBulkHeadED (*(volatile unsigned long *) 0x49000028)
#define HcBulkCurrentED (*(volatile unsigned long *) 0x4900002C)
#define HcDoneHead (*(volatile unsigned long *) 0x49000030)
#define HcRmInterval (*(volatile unsigned long *) 0x49000034)
#define HcFmRemaining (*(volatile unsigned long *) 0x49000038)
#define HcFmNumber (*(volatile unsigned long *) 0x4900003C)
#define HcPeriodicStart (*(volatile unsigned long *) 0x49000040)
#define HcLSTreshold (*(volatile unsigned long *) 0x49000044)
#define HcRhDescriptorA (*(volatile unsigned long *) 0x49000048)
#define HcRhDescriptorB (*(volatile unsigned long *) 0x4900004C)
#define HcRhStatus (*(volatile unsigned long *) 0x49000050)
#define HcRhPortStatus1 (*(volatile unsigned long *) 0x49000054)
#define HcRhPortStatus2 (*(volatile unsigned long *) 0x49000058)
// Interrupt Controller
#define SRCPND (*(volatile unsigned long *) 0x4A000000)
#define INTMOD (*(volatile unsigned long *) 0x4A000004)
#define INTMSK (*(volatile unsigned long *) 0x4A000008)
#define PRIORITY (*(volatile unsigned long *) 0x4A00000C)
#define INTPND (*(volatile unsigned long *) 0x4A000010)
#define INTOFFSET (*(volatile unsigned long *) 0x4A000014)
#define SUBSRCPND (*(volatile unsigned long *) 0x4A000018)
#define INTSUBMSK (*(volatile unsigned long *) 0x4A00001C)
// DMA
#define DISRC0 (*(volatile unsigned long *) 0x4B000000)
#define DISRCC0 (*(volatile unsigned long *) 0x4B000004)
#define DIDST0 (*(volatile unsigned long *) 0x4B000008)
#define DIDSTC0 (*(volatile unsigned long *) 0x4B00000C)
#define DCON0 (*(volatile unsigned long *) 0x4B000010)
#define DSTAT0 (*(volatile unsigned long *) 0x4B000014)
#define DCSRC0 (*(volatile unsigned long *) 0x4B000018)
#define DCDST0 (*(volatile unsigned long *) 0x4B00001C)
#define DMASKTRIG0 (*(volatile unsigned long *) 0x4B000020)
#define DISRC1 (*(volatile unsigned long *) 0x4B000040)
#define DISRCC1 (*(volatile unsigned long *) 0x4B000044)
#define DIDST1 (*(volatile unsigned long *) 0x4B000048)
#define DIDSTC1 (*(volatile unsigned long *) 0x4B00004C)
#define DCON1 (*(volatile unsigned long *) 0x4B000050)
#define DSTAT1 (*(volatile unsigned long *) 0x4B000054)
#define DCSRC1 (*(volatile unsigned long *) 0x4B000058)
#define DCDST1 (*(volatile unsigned long *) 0x4B00005C)
#define DMASKTRIG1 (*(volatile unsigned long *) 0x4B000060)
#define DISRC2 (*(volatile unsigned long *) 0x4B000080)
#define DISRCC2 (*(volatile unsigned long *) 0x4B000084)
#define DIDST2 (*(volatile unsigned long *) 0x4B000088)
#define DIDSTC2 (*(volatile unsigned long *) 0x4B00008C)
#define DCON2 (*(volatile unsigned long *) 0x4B000090)
#define DSTAT2 (*(volatile unsigned long *) 0x4B000094)
#define DCSRC2 (*(volatile unsigned long *) 0x4B000098)
#define DCDST2 (*(volatile unsigned long *) 0x4B00009C)
#define DMASKTRIG2 (*(volatile unsigned long *) 0x4B0000a0)
#define DISRC3 (*(volatile unsigned long *) 0x4B0000C0)
#define DISRCC3 (*(volatile unsigned long *) 0x4B0000C4)
#define DIDST3 (*(volatile unsigned long *) 0x4B0000C8)
#define DIDSTC3 (*(volatile unsigned long *) 0x4B0000CC)
#define DCON3 (*(volatile unsigned long *) 0x4B0000D0)
#define DSTAT3 (*(volatile unsigned long *) 0x4B0000D4)
#define DCSRC3 (*(volatile unsigned long *) 0x4B0000D8)
#define DCDST3 (*(volatile unsigned long *) 0x4B0000DC)
#define DMASKTRIG3 (*(volatile unsigned long *) 0x4B0000E0)
// Clock & Power Management
#define LOCKTIME (*(volatile unsigned long *) 0x4C000000)
#define MPLLCON (*(volatile unsigned long *) 0x4C000004)
#define UPLLCON (*(volatile unsigned long *) 0x4C000008)
#define CLKCON (*(volatile unsigned long *) 0x4C00000C)
#define CLKSLOW (*(volatile unsigned long *) 0x4C000010)
#define CLKDIVN (*(volatile unsigned long *) 0x4C000014)
#define CAMDIVN (*(volatile unsigned long *) 0x4C000018)
// LCD Controller
#define LCDCON1 (*(volatile unsigned long *) 0x4D000000)
#define LCDCON2 (*(volatile unsigned long *) 0x4D000004)
#define LCDCON3 (*(volatile unsigned long *) 0x4D000008)
#define LCDCON4 (*(volatile unsigned long *) 0x4D00000C)
#define LCDCON5 (*(volatile unsigned long *) 0x4D000010)
#define LCDSADDR1 (*(volatile unsigned long *) 0x4D000014)
#define LCDSADDR2 (*(volatile unsigned long *) 0x4D000018)
#define LCDSADDR3 (*(volatile unsigned long *) 0x4D00001C)
#define REDLUT (*(volatile unsigned long *) 0x4D000020)
#define GREENLUT (*(volatile unsigned long *) 0x4D000024)
#define BLUELUT (*(volatile unsigned long *) 0x4D000028)
#define DITHMODE (*(volatile unsigned long *) 0x4D00004C)
#define TPAL (*(volatile unsigned long *) 0x4D000050)
#define LCDINTPND (*(volatile unsigned long *) 0x4D000054)
#define LCDSRCPND (*(volatile unsigned long *) 0x4D000058)
#define LCDINTMSK (*(volatile unsigned long *) 0x4D00005C)
#define LPCSEL (*(volatile unsigned long *) 0x4D000060)
#define PALETTE 0x4D000400