/************************************************************************************************** * @fn macRadioUpdateChannel * * @brief Update the radio channel if a new channel has been requested. * * @param none * * @return none ************************************************************************************************** */ MAC_INTERNAL_API void macRadioUpdateChannel(void) { halIntState_t s; MAC_ASSERT(!macTxActive); /* cannot change channel during a transmit */ /* if the channel has changed, set the radio to the new channel */ HAL_ENTER_CRITICAL_SECTION(s); if (reqChannel != macPhyChannel) { macPhyChannel = reqChannel; HAL_EXIT_CRITICAL_SECTION(s); /* changing the channel stops any receive in progress */ macRxOff(); MAC_RADIO_SET_CHANNEL(macPhyChannel); /* If the channel is updated in the middle of receiving a frame, we must * clean up the Rx logic. */ macRxHaltCleanup(); macRxOnRequest(); } else { HAL_EXIT_CRITICAL_SECTION(s); } }
/************************************************************************************************** * @fn macRxOffRequest * * @brief Turn off receiver if permitted. * * @param none * * @return none ************************************************************************************************** */ void macRxOffRequest(void) { halIntState_t s; HAL_ENTER_CRITICAL_SECTION(s); if (!macRxEnableFlags) { if (!MAC_RX_IS_PHYSICALLY_ACTIVE() && !MAC_TX_IS_PHYSICALLY_ACTIVE()) { macRxOff(); } } HAL_EXIT_CRITICAL_SECTION(s); }
/************************************************************************************************** * @fn macRxOffRequest * * @brief Turn off receiver if permitted. * * @param none * * @return none ************************************************************************************************** */ MAC_INTERNAL_API void macRxOffRequest(void) { halIntState_t s; DBG_PRINT0(DBGSYS, "macRxOffRequest()"); HAL_ENTER_CRITICAL_SECTION(s); if (!macRxEnableFlags) { if (!MAC_RX_IS_PHYSICALLY_ACTIVE() && !MAC_TX_IS_PHYSICALLY_ACTIVE()) { macRxOff(); } } HAL_EXIT_CRITICAL_SECTION(s); }
/************************************************************************************************** * @fn macSleep * * @brief Puts radio into the selected sleep mode. * * @param sleepState - selected sleep level, see #defines in .h file * * @return TRUE if radio was successfully put into selected sleep mode. * FALSE if it was not safe for radio to go to sleep. ************************************************************************************************** */ uint8 macSleep(uint8 sleepState) { halIntState_t s; /* disable interrupts until macSleepState can be set */ HAL_ENTER_CRITICAL_SECTION(s); /* assert checks */ MAC_ASSERT(macSleepState == MAC_SLEEP_STATE_AWAKE); /* radio must be awake to put it to sleep */ MAC_ASSERT(macRxFilter == RX_FILTER_OFF); /* do not sleep when scanning or in promiscuous mode */ /* if either RX or TX is active or any RX enable flags are set, it's not OK to sleep */ if (macRxActive || macRxOutgoingAckFlag || macTxActive || macRxEnableFlags) { HAL_EXIT_CRITICAL_SECTION(s); return(FALSE); } /* turn off the receiver */ macRxOff(); /* update sleep state variable */ macSleepState = sleepState; /* macSleepState is now set, re-enable interrupts */ HAL_EXIT_CRITICAL_SECTION(s); /* put MAC timer to sleep */ MAC_RADIO_TIMER_SLEEP(); /* put radio in selected sleep mode */ if (sleepState == MAC_SLEEP_STATE_OSC_OFF) { MAC_RADIO_TURN_OFF_OSC(); } else { MAC_ASSERT(sleepState == MAC_SLEEP_STATE_RADIO_OFF); /* unknown sleep state */ MAC_RADIO_TURN_OFF_POWER(); } /* radio successfully entered sleep mode */ return(TRUE); }
/************************************************************************************************** * @fn macRadioUpdateChannel * * @brief Update the radio channel if a new channel has been requested. * * @param none * * @return none ************************************************************************************************** */ void macRadioUpdateChannel(void) { halIntState_t s; MAC_ASSERT(!macTxActive); /* cannot change channel during a transmit */ /* if the channel has changed, set the radio to the new channel */ HAL_ENTER_CRITICAL_SECTION(s); if (reqChannel != macPhyChannel) { macPhyChannel = reqChannel; HAL_EXIT_CRITICAL_SECTION(s); /* changing the channel stops any receive in progress */ macRxOff(); MAC_RADIO_SET_CHANNEL(macPhyChannel); macRxOnRequest(); } else { HAL_EXIT_CRITICAL_SECTION(s); } }
/************************************************************************************************** * @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) { 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; }