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!