看了开发板配套光盘中的非操作系统示例代码,试着进行简化,只留下最核心的启动代码,然后自己编写makefile进行编译,烧录到开发板中进行实验,总算成功了。第一个程序运行后只是简单地让4个
LED轮流开启关闭,虽然没有看懂是怎么做到控制LED的,但看懂了系统启动部分,而且把有点乱的代码整理得整齐了些;第二个程序运行后可以从串口输出文本,这对以后的进一步学习很重要,因为串口输出是很重要的调试手段(从显示屏输出文本太复杂,不是初学者可以容易搞定的)。此外,看了《基于ARM的
嵌入式系统开发与实例》,虽然第4章,第5章看得很晕,因为存储器控制器比较复杂,书中讲了好多硬件连接以及操作时序的问题,以前完全没接触过,基础不够,看不懂。但第6章和第7章讲的
中断控制器和PWM
定时器,看门狗定时器还是比较好懂的,然后结合S
3C2440A用户手册,了解了S3C2440A与书中讲的S3C44B0X的区别。把书中的例子改成可以在自己的开发板上运行的程序,烧录进去,运行得与预期效果一致。
0 说明
我用的开发板是mini2440,它采用的处理器是基于ARM920T的S3C2440A;而看的教材《基于ARM的嵌入式系统开发与实例》是以基于ARM7TDMI的S3C44B0X为例进行讲解的。
1 中断控制器
S3C2440A可以接受60个来自内部外设或者外部中断引脚的中断请求,多个中断请求经过仲裁判优后向ARM920T核心发出IRQ或者FIQ请求。S3C2440A与S3C44B0X有几处不同:
(1) 有些中断请求是带子寄存器的。这些请求先对子源中断请求寄存器(SUBSRCPND)相应位置1,再通过子中断屏蔽寄存器(INTSUBMASK),然后才能进入到源中断寄存器(SRCPND)中,最后通过中断屏蔽寄存器(INTMASK),再进行模式(INTMOD)和优先级(PRIORITY)判断。在处理通过子中断寄存器的中断时,要记得清除SUBSRCPND的相应位。
(2)从用户手册上看,S3C2440A是没有像S3C44B0X那样的中断控制寄存器的,不能选择是使用向量中断还是非向量中断。书中讲的IRQ向量模式寄存器应该是对应S3C2440A的中断优先级寄存器,S3C2440A的优先级轮转也比较好理解;至于中断请求清除寄存器,S3C2440A好像是没有对应的寄存器的。在这上面,S3C44B0X似乎复杂一些。
下面是来自S3C2440A用户手册的中断处理过程图:
2 PWM定时器
这方面S3C2440A与S3C44B0X没有太大的不同,书中讲的基本原理与定时器特性适用于S3C2440A。
3 看门狗定时器
除主时钟输入频率不同外,S3C2440A与S3C44B0X没有大的差别。
4 源代码
(1)PWM定时器处理代码
static int int_count;
static __irq void Timer0_Int(void)
{
Uart_Printf("\nTimer 0 interrupt %d times",++int_count);
rSRCPND = BIT_TIMER0;
rINTPND = BIT_TIMER0;
}
void Timer0_Start(void)
{
int i;
rTCFG0 = 0xFF;// 定时器0,1的预分频值为255
rTCFG1 = 0x2; // 定时器0的时钟分割器采用1/8分频
rTCNTB0 = 25600;
rTCON = 0x06;
for(i=0;i<1000;i++);
rTCON = 0x09;
pISR_TIMER0 = (unsigned int)Timer0_Int;
rINTMSK &= (~BIT_TIMER0);
}
(2)看门狗定时器处理代码
static int int_count;
#define SUB_BIT_WDT (0x01 < 13)
static __irq void Watchdog_Int(void)
{
Uart_Printf("\nWatchdog interrupt %d times",++int_count);
rSUBSRCPND = SUB_BIT_WDT;
rSRCPND = BIT_WDT_AC97;
rINTPND = BIT_WDT_AC97;
}
void Watchdog_Start(void)
{
rWTCNT = 16000;
rWTDAT = 16000;
pISR_WDT_AC97 = (unsigned int)Watchdog_Int;
rINTMSK &= (~BIT_WDT_AC97);
rINTSUBMSK &= (~SUB_BIT_WDT);
// 0xFF3C=不产生复位信号 0xFF3D=产生复位信号,约10秒后系统复位
rWTCON = 0xFF3C;
}
(3)说明
主函数中执行下列代码:
Timer0_Start();
Watchdog_Start();
while(1);
会看到串口约1秒输出一次定时器中断处理消息,约10秒输出一次看门狗中断处理消息。如果设置看门狗定时器控制寄存器的值为0xFF3D,则看门狗定时器超时时,会发出复位信号,即大约每隔10秒,系统会复位一次。
主程序在运行死循环,但串口输出还是可以进行的,这就是中断的功能了:中断程序的执行,处理其他事务。以前学微机原理的时候,讲中断只是抽象的概念,不好理解,这里就看得比较清楚了。
中断处理函数中,应该清除相应的中断请求位。对于看门狗中断,由于是通过子中断寄存器的,所以还要清除子中断源请求寄存器。如果不进行清除动作,则中断请求一直保持,相当于不停地发生中断,无法返回到主程序中。
armcc扩展了C语言,提供__irq关键字用以定义中断处理函数。曾试着不使用__irq,