昨天我讲了自己对LM3S时钟配置函数的一些理解,今天我对前两天做的图形化配置文件中时钟部分做了一些修改。
原时钟配置函数因为参数是变量,所以需要在程序中作一些判断,以适应不同场合的应用,不过我们再初始化的时候参数是常量,所以,我在函数中加入了条件编译选项,可以根据当前配置时钟有选择性的编译一些语句,既可以减小代码的体积,同时由于程序中不需要判断了,对程序运行效率也会有一定的提升。
比如对于锁相环相关配置是这样写的:
#if(!(__SYSCTL_BOTH_RCC & SYSCTL_RCC_BYPASS))
for(ulDelay = 32768; ulDelay > 0; ulDelay--)
{
if(HWREG(SYSCTL_RIS) & SYSCTL_INT_PLL_LOCK)
{
break;
}
}
ulRCC &= ~(SYSCTL_RCC_BYPASS);
#if (__SYSCTL_BOTH_RCC & 0x80000000)
ulRCC2 &= ~(SYSCTL_RCC2_BYPASS2);
#endif
#endif
这句话就是说如果新设置的时钟使用了锁相环,那么编译这段,如果没有使用锁相环,则不编译。在这个条件编译里面还嵌套了一个条件编译,使用时钟设置常量的第一位来判断是否使用了RCC2,如果没有使用RCC2,那么有关RCC2的语句也不被编译。
不过并非所有的RCC2相关语句都不编译,比如最开始的这一段:
ulRCC = HWREG(SYSCTL_RCC);
ulRCC2 = HWREG(SYSCTL_RCC2);
ulRCC |= SYSCTL_RCC_BYPASS;
ulRCC &= ~(SYSCTL_RCC_USESYSDIV);
ulRCC2 |= SYSCTL_RCC2_BYPASS2;
HWREG(SYSCTL_RCC) = ulRCC;
HWREG(SYSCTL_RCC2) = ulRCC2;
if(((ulRCC & SYSCTL_RCC_IOSCDIS) && !(__SYSCTL_BOTH_RCC & SYSCTL_RCC_IOSCDIS)) || ((ulRCC & SYSCTL_RCC_MOSCDIS) && !(__SYSCTL_BOTH_RCC & SYSCTL_RCC_MOSCDIS)))
{
ulRCC &= (~(SYSCTL_RCC_IOSCDIS | SYSCTL_RCC_MOSCDIS) |
(__SYSCTL_BOTH_RCC & (SYSCTL_RCC_IOSCDIS | SYSCTL_RCC_MOSCDIS)));
HWREG(SYSCTL_RCC) = ulRCC;
if((ulRCC2 & SYSCTL_RCC2_USERCC2) &&
(((ulRCC2 & SYSCTL_RCC2_OSCSRC2_M) == SYSCTL_RCC2_OSCSRC2_30) ||
((ulRCC2 & SYSCTL_RCC2_OSCSRC2_M) == SYSCTL_RCC2_OSCSRC2_32)))
{
SysCtlDelay(4096);
}
else
{
SysCtlDelay(524288);
}
}
这一段是根据当前时钟来设置我们配置时钟时运行的时钟的,如果当前时钟使用了RCC2,那么我们在修改时钟的时候也需要修改RCC2中的值,因此这一段无论是否使用RCC2都要被编译。同理,还有:
ulRCC &= ~(SYSCTL_RCC_XTAL_M | SYSCTL_RCC_OSCSRC_M |
SYSCTL_RCC_PWRDN | SYSCTL_RCC_OEN);
ulRCC |= (__SYSCTL_BOTH_RCC & (SYSCTL_RCC_XTAL_M | SYSCTL_RCC_OSCSRC_M |
SYSCTL_RCC_PWRDN | SYSCTL_RCC_OEN))|(__SYSCTL_ONLY_RCC2 & 0x00000070);
ulRCC2 &= ~(SYSCTL_RCC2_USERCC2 | SYSCTL_RCC2_OSCSRC2_M |
SYSCTL_RCC2_PWRDN2);
ulRCC2 |= (__SYSCTL_BOTH_RCC & (SYSCTL_RCC2_USERCC2 | SYSCTL_RCC_OSCSRC_M |
SYSCTL_RCC2_PWRDN2))|(__SYSCTL_ONLY_RCC2 & 0x00000070);
#if __SYSCTL_ONLY_RCC2
ulRCC2 |= (__SYSCTL_ONLY_RCC2 & 0x00000070);
#endif
HWREG(SYSCTL_MISC) = SYSCTL_INT_PLL_LOCK;
if(ulRCC2 & SYSCTL_RCC2_USERCC2)
{
HWREG(SYSCTL_RCC2) = ulRCC2;
HWREG(SYSCTL_RCC) = ulRCC;
}
else
{
HWREG(SYSCTL_RCC) = ulRCC;
HWREG(SYSCTL_RCC2) = ulRCC2;
}
虽然临时时钟已经设置好,但是因为这段程序中包含RCC2寄存器中USERCC2位的操作,所以也需要被编译,因为如果当前时钟使用了RCC2,而我们新的时钟不需要RCC2,则需要改变USERCC2寄存器的值。这一段中有关RCC2的语句也需要被编译。
当然我们的配置文件是在系统启动时运行的,因此此时可以使用复位时的默认值来处理,这样的话,时钟设置就更加简便了,不过,因为LM3S有众多复位源,每种复位源复位后是什么状态,我还不清楚,Datasheet中说的也比较笼统。如果能够明确这些状态的话,就可以再将复位源作为条件编译的一种条件,应该可以获得更加优异的代码的。
目前优化程度如下(还是以上次例子来说):
不使用初始化配置文件
Program Size: Code=1180 RO-data=172 RW-data=0 ZI-data=352
使用配置文件,同时配置中使用了锁相环及RCC2
Program Size: Code=956 RO-data=16 RW-data=0 ZI-data=352
使用配置文件,使用锁相环,但不使用RCC2
Program Size: Code=940 RO-data=16 RW-data=0 ZI-data=352
使用配置文件,使用RCC2,使用低频晶振,但不使用锁相环
Program Size: Code=920 RO-data=16 RW-data=0 ZI-data=352
使用配置文件,不使用锁相环及RCC2
Program Size: Code=912 RO-data=16 RW-data=0 ZI-data=352
下面是新的设置文件包,使用方法见
https://bbs.eeworld.com.cn/thread-237849-1-1.html
LM3S_init_20110120.rar
(4.85 KB, 下载次数: 11)