一、简介
本篇解析协议栈的晶振初始化过程。
二、实验平台
协议栈版本:BLE-CC254x-1.3.2
编译软件:IAR 8.20.2
三、版权声明
博主:甜甜的大香瓜
声明:喝水不忘挖井人,转载请注明出处。
原文地址:http://blog.csdn.net/feilusia
联系方式:[email protected]
技术交流QQ群:127442605
四、解析代码
1、代码位置
在2541的协议栈初始化最开头的HAL_BOARD_INIT处,协议栈对晶振进行了初始化。
2、晶振初始化的流程
/* Board Initialization */ #define HAL_BOARD_INIT() \ { \ /* Set to 16Mhz to set 32kHz OSC, then back to 32MHz */ \ START_HSOSC_XOSC();//开启内部16M的RC振荡器和外部32M晶振 SET_OSC_TO_HSOSC();//切换到内部16M的RC振荡器(是32k的OSC切换的前提) SET_32KHZ_OSC(); //切换32k的OSC32k SET_OSC_TO_XOSC(); //切换到外部32M晶振 STOP_HSOSC(); //停止内部16M的RC振荡器 \ /* Enable cache prefetch mode. */ \ PREFETCH_ENABLE(); \ }
要想切换OSC32k小晶振,就必须先把OSC切换到内部16M的RC振荡器。
所以在HAL_BOARD_INIT中才频繁地对晶振各种起震、切换。
3、各个函数解析
1)START_HSOSC_XOSC()(开启内部16M的RC振荡器和外部32M晶振):
#define START_HSOSC_XOSC() \ { \ SLEEPCMD &= ~OSC_PD; /* start 16MHz RCOSC & 32MHz XOSC */ \ while (!(SLEEPSTA & XOSC_STB)); /* wait for stable 32MHz XOSC */ \ }
然而我去查找CC254X的芯片手册,发现SLEEPCMD没有OSC_PD(第2位)、SLEEPSTA也没有XOSC_STB(第6位),如下图:
于是参考CC2430的datasheet:
协议栈在这里将OSC_PD清零,也就是同时起震内部16M的RC振荡器和外部的32M晶振。
然后判断XOSC_STB状态位,等待外部晶振起震并稳定。
2)SET_OSC_TO_HSOSC()(切换到内部16M的RC振荡器)
// switch to the 16MHz HSOSC and wait until it is stable #define SET_OSC_TO_HSOSC() \ { \ CLKCONCMD = (CLKCONCMD & 0x80) | CLKCONCMD_16MHZ; \ while ( (CLKCONSTA & ~0x80) != CLKCONCMD_16MHZ ); \ }
其中第一行代码是让CLKCONCMD寄存器的第7位保持、其他位清零,然后第6、3、0位置1,也就是值变成x100 1001。
参照datasheet来看:
也就是不改变32k小晶振的配置、只切换到内部16M的RC振荡器。
这么做的意义在于:在切换32k小晶振前,必须先将OSC配置为16M。
所以接下来就可以配置32k小晶振了。
3)SET_32KHZ_OSC()(切换32k的OSC)
// set 32kHz OSC and wait until it is stable #define SET_32KHZ_OSC() \ { \ CLKCONCMD = (CLKCONCMD & ~0x80) | OSC_32KHZ; \ while ( (CLKCONSTA & 0x80) != OSC_32KHZ ); \ }默认是使用外部的32k的OSC小晶振。
// For non-USB, assume external, unless an internal crystal is explicitly indicated. #if !defined (XOSC32K_INSTALLED) || (defined (XOSC32K_INSTALLED) && (XOSC32K_INSTALLED == TRUE)) #define OSC_32KHZ EXTERNAL_CRYSTAL_OSC #else #define OSC_32KHZ INTERNAL_RC_OSC #endif如果要使用低功耗,外部的32k小晶振是必须的。参看《CC2541之32.768kHZ外部晶振》。
4)SET_OSC_TO_XOSC()(重新切换到32M外部晶振)
内部的32K的RC振荡电路已经配置好,所以这时候系统时钟即可配置为最快的外部32M晶振。
5)STOP_HSOSC()(停止内部16M的RC振荡器)
内部的16M的RC振荡电路已经没用了,即可关掉,省电。