Hi,
My application needs to do some operation after every 140us in a loop for 3 - 4 seconds (we can say it as scan duration). To check the timer accuracy I have increased the scan duration to 30 seconds. In my application i am using Timer1 in my application timer module, since some times I need timer which can accommodate in 16-bits only. I want to configure the CC2530 to work on 32MHz and timer for 1 MHz. Below is the code, where I have set the scan duration to 30 seconds, Timer1 is set to 140us, on every interrupt callback function I am reducing the scan duration by 140us and resetting the timer1 for 140us. My expectation was that the end of scan duration shall reach exactly after 30 seconds but it is taking 35 - 36 seconds to reach the end of scan duration. The same application works perfectly on MSP430F5438A microcontroller, Please find my code below:
#include <ioCC2530.h>
#include <stdint.h>
#include "hal_int.h"
#include "hal_mcu.h"
#include "hal_board_cfg.h"
#include "clock.h"
#define HAL_INT_ON(x) st( EA = 1; )
#define HAL_INT_OFF(x) st( EA = 0; )
#define HAL_INT_LOCK(x) st( (x) = EA; EA = 0; )
#define HAL_INT_UNLOCK(x) st( EA = (x); )
/******************************************************************************
* @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_t source)
{
register uint8_t 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)
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();
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);
CLKCONCMD = 0x28; // Tick speed 1 MHz, Clock speed 32MHz
}
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 FAILURE
*
******************************************************************************/
retval_t clockSelect32k(uint8 source)
{
// System clock source must be high frequency RC oscillator before
// changing 32K source.
if( !(CLKCONSTA & CLKCON_OSC_BM) )
return FAILURE;
if (source == CLOCK_32K_XTAL){
CLKCONCMD &= ~CLKCON_OSC32K_BM;
}
else if (source == CLOCK_32K_RCOSC){
CLKCONCMD |= CLKCON_OSC32K_BM;
}
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
if(clockSelect32k(CLOCK_32K_XTAL) != SUCCESS) {
clockSetMainSrc(CLOCK_SRC_HFRC);
if(clockSelect32k(CLOCK_32K_XTAL) != SUCCESS) {
// HAL_ASSERT(FALSE);
}
}
clockSetMainSrc(CLOCK_SRC_XOSC);
}
void halBoardInit(void)
{
halMcuInit();
// Initialize interrupts
IEN0 = IEN0_EA | IEN0_STIE | IEN0_ENCIE | IEN0_ADCIE | IEN0_RFERRIE;
IEN1 = IEN1_P0IE | IEN1_T1IE | IEN1_DMAIE;
IEN2 = IEN2_WDTIE | IEN2_RFIE;
HAL_INT_ON();
}
uint32_t t_scan_time = 30000000;
void timer_test(void)
{
// Set the Timer 1 compare register
T1CC0L = 0x8C;
T1CC0H = 0x00;
// Write to the counter register to reset it
T1CNTL = 0x00;
// Set the counter running mode to Free-running
T1CTL |= 0x01;
T1CCTL0 |= 0x40;
if (t_scan_time > 140)
{
t_scan_time -= 140;
}
else
{
t_scan_time = 30000000;
}
}
/***********************************************************************************
* @fn main
*
* @brief This is the main entry of the "PER test" application.
*
* @param basicRfConfig - file scope variable. Basic RF configuration data
* appState - file scope variable. Holds application state
* appStarted - file scope variable. Used to control start and stop of
* transmitter application.
*
* @return none
*/
void main (void)
{
// Initialise board peripherals
halBoardInit();
// Configure the Timer registers
// TIMER 1 -- Used for non-blocking timers; Channel 0 is used.
// Set prescaler divider value to 1 and Operation is suspended
T1CTL = 0x00;
T1CCTL0 = 0x04; // Set Compare mode
IEN1 |= 0x02; // IEN1.T1EN = 0 .. 1
// Set the Timer 1 compare register
T1CC0L = 0x8C;
T1CC0H = 0x00;
// Write to the counter register to reset it
T1CNTL = 0x00;
// Set the counter running mode to Free-running
T1CTL |= 0x01;
T1CCTL0 |= 0x40;
while(1);
}
/***********************************************************************************
* @fn Timer1_ISR
*
* @brief Timer 1 Interrupt handler; It is used for non-blocking timers
*
* @param none
*
* @return none
*/
HAL_ISR_FUNCTION(T1_ISR, T1_VECTOR)
{
// ENTER_CRITICAL_REGION();
// Handle the interrupt if the
if ((T1CCTL0 & 0x40) && (T1STAT & 0x21))
{
// Stop timer and Disable Interrupt
T1CCTL0 &= ~0x40;
timer_test();
}
// Clear Timer 1 interrupts
T1STAT = 0x00;
// LEAVE_CRITICAL_REGION();
}
Looking forward to your support.
Thanks and regards,
Praveen