/************************************************************************************************** * @fn macBackoffTimerRealign * * @brief * * Realignment is accomplished by adjusting the internal time base to align with the expected * reception time of an incoming frame. The difference between the expected reception time and * the actual reception time is computed and this difference is used to adjust the hardware * timer count and backoff count. * * The realignment is based on the SFD signal for the incoming frame. The timer is aligned * by adjusting it with the difference between the expected SFD time and the actual SFD time. * * @param none * * @return none ************************************************************************************************** */ int32 macBackoffTimerRealign(macRx_t *pMsg) { uint16 timerDelayTicks; int32 backoffDelta; int32 backoffCount; MAC_ASSERT(!MAC_TX_IS_PHYSICALLY_ACTIVE()); /* realignment during actual transmit corrupts timing */ /*------------------------------------------------------------------------------- * Calculate the delta backoff difference between expected backoff count, * which is zero, and the backoff count of the received frame. */ /* since expected receive time is zero, the delta is simply the receive time */ backoffDelta = pMsg->mac.timestamp; /* if the frame was received more than halfway to the rollover count, use a negative delta value */ if (((uint32) backoffDelta) > (backoffTimerRollover / 2)) { backoffDelta = backoffDelta - backoffTimerRollover; /* result will be negative */ } /*------------------------------------------------------------------------------- * Calculate the number of timer ticks to delay that will align the internal * time base with the received frame. */ /* retrieve the timer count when frame was received */ timerDelayTicks = pMsg->mac.timestamp2; /* * Subtract the expected SFD time from the actual SFD time to find the needed * timer adjustment. If subtracting the offset would result in a negative value, * the tick delay must wrap around. */ if (timerDelayTicks >= TIMER_TICKS_EXPECTED_AT_SFD) { /* since delay count is greater than or equal to offset, subtract it directly */ timerDelayTicks = timerDelayTicks - TIMER_TICKS_EXPECTED_AT_SFD; } else { /* * The expected time is greater that actualy time so it cannot be subtracted directly. * The tick count per backoff is added to wrap around within the backoff. * Since a wrap around did happen, the backoff delta is adjusted by one. */ timerDelayTicks = timerDelayTicks - TIMER_TICKS_EXPECTED_AT_SFD + MAC_RADIO_TIMER_TICKS_PER_BACKOFF(); backoffDelta--; } /*------------------------------------------------------------------------------- * Calculate the new backoff count. */ backoffCount = MAC_RADIO_BACKOFF_COUNT() - backoffDelta; if (backoffCount >= ((int32) backoffTimerRollover)) { backoffCount -= backoffTimerRollover; } else if (backoffCount < 0) { backoffCount += backoffTimerRollover; } MAC_RADIO_TIMER_FORCE_DELAY(timerDelayTicks); MAC_RADIO_BACKOFF_SET_COUNT(backoffCount); return(backoffDelta); }
/************************************************************************************************** * @fn macMcuInit * * @brief Initialize the MCU. * * @param none * * @return none ************************************************************************************************** */ MAC_INTERNAL_API void macMcuInit(void) { halIntState_t s; /* This CORR_THR value should be changed to 0x14 before attempting RX. Testing has shown that * too many false frames are received if the reset value is used. Make it more likely to detect * sync by removing the requirement that both symbols in the SFD must have a correlation value * above the correlation threshold, and make sync word detection less likely by raising the * correlation threshold. */ MDMCTRL1 = CORR_THR; #ifdef FEATURE_CC253X_LOW_POWER_RX /* Reduce RX power consumption current to 20mA at the cost of some sensitivity * Note: This feature can be applied to CC2530 and CC2533 only. */ RXCTRL = 0x00; FSCTRL = 0x50; #else /* tuning adjustments for optimal radio performance; details available in datasheet */ RXCTRL = 0x3F; /* Adjust current in synthesizer; details available in datasheet. */ FSCTRL = 0x55; #endif /* #ifdef FEATURE_CC253X_LOW_POWER_RX */ #if !(defined HAL_PA_LNA || defined HAL_PA_LNA_CC2590) /* Raises the CCA threshold from about -108 dBm to about -80 dBm input level. */ CCACTRL0 = CCA_THR; #endif /* Makes sync word detection less likely by requiring two zero symbols before the sync word. * details available in datasheet. */ MDMCTRL0 = 0x85; #if defined (HAL_MCU_CC2533) if (*(uint8 *)(P_INFOPAGE+0x03) == 0x95) // Device is a CC2533 { /* In case the device is a 2533, just update the IVCTRL regoster which is 2533 specific */ #define IVCTRL XREG( 0x6265 ) IVCTRL = 0xF; } #endif /* Adjust current in VCO; details available in datasheet. */ FSCAL1 = 0x01; /* Adjust target value for AGC control loop; details available in datasheet. */ AGCCTRL1 = 0x15; /* Disable source address matching an autopend for now */ SRCMATCH = 0; /* Tune ADC performance, details available in datasheet. */ ADCTEST0 = 0x10; ADCTEST1 = 0x0E; ADCTEST2 = 0x03; /* Sets TX anti-aliasing filter to appropriate bandwidth. * Reduces spurious emissions close to signal. */ TXFILTCFG = TXFILTCFG_RESET_VALUE; /*Controls bias currents */ IVCTRL = 0x0B; /* disable the CSPT register compare function */ CSPT = 0xFFUL; IntPrioritySet(INT_RFCORERTX, HAL_INT_PRIOR_MAC); IntPrioritySet(INT_RFCOREERR, HAL_INT_PRIOR_MAC); /* enable general RF interrupts */ HAL_ENABLE_RF_INTERRUPT(); /* enable general REERR interrupts */ HAL_ENABLE_RF_ERROR_INTERRUPT(); /* set T2 interrupts one notch above lowest priority (four levels available) * This effectively turned off nested interrupt between T2 and RF. */ IntPrioritySet(INT_MACTIMR, HAL_INT_PRIOR_MAC); /* read chip version */ macChipVersion = CHIPID >> 16; /*------------------------------------------------------------------------------- * Initialize MAC timer. */ /* set timer rollover */ HAL_ENTER_CRITICAL_SECTION(s); MAC_MCU_T2_ACCESS_PERIOD_VALUE(); T2M0 = MAC_RADIO_TIMER_TICKS_PER_BACKOFF() & 0xFFUL; T2M1 = MAC_RADIO_TIMER_TICKS_PER_BACKOFF() >> 8UL; HAL_EXIT_CRITICAL_SECTION(s); /* start timer */ MAC_RADIO_TIMER_WAKE_UP(); /* Enable latch mode and T2 SYNC start. OSAL timer is based on MAC timer. * The SYNC start msut be on when POWER_SAVING is on for this design to work. */ T2CTRL |= (LATCH_MODE | TIMER2_SYNC); /* enable timer interrupts */ IntEnable(INT_MACTIMR); /*---------------------------------------------------------------------------------------------- * Initialize random seed value. */ /* * Set radio for infinite reception. Once radio reaches this state, * it will stay in receive mode regardless RF activity. */ FRMCTRL0 = FRMCTRL0_RESET_VALUE | RX_MODE_INFINITE_RECEPTION; /* turn on the receiver */ macRxOn(); /* * Wait for radio to reach infinite reception state by checking RSSI valid flag. * Once it does, the least significant bit of ADTSTH should be pretty random. */ while (!(RSSISTAT & 0x01)); /* put 16 random bits into the seed value */ { uint16 rndSeed; uint8 i; rndSeed = 0; for(i=0; i<16; i++) { /* use most random bit of analog to digital receive conversion to populate the random seed */ rndSeed = (rndSeed << 1) | (RFRND & 0x01); } /* * The seed value must not be zero or 0x0380 (0x8003 in the polynomial). If it is, the psuedo * random sequence won’t be random. There is an extremely small chance this seed could randomly * be zero or 0x0380. The following check makes sure this does not happen. */ if (rndSeed == 0x0000 || rndSeed == 0x0380) { rndSeed = 0xBABE; /* completely arbitrary "random" value */ } /* * Two writes to RNDL will set the random seed. A write to RNDL copies current contents * of RNDL to RNDH before writing new the value to RNDL. */ RNDL = rndSeed & 0xFF; RNDL = rndSeed >> 8; } /* Read 16*8 random bits and store them in flash for future use in random * key generation for CBKE key establishment */ if( pRandomSeedCB ) { uint8 randomSeed[MAC_RANDOM_SEED_LEN]; uint8 i,j; for(i = 0; i < MAC_RANDOM_SEED_LEN; i++) { uint8 rndByte = 0; for(j = 0; j < 8; j++) { /* use most random bit of analog to digital receive conversion to populate the random seed */ rndByte = (rndByte << 1) | (RFRND & 0x01); } randomSeed[i] = rndByte; } pRandomSeedCB( randomSeed ); } /* turn off the receiver */ macRxOff(); /* take receiver out of infinite reception mode; set back to normal operation */ FRMCTRL0 = FRMCTRL0_RESET_VALUE | RX_MODE_NORMAL_OPERATION; /* Turn on autoack */ MAC_RADIO_TURN_ON_AUTO_ACK(); /* Initialize SRCEXTPENDEN and SRCSHORTPENDEN to zeros */ MAC_RADIO_SRC_MATCH_INIT_EXTPENDEN(); MAC_RADIO_SRC_MATCH_INIT_SHORTPENDEN(); }
/************************************************************************************************** * @fn macMcuInit * * @brief Initialize the MCU. * * @param none * * @return none ************************************************************************************************** */ void macMcuInit(void) { uint16 i; /////////////////////////////////////////////////////////////////////////////////// // FIX_ON_REV_C : replace with line below after transition to Rev C #ifndef _NEXTREV MAC_ASSERT(CHVER >= 0x01); /* chip revision is obsolete */ #else //vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv // keep this code, delete the rest (may need to update compare value) MAC_ASSERT(CHVER >= 0x02); /* chip revision is obsolete */ //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #endif /////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////// // FIX_ON_REV_C : workaround for chip bug #51, remove when fixed #ifndef _NEXTREV FSCTRLH = 0x41; #endif /////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////// // FIX_ON_REV_C : workaround for chip bug #267, remove when fixed #ifndef _NEXTREV MDMCTRL0L |= AUTOACK; /* enable autoack */ #endif /////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////// // FIX_ON_REV_C : workaround for chip bug #267, make permanent with Rev C #ifndef _NEXTREV /* do nothing */ #else // this part can go away once new .h file is shipping #ifndef IRQSRC #define IRQSRC XREG( 0xDF64 ) #endif //vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv // keep this code, delete the rest /* enable TX_DONE interrupts for ACK transmits */ IRQSRC = TXACK; //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #endif /////////////////////////////////////////////////////////////////////////////////// /* disable the CSPT register compare function */ CSPT = 0xFF; /* enable general RF interrupts */ IEN2 |= RFIE; /* enable CSP INT interrupts */ RFIM |= IM_CSP_INT; /* intialize shadow register */ shadowPerof2 = 0; /* set RF interrupts to be second highest interrupt level (four levels available) */ IP0 |= IP_RFERR_RF_DMA_BV; IP1 &= ~IP_RFERR_RF_DMA_BV; /*------------------------------------------------------------------------------- * Initialize MAC timer. */ /* set timer rollover */ T2CAPLPL = MAC_RADIO_TIMER_TICKS_PER_BACKOFF() & 0xFF; T2CAPHPH = MAC_RADIO_TIMER_TICKS_PER_BACKOFF() >> 8; /* start timer */ T2CNF |= RUN; /* enable timer interrupts */ T2IE = 1; /* configure clock to use XOSC */ SLEEP &= ~OSC_PD; /* turn on 16MHz RC and 32MHz XOSC */ while (!(SLEEP & XOSC_STB)); /* wait for 32MHz XOSC stable */ asm("NOP"); /* chip bug workaround */ for (i=0; i<504; i++) asm("NOP"); /* Require 63us delay for Rev B */ CLKCON = (0x00 | OSC_32KHZ); /* 32MHz XOSC */ while (CLKCON != (0x00 | OSC_32KHZ)); SLEEP |= OSC_PD; /* turn off 16MHz RC */ }
/************************************************************************************************** * @fn macMcuInit * * @brief Initialize the MCU. * * @param none * * @return none ************************************************************************************************** */ void macMcuInit(void) { MAC_ASSERT(CHVER >= 0x03); /* chip versions before version D are obsolete */ /* tuning adjustments for optimal radio performance; details available in datasheet */ RXCTRL0H = 0x32; RXCTRL0L = 0xF5; /* enable TX_DONE interrupts for ACK transmits */ IRQSRC = TXACK; /* disable the CSPT register compare function */ CSPT = 0xFF; /* enable general RF interrupts */ IEN2 |= RFIE; /* intialize shadow register */ shadowPerof2 = 0; /* set RF interrupts one notch above lowest priority (four levels available) */ IP0 |= IP_RFERR_RF_DMA_BV; IP1 &= ~IP_RFERR_RF_DMA_BV; /*------------------------------------------------------------------------------- * Initialize MAC timer. */ /* set timer rollover */ T2CAPLPL = MAC_RADIO_TIMER_TICKS_PER_BACKOFF() & 0xFF; T2CAPHPH = MAC_RADIO_TIMER_TICKS_PER_BACKOFF() >> 8; /* start timer */ T2CNF |= RUN; /* enable timer interrupts */ T2IE = 1; /*---------------------------------------------------------------------------------------------- * Initialize random seed value. */ /* turn on radio power */ RFPWR &= ~RREG_RADIO_PD; while((RFPWR & ADI_RADIO_PD)); /* * Set radio for infinite reception. Once radio reaches this state, * it will stay in receive mode regardless RF activity. */ MDMCTRL1L = MDMCTRL1L_RESET_VALUE | RX_MODE_INFINITE_RECEPTION; /* turn on the receiver */ macRxOn(); /* * Wait for radio to reach infinite reception state. Once it does, * The least significant bit of ADTSTH should be pretty random. */ while (FSMSTATE != FSM_FFCTRL_STATE_RX_INF) /* put 16 random bits into the seed value */ { uint16 rndSeed; uint8 i; rndSeed = 0; for(i=0; i<16; i++) { /* use most random bit of analog to digital receive conversion to populate the random seed */ rndSeed = (rndSeed << 1) | (ADCTSTH & 0x01); } /* * The seed value must not be zero. If it is, the psuedo random sequence will be always be zero. * There is an extremely small chance this seed could randomly be zero (more likely some type of * hardware problem would cause this). The following check makes sure this does not happen. */ if (rndSeed == 0x0000) { rndSeed = 0xBEEF; /* completely arbitrary "random" value */ } /* * Two writes to RNDL will set the random seed. A write to RNDL copies current contents * of RNDL to RNDH before writing new the value to RNDL. */ RNDL = rndSeed & 0xFF; RNDL = rndSeed >> 8; } /* turn off the receiver */ macRxOff(); /* take receiver out of infinite reception mode; set back to normal operation */ MDMCTRL1L = MDMCTRL1L_RESET_VALUE | RX_MODE_NORMAL_OPERATION; /* turn radio back off */ RFPWR |= RREG_RADIO_PD; }