菜鸟学uC/OS_II(10)<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
By <?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />Norman
2008-7-22
LPC2131系统控制模块
1、晶体振荡器和锁相环PLL
两种工作模式:从属模式和振荡模式。
l PLL控制寄存器:PLLCON
l PLL配置寄存器:PLLCFG
l PLL状态寄存器:PLLSTAT
l PLL馈送寄存器:PLLFEED
PLL频率计算:
PLL输出频率:<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />
如何确定PLL
(1)选择处理器的操作频率(Fcclk)。这可以根据处理器的整体要求和UART波特率的支持因素来决定。(外围器件的时钟频率可以低于处理器频率)。
(2)选择振荡器频率(FOSC)。Fcclk一定是FOSC的整数倍。
(3)计算M值以配置MSEL位。M=Fcclk/FOSC,M的取值范围为1~32。写入MSEL位的值为M-1。
(4)选择P值以配置PSEL位,使FCCO在定义的频率限制范围内,FCCO可通过前面计算。P必须是1、2、4、8中的一个。写入PSEL位的值:00:P=1;01:P=2;10:P=4;11:P=8。
PLL操作方法:
1)查询方式
l PLLCON=1——设定PLL之前,必须使能PLL,但不能连接PLL;
l 设定P和M的值(PLLCFG);
l 发送PLL馈送序列
l 等待PLL锁定——PLLSTAT.10=1;
l PLLCON=3——设定P和M之后,链接PLL;
l 发送PLL馈送序列,将P和M的值写入硬件;
2)中断方式
主程序:
l PLLCON=1——使能但不链接PLL;
l 设定P和M的值;
l 发送PLL馈送序列;
PLL中断服务程序:
l PLLCON=3——链接PLL;
l 发送PLL馈送序列,将P和M的值写入硬件;
l 禁止PLL中断,返回。
举例:
1)M和P的确定
设FOSC=10MHz,Fcclk=60MHz
M=Fcclk/FOSC=60/10=6,则M-1=5,因此,PLLCFG[4:0]=5。
P=Fcco/(Fcclk×2),Fcco在156~320MHz之间,设最低频率为156MHz,最高频为320MHz,那么,在1.3~2.67之间,P只能够取2;因此PLLCFG[6:5]=01;最终,PLLCFG=0x25。
2)设定PLL序列
PLLCON = 1;
PLLCFG = 0x25;
PLLFEED = 0xAA;
PLLFEED = 0x 55; /*这个好像DSP中有一个写入读出序列的作用相似*/
While((PLLSTAT & (1 << 10)) == 0);
PLLCON = 3;
PLLFEED = 0xAA;
PLLFEED = 0x55;
2、外部中断输入
中断相关的寄存器有4个:
EXTINT:外部中断标志寄存器。包含EINT0、EINT1、EINT2的中断标志
EXTWAKE:外部中断唤醒寄存器。指示哪些中断可以唤醒掉电的CPU,以及控制是否使能唤醒
EXTMODE:外部中断方式寄存器。控制每个引脚的边沿或电平激活
EXTPOLAR:外部中断极性寄存器。控制由每个引脚的哪种电平或边沿来产生中断
外部中断应用示例:
1)设置EINT0为电平中断
PINSEL1 = 0x00000001;
EXTMODE = 0x00;
EXTPOLAR = 0x00;
或
EXTPOLA = 0x01;
2)设置EINT0为上升/下降沿中断
PINSEL1 = 0x01;
EXTMODE = 0x01;
EXTPOLAR = 0x00;
或
EXTPOLAR = 0x01;
3)清除所有中断标志
EXTINT = 0x0F; /*写1清零*/
3、存储器映射控制REMAP
该寄存器的作用是做存储器重新映射的控制。选择从Flash Boot Block、用户Flash或RAM中读取ARM中断向量。其中MAP1:0对应值:
l 00:Boot装载程序模式。中断向量从Boot Block重新映射
l 01:用户Flash模式。中断向量不重新映射,位于Flash中
l 10:用户RAM模式。中断向量从静态RAM重新映射
l 00:保留
4、功率控制
LPC2131支持两种节电模式:空闲模式和掉电模式。
PCON:功率控制寄存器。该寄存器包含LPC2131的两种节电模式的控制位
PCONP:外设功率控制寄存器。该寄存器包含使能和禁止单个外设功能的控制位
示例:
1)使CPU进入空闲模式
PCON = 0x01;
2)使CPU进入掉电模式
PCON = 0x02;
或
PCON = 0x03; /*IDL和PD均为1*/
3)关闭PWM实现节电
PCONP = PCONP & (~(1 << 5));
5、复位
LPC2131有两个复位源:/RESET引脚复位和看门狗复位。
复位流程:
6、VPB分频器
寄存器:VPBDIV
作用:决定处理器时钟cclk与外设器件所使用的时钟pclk之间的关系。
l 通过VPB总线为外设提供所需的pclk时钟,以便外设在为满足ARM处理器而调整的速度下工作
l 应用在不需要任何外设全速运行时使功耗降低
VPBDIV[1:0]:
l 00:VPB总线时钟为处理器时钟的1/4
l 01:相同
l 10:1/2
l 11:保留
7、唤醒定时器
确保振荡器和芯片所需要的其他模拟功能在处理器开始执行指令之前能够正确工作。
8、掉电检测BOD(Brown-Out Detection)
含有中断
9、启动代码相关
在LPC2131的启动代码中,target.c文件包含目标板特殊的代码,包括一场处理程序和目标板初始化程序,此文件必须根据程序的需要修改。
为了让系统能够正常工作,必须在 进入main()函数之前对系统进行一些基本的初始化工作,由函数TargetResetInit()完成。
void TargetResetInit(void)
{
#ifdef __DEBUG_RAM
MEMMAP = 0x2; //如果在片内RAM中调试,映射到片内RAM
#endif
#ifdef __DEBUG_FLASH
MEMMAP = 0x1; //如果在片内FLASH中调试,映射到片内FLASH
#endif
#ifdef __IN_CHIP
MEMMAP = 0x1; //如果在片内FLASH中发布(加密),映射到片内FLASH
#endif
/* 设置系统各部分时钟 */
/*设置外设时钟与系统时钟的分频比*/
/*pclk与cclk具体值在config.h中定义*/
/* Set system timers for each component */
PLLCON = 1; //设置激活但未链接PLL
#if (Fpclk / (Fcclk / 4)) == 1
VPBDIV = 0;
#endif
#if (Fpclk / (Fcclk / 4)) == 2
VPBDIV = 2;
#endif
#if (Fpclk / (Fcclk / 4)) == 4
VPBDIV = 1;
#endif
/*设定PLL的乘积因子M和除因子P的值*/
#if (Fcco / Fcclk) == 2
PLLCFG = ((Fcclk / Fosc) - 1) | (0 << 5);
#endif
#if (Fcco / Fcclk) == 4
PLLCFG = ((Fcclk / Fosc) - 1) | (1 << 5);
#endif
#if (Fcco / Fcclk) == 8
PLLCFG = ((Fcclk / Fosc) - 1) | (2 << 5);
#endif
#if (Fcco / Fcclk) == 16
PLLCFG = ((Fcclk / Fosc) - 1) | (3 << 5);
#endif
PLLFEED = 0xaa; //馈送序列,执行设定的PLL的动作
PLLFEED = 0x55;
while((PLLSTAT & (1 << 10)) == 0); //等待锁定
PLLCON = 3; //设置激活并连接PLL
PLLFEED = 0xaa; //发送PLL馈送序列,执行激活和链接动作
PLLFEED = 0x55;
/* 设置存储器加速模块 */
/* Set memory accelerater module*/
MAMCR = 0;
#if Fcclk < 20000000
MAMTIM = 1;
#else
#if Fcclk < 40000000
MAMTIM = 2;
#else
MAMTIM = 3;
#endif
#endif
MAMCR = 2;
/* 初始化VIC */
/* initialize VIC*/
VICIntEnClr = 0xffffffff;
VICVectAddr = 0;
VICIntSelect = 0;
/* 添加自己的代码 */
/* Add your codes here */
}
设置系统时钟:(config.h)
/* 系统设置, Fosc、Fcclk、Fcco、Fpclk必须定义*/
#define Fosc 11059200
//应当与实际一至晶振频率,10MHz~25MHz,应当与实际一至
#define Fcclk (Fosc * 4)
//系统频率,必须为Fosc的整数倍(1~32),且<=60MHZ
#define Fcco (Fcclk * 4)
//CCO频率,必须为Fcclk的2、4、8、16倍,范围为156MHz~320MHz
#define Fpclk (Fcclk / 4) * 1
//VPB时钟频率,只能为(Fcclk / 4)的1、2、4倍
#include "target.h" //这一句不能删除
#endif
10、存储器加速模块
见前节程序清单——
11、向量中断控制器VIC
这是非常重要的一节——
VIC具有32个中断请求输入:FIQ、向量IRQ和非向量IRQ
首先看看三种中断的特点:
FIQ:具有最高的优先级,一般(最好)分配一个中断为FIQ,多个FIQ可能产生中断延迟。如果分配给FIQ的中断多于一个,那么,FIQ服务程序要读取FIQ状态寄存器来识别产生中断请求的FIQ中断源。
向量IRQ(Vectored IRQ):中等优先级。可分配32个请求中的16个。Slot0为最高优先级,而Slot15为最低优先级。
非向量IRO(NON-Vectored IRQ):优先级最低,服务程序放在VICDefVectAddr中。由于多个中断共用一个服务程序地址,可在ISR中读取IRQ状态寄存器来判定那个IRQ被激活。
中断寄存器:
<略>
VIC使用举例:
1)将外部中断0设置为非向量中断
VICDefVectAddr = (int)IRQ_Eint0; //设置中断服务程序地址
EXTINT = 0x01; //清除EINT0中断标志
VICIntEnable = 1 << 0x0e; //使能EINT0中断
2)设置外部中断0为向量中断
VICIntSelect = 0x00000000; //设置所有中断分配为IRQ中断
VICVectCntl0 = 0x20 | 0x0e; //分配外部中断0到向量中断0
VICVectAddr0 = (uint32)IRQ_Eint0; //设置中断服务程序地址
EXTINT = 0x01; //清除EINT0中断标志
VICIntEnable = 1 << 0x0e; //使能EINT0中断
*注意:VICVectCntlx必须和VICVectAddrx对应
3)将外部中断0分配为快速中断
VICIntSelect = 1 << EINT0; //设置EINT0为FIQ中断
EXTINT = 0x01; //清楚EINT0中断标志
VICIntEnable = 1 << EINT0; //使能EINT0中断
4)多个中断设置
假设UART0和SPI0产生中断请求,他们被分配为向量IRQ(UART0的优先级高于SPI0),而UART1和I2C产生非向量IRQ。
VICIntSelect = 0x00000000; //SPI0、I2C、UART1和UART0为IRQ
VICIntEnable = 0x000006C0; //
VICDefVectAddr = 0x…. //保存非向量IRQ的程序地址
VICVectAddr0 = 0x…. //保存UART0 IRQ的ISR地址
VICVectAddr1 = 0x…. //保存SPI0 IRQ 的ISR地址
VICVectCntl0 = 0x00000026 //VIC通道号为6的中断源UART0使能为优先级0
VICVectCntl0 = 0x0000002A //VIC通道号为10的中断源SPI0使能为优先级1
5)IRQ中断服务程序的编写
Void __irq EINT1_IRQ(void)
{
…. //中断处理
EXTINT = 0x02; //清除外部中断2标志位
VICVectAddr = 0x00; //对VICVectAddr执行写操作,通知VIC中断处理结束
}
*注意:__irq 是ADS1.2编译器的关键字,产生相应的中断进入推出机器码
VIC使用注意事项:
l 如果在片内RAM中运行代码且应用程序需要使用中断,那么必须将中断向量重新映射到片内地址0x00000000。这样做是因为所有的异常向量都位于地址0x00000000及以上。
l 虽然可以选择多个中断源来产生FIQ请求,但是只有一个专门的中断服务程序来服务响应所有可用出现的FIQ请求。因此,如果分配为FIQ的中断对于一个FIQ中断服务程序就必须读取VICFIQStatus的内容来决定如何处理中断请求。因此,一般建议分配一个中断为FIQ。(有个疑问:FIQ中断服务程序在哪里写的,如何编写?——这些都可以在Target.c文件中编写,快速中断的处理程序也是放在这里的,默认为slot0?)
l 在中断服务程序执行完毕后,对外设中断标志的清零将会对VIC寄存器(VICRawlntr、VICFIQStatus和VICIRQStatus)当中的对应位产生影响。另外,为了能够服务下次中断,必须在中断返回前对VICVectAddr寄存器执行写操作清零内部中断优先级硬件中断中断标志。
l 通常要禁止VIC中断,必须清零VICIntEnClr寄存器中对应位,该操作使得VICIntEnable寄存器的对应位清零。当然这同样适用于VICSoftInt和VICSoftIntClear。
l 如果看门狗在溢出或者无效喂狗时产生中断,那么无法清除中断。唯一的方法是通过VICIntEnClr禁止VIC中断来实现中断返回。
12、引脚链接模块
切换功能选择——PINSEL0、PINSEL1、PINSEL2
看来这节,才知道这款芯片的引脚复用真是太厉害了。
注意,在设置的时候,最好选用读-修改-写的方法,这样才能够避免改变其他引脚的功能,尤其是对于PINSEL2——具有调试、跟踪功能
如:将P0.8、P0.9设置为TxD1、RxD1功能
PINSEL0 = (PINNSEL0 & 0xFFF0FFFF) | (0x05 << 16);
至于控制寄存器,则要对应功能来选择使用——
13、启动代码分析
以ADS模板为例——
启动文件组成
<由于内容太多,不一一记录详述,详见《深入浅出ARM7——LPC2131》一书>
启动流程——
ARM芯片复位后,系统进入管理模式,ARM状态,PC(R15)寄存器值为0x00000000,系统从0x00000000处开始执行程序,而0x00000000处放着异常向量表,程序将根据异常向量表进行跳转。
l 芯片复位后,PC=0x00000000,在异常向量表0x00000000处
l 芯片根据异常处理程序地址表,得到复位程序的地址
l 跳转到复位处理程序处
l 调用InitStack()函数,初始化各模式的堆栈
l 调用Target.c中断TargetResetInit()函数初始化目标板:配置Remap、个部分时钟、存储器加速模块和VIC等
l 跳转到用户C程序入口main()处
总结:该部分介绍了LPC2131的一些内部结构和相关原理,走了个大概,对一些特殊结构操作有了一定的了解,并对整个ADS模板代码结构初步分析。下一步就是通过具体的实验来进一步了解其功能和结构。
(待续)
文章评论(0条评论)
登录后参与讨论