Question

I am writing some code for the CC2541 (8051 based) MCU, which is TI's BTLE SOC and am having a problem getting timer based interrupts to fire. I have successfully configured GPIO interrupts, and can even use that interrupt to set the timer interrupt flag (which then fires the timer interrupt)...but I can't get the timer itself to fire the interrupt on rollover.

Here is some base code that I'm using:

   /**************************************************************************************************
 *                                           Includes
 **************************************************************************************************/
#include <ioCC2541.h>
#include <hal_defs.h>
#include <hal_board_cfg.h>

 unsigned int ISR_Counter = 0;
 uint16 loop_Counter = 0;

void main(void)
{

  HAL_BOARD_INIT();

  P1DIR |= BV(0);
  P0DIR |= BV(4);

  P1_0 = 1;
  P0_4 = 1;


 /*****************************************************************************/
    //Configure sleep timer

   IEN0 &= ~BV(5);  //Disable interrupt

  //Set timer compare value
  ST2 = 0x00;
  ST1 = 0xFF;
  ST0 = 0x00;

  IRCON &= ~0x80;  //Clear flag
  IEN0 |= BV(5);  //Enable interrupt

   EA = 1;   //Enable all interrupts

   while(1){ 

    if (loop_Counter == 0){ P0_4 ^= 1; }
    loop_Counter++;
    }

}
/**************************************************************************************************
                                           CALL-BACKS
**************************************************************************************************/


/*Sleep Timer interrupt */
_PRAGMA(vector=ST_VECTOR)
__interrupt void SLEEP_ISR(void)
{
  P1_0 ^= 1; // P1.0 = toggle
  IRCON &= ~0x80;  //Clear flag
  ISR_Counter++; 
}

The HAL_BOARD_INIT function (and related defs) is:

/* Setting Clocks */

// 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 );                            \
}

// switch to the 32MHz XOSC and wait until it is stable
#define SET_OSC_TO_XOSC()                                                      \
{                                                                              \
  CLKCONCMD = (CLKCONCMD & 0x80) | CLKCONCMD_32MHZ;                            \
  while ( (CLKCONSTA & ~0x80) != CLKCONCMD_32MHZ );                            \
}

// set 32kHz OSC and wait until it is stable
#define SET_32KHZ_OSC()                                                        \
{                                                                              \
  CLKCONCMD = (CLKCONCMD & ~0x80) | OSC_32KHZ;                                 \
  while ( (CLKCONSTA & 0x80) != OSC_32KHZ );                                   \
}

#define START_HSOSC_XOSC()                                                     \
{                                                                              \
  SLEEPCMD &= ~OSC_PD;            /* start 16MHz RCOSC & 32MHz XOSC */         \
  while (!(SLEEPSTA & XOSC_STB)); /* wait for stable 32MHz XOSC */             \
}

#define STOP_HSOSC()                                                           \
{                                                                              \
  SLEEPCMD |= OSC_PD;             /* stop 16MHz RCOSC */                       \
}
/* ----------- Board Initialization ---------- */

#define HAL_BOARD_INIT()                                         \
{                                                                \
   /* Set to 16Mhz to set 32kHz OSC, then back to 32MHz */       \
  START_HSOSC_XOSC();                                            \
  SET_OSC_TO_HSOSC();                                            \
  SET_32KHZ_OSC();                                               \
  SET_OSC_TO_XOSC();                                           \
  STOP_HSOSC();                                                  \
                                                                 \
  /* Turn on cache prefetch mode */                              \
  PREFETCH_ENABLE();                                             \
                                                                 \
  /* set direction for GPIO outputs  */                          \
  LED1_DDR |= LED1_BV;                                           \
  LED2_DDR |= LED2_BV;                                           \
  GYRO_VDD_DDR |= GYRO_VDD_BV;                                   \
  DCDC_DDR |= DCDC_BV;     /* Set P0_7 as output */              \
  GYRO_VDD_SBIT = 1;       /* Gyro must be on for I2C to work */ \
  P0DIR |= BV(5);          /* Unused pin as output */            \
  P2DIR |= BV(0);          /* Unused pin as output */            \
  P1DIR |= 0x3C;           /* UART pins as output */             \
  P0INP =  0x4E;           /* Tri-state inputs */                \
}

I have run it through the debugger and can see that the sleep timer registers are changing, so the timer is in fact running. Like I said, I can also set the interrupt flag manually through another interrupt handler, and the interrupt fires just as you would expect. I've tried configuring the other timers as well, as well as the UART interrupts...all with the same result. At this point, I'm not not sure if it is an issue with the interrupts themselves or something with the configuration of the clock source....either way I'm sure it's something stupid I'm doing wrong.

I should add that I am using small pieces of the HAL code that TI includes with their BTLE stack, but I am not using any part of the OSAL. In fact I'm not using the BT aspect of the chip at all.

Was it helpful?

Solution

I still haven't figured out why the normal timer interrupts were not working, but I did manage to get the sleep timer to work (which is what I needed anyway to pull the chip out of low power mode).

The problem was that a timer compare event throws an interrupt, but does not reset the timer (which I was assuming it would)...and since it is a 24 bit timer running at 32 kHz, it takes a very long time to roll over and hit the old set point again.

OTHER TIPS

The problem is you need to read the register, add your time to it and write to the compare register. The counter is not intended to reset.

Maybe the sleep timer is used by the portion of the HAL you've imported to your code. You might try using one of the other timers, not used by the BLE stack (I think 1,2 and 4 are available).

Of course, you'll need to modify a different set of registers, for setting the counter value, and enabling the interrupt.

For timer1, see T1IET and T1CC0L/H ( defined in ioCC2541.h, and in the developer manual for CC2541, ofc )

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top