This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC2538 MAC Timer



Hi,

I am using CC2538 with the SmartRF06 Evaluation Board to carry a project using the Contiki OS.

At the moment I need to get the Start of Frame Delimiter value when the platform receive a beacon. The problem is that the value that I read is very big, despite it's read very early (values in the rank of b28f2d, when meausring the real time i get values of  481c1). Could anyone help me in understanding how to understand this values or where I have failed with the configuration?

I  have done it following the instructions written in the User's Guide section "12.1.10 Capture Input". The function called to read the sfd is written below:

unsigned char s;
rtimer_clock_t sfd;

HAL_ENTER_CRITICAL_SECTION(s);

REG(RFCORE_SFR_MTMSEL) = (REG(RFCORE_SFR_MTMSEL) & ~RFCORE_SFR_MTMSEL_MTMSEL) | 0x00000001;

sfd = REG(RFCORE_SFR_MTM0) & RFCORE_SFR_MTM0_MTM0;
sfd |= ((REG(RFCORE_SFR_MTM1) & RFCORE_SFR_MTM1_MTM1) << 8);

REG(RFCORE_SFR_MTMSEL) = (REG(RFCORE_SFR_MTMSEL) & ~RFCORE_SFR_MTMSEL_MTMOVFSEL)|0x00000010;

sfd |= ((REG(RFCORE_SFR_MTMOVF0) & RFCORE_SFR_MTMOVF0_MTMOVF0) << 16);
sfd |= ((REG(RFCORE_SFR_MTMOVF1) & RFCORE_SFR_MTMOVF1_MTMOVF1) << 24);
// sfd |= ((REG(RFCORE_SFR_MTMOVF2) & RFCORE_SFR_MTMOVF2_MTMOVF2) << 32);

HAL_EXIT_CRITICAL_SECTION(s);

Where:

#define HAL_ENTER_CRITICAL_SECTION(x)  \
  do { (x) = !cpu_cpsid(); } while (0)

#define HAL_EXIT_CRITICAL_SECTION(x) \
  do { if (x) { cpu_cpsie();} } while (0)

and the functions cpu_cpsid() and cpu_cpsie() respectively disable and enable all the interrupts.

To read the values of the current value of the timer I use the sleep timer:

rv = REG(SMWDTHROSC_ST0);
rv |= (REG(SMWDTHROSC_ST1) << 8);
rv |= (REG(SMWDTHROSC_ST2) << 16);
rv |= (REG(SMWDTHROSC_ST3) << 24);

The initial configurations that I do are the following:

static int init(void) {

  unsigned char s;

  if(rf_flags & RF_ON) {
    return 0;
  }

  REG(SYS_CTRL_I_MAP) &= ~0x00000001;    //Select regular interrupt map
  nvic_init();
  sys_ctrl_init();

  /* Enable clock for the RF Core while Running, in Sleep and Deep Sleep */
  REG(SYS_CTRL_RCGCRFC) = 1;
  REG(SYS_CTRL_SCGCRFC) = 1;
  REG(SYS_CTRL_DCGCRFC) = 1;

  REG(RFCORE_XREG_CCACTRL0) = CC2538_RF_CCA_THRES_USER_GUIDE;

  /*
   * Changes from default values
   * See User Guide, section "Register Settings Update"
   */
  REG(RFCORE_XREG_TXFILTCFG) = 0x09;    /** TX anti-aliasing filter bandwidth */
  REG(RFCORE_XREG_AGCCTRL1) = 0x15;     /** AGC target value */
  REG(ANA_REGS_IVCTRL) = 0x0B;          /** Bias currents */
  REG(RFCORE_XREG_MDMCTRL1)= 0x00000014; /** Correlation Treshold*/

  /*Set the PREAMBLE_LENGTH bit of the MDMCTRL0 register */
  REG(RFCORE_XREG_MDMCTRL0) =   (REG(RFCORE_XREG_MDMCTRL0) & ~ RFCORE_XREG_MDMCTRL0_PREAMBLE_LENGTH) | RFCORE_XREG_MDMCTRL0_PREAMBLE_LENGTH;

  /*After frame reception, there is by default an interval of 192 μs where
   * SFD detection is disabled.
   * This interval can be removed by clearing the RX2RX_TIME_OFF bit
   * of the FSMCTRL register.
   */
  REG(RFCORE_XREG_FSMCTRL) &= ~ RFCORE_XREG_FSMCTRL_RX2RX_TIME_OFF;

  /*
   * Defaults:
   * Auto CRC; Append RSSI, CRC-OK and Corr. Val.; CRC calculation;
   * RX and TX modes with FIFOs
   */
  REG(RFCORE_XREG_FRMCTRL0) = RFCORE_XREG_FRMCTRL0_AUTOCRC;

#if CC2538_RF_AUTOACK
  REG(RFCORE_XREG_FRMCTRL0) |= RFCORE_XREG_FRMCTRL0_AUTOACK;
#endif

  /* If we are a sniffer, turn off frame filtering */
#if CC2538_RF_CONF_SNIFFER
  REG(RFCORE_XREG_FRMFILT0) &= ~RFCORE_XREG_FRMFILT0_FRAME_FILTER_EN;
#endif

  /* Disable source address matching and autopend */
  REG(RFCORE_XREG_SRCMATCH) = 0;

  /* MAX FIFOP threshold */
  REG(RFCORE_XREG_FIFOPCTRL) = CC2538_RF_MAX_PACKET_LEN;

  /* Set TX Power */
  REG(RFCORE_XREG_TXPOWER) = CC2538_RF_TX_POWER;

  set_channel(rf_channel);

  /* Acknowledge RF interrupts, FIFOP only */
  REG(RFCORE_XREG_RFIRQM0) |= RFCORE_XREG_RFIRQM0_FIFOP;
  nvic_interrupt_enable(NVIC_INT_RF_RXTX);

  /* Acknowledge all RF Error interrupts */
  REG(RFCORE_XREG_RFERRM) = RFCORE_XREG_RFERRM_RFERRM;
  nvic_interrupt_enable(NVIC_INT_RF_ERR);

  if(CC2538_RF_CONF_TX_USE_DMA) {
      /* Disable peripheral triggers for the channel */
      udma_channel_mask_set(CC2538_RF_CONF_TX_DMA_CHAN);

      /*
       * Set the channel's DST. SRC can not be set yet since it will change for
       * each transfer
       */
    udma_set_channel_dst(CC2538_RF_CONF_TX_DMA_CHAN, RFCORE_SFR_RFDATA);
  }

  if(CC2538_RF_CONF_RX_USE_DMA) {
    /* Disable peripheral triggers for the channel */
    udma_channel_mask_set(CC2538_RF_CONF_RX_DMA_CHAN);

    /*
     * Set the channel's SRC. DST can not be set yet since it will change for
     * each transfer
     */
    udma_set_channel_src(CC2538_RF_CONF_RX_DMA_CHAN, RFCORE_SFR_RFDATA);
  }

  /* Enable MAC Timer*/

  CC2538_MAC_RADIO_TIMER_WAKE_UP();

  REG(RFCORE_SFR_MTCTRL) |= (RFCORE_SFR_MTCTRL_LATCH_MODE|RFCORE_SFR_MTCTRL_SYNC);

  nvic_interrupt_enable(NVIC_INT_MACTIMER);

  set_poll_mode(0);

  process_start(&cc2538_rf_process, NULL);

  rf_flags |= RF_ON;

  ENERGEST_ON(ENERGEST_TYPE_LISTEN);

  return 1;
}

