[资料分享]

CC2541之解析协议栈的晶振初始化过程

[复制链接]
541|14
手机看帖
扫描二维码
随时随地手机跟帖
nawu|  楼主 | 2019-7-10 11:33 | 显示全部楼层

解析代码

1、代码位置


在2541的协议栈初始化最开头的HAL_BOARD_INIT处,协议栈对晶振进行了初始化。


使用特权

评论回复
nawu|  楼主 | 2019-7-10 11:33 | 显示全部楼层
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中才频繁地对晶振各种起震、切换。

使用特权

评论回复
nawu|  楼主 | 2019-7-10 11:33 | 显示全部楼层
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 */             \
}

使用特权

评论回复
nawu|  楼主 | 2019-7-10 11:34 | 显示全部楼层

然而我去查找CC254X的芯片手册,发现SLEEPCMD没有OSC_PD(第2位)、SLEEPSTA也没有XOSC_STB(第6位),如下图:


使用特权

评论回复
nawu|  楼主 | 2019-7-10 11:34 | 显示全部楼层

于是参考CC2430的datasheet:


协议栈在这里将OSC_PD清零,也就是同时起震内部16M的RC振荡器和外部的32M晶振。

然后判断XOSC_STB状态位,等待外部晶振起震并稳定。



使用特权

评论回复
nawu|  楼主 | 2019-7-10 11:34 | 显示全部楼层
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 );                            \
}

使用特权

评论回复
nawu|  楼主 | 2019-7-10 11:35 | 显示全部楼层

其中第一行代码是让CLKCONCMD寄存器的第7位保持、其他位清零,然后第6、3、0位置1,也就是值变成x100 1001。

参照datasheet来看:

也就是不改变32k小晶振的配置、只切换到内部16M的RC振荡器。


使用特权

评论回复
nawu|  楼主 | 2019-7-10 11:35 | 显示全部楼层

这么做的意义在于:在切换32k小晶振前,必须先将OSC配置为16M。


  所以接下来就可以配置32k小晶振了。


使用特权

评论回复
nawu|  楼主 | 2019-7-10 11:35 | 显示全部楼层
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 );                                   \
}

使用特权

评论回复
nawu|  楼主 | 2019-7-10 11:35 | 显示全部楼层
默认是使用外部的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外部晶振》。

使用特权

评论回复
nawu|  楼主 | 2019-7-10 11:36 | 显示全部楼层

4)SET_OSC_TO_XOSC()(重新切换到32M外部晶振)


内部的32K的RC振荡电路已经配置好,所以这时候系统时钟即可配置为最快的外部32M晶振。


使用特权

评论回复
nawu|  楼主 | 2019-7-10 11:36 | 显示全部楼层

5)STOP_HSOSC()(停止内部16M的RC振荡器)


内部的16M的RC振荡电路已经没用了,即可关掉,省电。



使用特权

评论回复
dirtwillfly| | 2019-7-14 22:49 | 显示全部楼层
感谢分享

使用特权

评论回复
htmlme| | 2019-7-15 22:44 | 显示全部楼层
学习一下CC2541      

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

72

主题

3307

帖子

3

粉丝