/***********************************************************************************
* @fn halBoardInit
*
* @brief Set up board. Initialize MCU, configure I/O pins and user interfaces
*
* @param none
*
* @return none
*/
电路板的初始化,主要初始化MCU,配置I/O及用户应用接口:LEDS、按键、JoyStick、LCD。其中,初始化MCU主要为两个时钟的初始化。
void halBoardInit(void)
{
halMcuInit(); //初始化时钟;
//可以根据自己需要对LEDS、按键、JoyStick、LCD代码段进行修改或删除;
// LEDs
#ifdef SRF05EB_VERSION_1_3
// SmartRF05EB rev 1.3 has only one accessible LED
MCU_IO_DIR_OUTPUT(HAL_BOARD_IO_LED_1_PORT, HAL_BOARD_IO_LED_1_PIN);
HAL_LED_CLR_1();
#else
MCU_IO_DIR_OUTPUT(HAL_BOARD_IO_LED_1_PORT, HAL_BOARD_IO_LED_1_PIN);
HAL_LED_CLR_1();
MCU_IO_DIR_OUTPUT(HAL_BOARD_IO_LED_2_PORT, HAL_BOARD_IO_LED_2_PIN);
HAL_LED_CLR_2();
MCU_IO_DIR_OUTPUT(HAL_BOARD_IO_LED_3_PORT, HAL_BOARD_IO_LED_3_PIN);
HAL_LED_CLR_3();
MCU_IO_DIR_OUTPUT(HAL_BOARD_IO_LED_4_PORT, HAL_BOARD_IO_LED_4_PIN);
HAL_LED_CLR_4();
#endif
// Buttons
MCU_IO_INPUT(HAL_BOARD_IO_BTN_1_PORT, HAL_BOARD_IO_BTN_1_PIN, MCU_IO_TRISTATE);
// Joystick push input
MCU_IO_INPUT(HAL_BOARD_IO_JOY_MOVE_PORT, HAL_BOARD_IO_JOY_MOVE_PIN, \
MCU_IO_TRISTATE);
// Analog input
MCU_IO_PERIPHERAL(HAL_BOARD_IO_JOYSTICK_ADC_PORT, HAL_BOARD_IO_JOYSTICK_ADC_PIN);
halLcdSpiInit();
halLcdInit();
halIntOn();
}
在halBoardInit()中,关于LED等外设的修改相对容易不做过多介绍;
由于在per_test丢包率测试程序时,在修改连续发送数据包的时间间隔时卡在这好长时间,因此主要解读下在该项目文件关于MCU的晶振设置;
在halMcuInit()中主要调用了clockSetMainSrc()和clockSelect32k()其功能代码如下:
/******************************************************************************
* @fn clockSetMainSrc
*
* @brief Function for setting the main system clock source.
* The function turns off the clock source that is not being used.
* TICKSPD is set to the same frequency as the source.
*
* @param uint8 source (one of CLOCK_SRC_HFRC or CLOCK_SRC_XOSC)
*
* @return void
*
******************************************************************************/
void clockSetMainSrc(uint8 source)
{
//32K的晶振 设置为 RCOSC;
register uint8 osc32k_bm = CLKCONCMD & CLKCON_OSC32K_BM;
// Source can have the following values:
// CLOCK_SRC_XOSC 0x00 High speed Crystal Oscillator (XOSC)
// CLOCK_SRC_HFRC 0x01 Low power RC Oscillator (HFRC)
//2430中开启16M和32M晶振,Ti论坛上的解释是2430的移植代码,这部分在2430中是手动来控制,2530中已经变成自动控制;
//相关链接见文章末尾;
SLEEPCMD &= ~SLEEP_OSC_PD_BM; // power up both oscillators
while (!CC2530_IS_HFRC_STABLE() || ((SLEEPSTA & SLEEP_OSC_PD_BM)!=0));// wait until the oscillator is stable
NOP();
//设置主时钟源,并将TICKSPD和 CLKSPD 跟时钟源一致;
if (source == CLOCK_SRC_HFRC){
CLKCONCMD = (osc32k_bm | CLKCON_OSC_BM | TICKSPD_DIV_2 | CLKCON_CLKSPD_BM);
}
else if (source == CLOCK_SRC_XOSC){
CLKCONCMD = (osc32k_bm | TICKSPD_DIV_1);
}
//通过查询CLKCONSTA来确定修改后的时钟源是否达到稳定;
CC2530_WAIT_CLK_UPDATE();
SLEEPCMD |= SLEEP_OSC_PD_BM; // power down the unused oscillator
}
/******************************************************************************
* @fn clockSelect32k
*
* @brief Function for selecting source for the 32kHz oscillator
*
* @param uint8 source (one of CLOCK_32K_XTAL or CLOCK_32K_RCOSC)
*
* @return uint8 - SUCCESS or FAILED
*
******************************************************************************/
uint8 clockSelect32k(uint8 source)
{
// System clock source must be high frequency RC oscillator before
// changing 32K source.
//在改变32K时钟源之前 16M RCOSC必须处于活动状态;
//作为芯片初始化开始,删掉是可以的,这样处理为了代码的性能?模仿吧:)
if( !(CLKCONSTA & CLKCON_OSC_BM) )
return FAILED;
//选择不同的32K时钟源
if (source == CLOCK_32K_XTAL){
CLKCONCMD &= ~CLKCON_OSC32K_BM;
}
else if (source == CLOCK_32K_RCOSC){
CLKCONCMD |= CLKCON_OSC32K_BM;
}
//通过查询CLKCONSTA来确定修改后的时钟源是否达到稳定;
CC2530_WAIT_CLK_UPDATE();
return SUCCESS;
}
/***********************************************************************************
* @fn halMcuInit
*
* @brief Set Main Clock source to XOSC
*
* @param none
*
* @return none
*/
void halMcuInit(void)
{
// if 32k clock change fails, set system clock to HF RC and try again
//32K时钟源选择位 在 主系统时钟工作在 16M RCOSC 下才能设置有效;
//若第一次设置无效,则进行第二次设置,若二次设置失败,则指示灯亮;
//关键部分进行二次检验性设置?后面CCA启用过程中也是进行二次检验,稍有差别;
//如此处理,函数的可移植性大大增强,可以任何时候调用来进行时钟的设置;
if(clockSelect32k(CLOCK_32K_XTAL) != SUCCESS) {
clockSetMainSrc(CLOCK_SRC_HFRC);
if(clockSelect32k(CLOCK_32K_XTAL) != SUCCESS) {
HAL_ASSERT(FALSE);
}
}
//设置或回复 系统主时钟源为 32M XOSC ;
clockSetMainSrc(CLOCK_SRC_XOSC);
}
总结:
1. 32K XTAL时钟源的选择操作进行两次的问题,猜测可能是由于 “对于OSC32K 寄存器操作有效主时钟必须工作在16M RCOSC时钟源下”,因此首先操作一次,如果失败 创造条件再进行第二次操作,最后恢复系统主时钟源(对于一定条件下才能进行的操作 都可参考这种程序设计结构?);
2. 时刻关注寄存器或变量的初始值 及相关修改位置,如:CLKCONCMD。另外,可在此时来修改TICKSPD的值来进行定时器的时间的调整。
参考链接:http://e2e.ti.com/support/low_power_rf/f/156/t/74054.aspx#269288
http://e2e.ti.com/support/low_power_rf/f/158/t/98362.aspx#343868