Here i start and configure the MAC Timer to be synchronized with the 32KHz clock:

#define CC2538_MAC_RADIO_TIMER_WAKE_UP()    do { \
            HAL_CLOCK_STABLE(); \
            REG(RFCORE_SFR_MTCTRL) |= RFCORE_SFR_MTCTRL_RUN; \
            REG(RFCORE_SFR_MTCTRL) |= RFCORE_SFR_MTCTRL_SYNC; \
            while(!(RFCORE_SFR_MTCTRL & RFCORE_SFR_MTCTRL_STATE));\
} while(0)

#define HAL_CLOCK_STABLE()    do { \
    while ( !((SYS_CTRL_CLOCK_STA) & (SYS_CTRL_CLOCK_STA_XOSC_STB)));\
} while(0)

And the   sys_ctrl_init(); function sets the osillators frequencies:

void sys_ctrl_init() {
uint32_t val;

#if SYS_CTRL_OSC32K_USE_XTAL
  /* Set the XOSC32K_Q pads to analog for crystal */
  GPIO_SOFTWARE_CONTROL(GPIO_PORT_TO_BASE(GPIO_D_NUM), GPIO_PIN_MASK(6));
  GPIO_SET_INPUT(GPIO_PORT_TO_BASE(GPIO_D_NUM), GPIO_PIN_MASK(6));
  ioc_set_over(GPIO_D_NUM, 6, IOC_OVERRIDE_ANA);
  GPIO_SOFTWARE_CONTROL(GPIO_PORT_TO_BASE(GPIO_D_NUM), GPIO_PIN_MASK(7));
  GPIO_SET_INPUT(GPIO_PORT_TO_BASE(GPIO_D_NUM), GPIO_PIN_MASK(7));
  ioc_set_over(GPIO_D_NUM, 7, IOC_OVERRIDE_ANA);
#endif

  /*
   * Desired Clock Ctrl configuration:
   * 32KHz source: RC or crystal, according to SYS_CTRL_OSC32K_USE_XTAL
   * System Clock: 32 MHz
   * Power Down Unused
   * I/O Div: according to SYS_CTRL_IO_DIV
   * Sys Div: according to SYS_CTRL_SYS_DIV
   * Rest: Don't care
   */

  val = SYS_CTRL_OSCS | SYS_CTRL_CLOCK_CTRL_OSC_PD
    | SYS_CTRL_IO_DIV | SYS_CTRL_SYS_DIV;
  REG(SYS_CTRL_CLOCK_CTRL) = val;

  while((REG(SYS_CTRL_CLOCK_STA) 
        & (SYS_CTRL_CLOCK_STA_OSC32K | SYS_CTRL_CLOCK_STA_OSC)) 
        != SYS_CTRL_OSCS);

#if SYS_CTRL_OSC32K_USE_XTAL
  /* Wait for the 32-kHz crystal oscillator to stabilize */
  while(REG(SYS_CTRL_CLOCK_STA) & SYS_CTRL_CLOCK_STA_SYNC_32K);
  while(!(REG(SYS_CTRL_CLOCK_STA) & SYS_CTRL_CLOCK_STA_SYNC_32K));
#endif
}

Where:

#define SYS_CTRL_CONF_OSC32K_USE_XTAL    1
#define SYS_CTRL_CONF_SYS_DIV            SYS_CTRL_CLOCK_CTRL_SYS_DIV_32MHZ

I know that this could be long, but I would be very pleased if someone could help me! I hope I've given enough information.
Thank you!