diff --git a/examples/platforms/cc2538/cc2538-reg.h b/examples/platforms/cc2538/cc2538-reg.h index 5c756bf1e..132e859f8 100644 --- a/examples/platforms/cc2538/cc2538-reg.h +++ b/examples/platforms/cc2538/cc2538-reg.h @@ -69,6 +69,7 @@ #define RFCORE_XREG_RSSISTAT 0x40088664 // RSSI valid status register #define RFCORE_XREG_AGCCTRL1 0x400886C8 // AGC reference level #define RFCORE_XREG_TXFILTCFG 0x400887E8 // TX filter configuration +#define RFCORE_XREG_RFRND 0x4008869C // Random data #define RFCORE_SFR_RFDATA 0x40088828 // The TX FIFO and RX FIFO #define RFCORE_SFR_RFERRF 0x4008882C // RF error interrupt flags #define RFCORE_SFR_RFIRQF0 0x40088834 // RF interrupt flags @@ -78,9 +79,12 @@ #define RFCORE_XREG_FRMCTRL0_AUTOACK 0x00000020 #define RFCORE_XREG_FRMCTRL0_AUTOCRC 0x00000040 +#define RFCORE_XREG_FRMCTRL0_INFINITY_RX 0x00000008 #define RFCORE_XREG_FRMCTRL1_PENDING_OR 0x00000004 +#define RFCORE_XREG_RFRND_IRND 0x00000001 + #define RFCORE_XREG_FSMSTAT1_TX_ACTIVE 0x00000002 #define RFCORE_XREG_FSMSTAT1_CCA 0x00000010 // Clear channel assessment #define RFCORE_XREG_FSMSTAT1_SFD 0x00000020 @@ -91,6 +95,12 @@ #define RFCORE_SFR_RFERRF_RXOVERF 0x00000004 // RX FIFO overflowed. +#define RFCORE_SFR_RFST_INSTR_RXON 0xE3 // Instruction set RX on +#define RFCORE_SFR_RFST_INSTR_TXON 0xE9 // Instruction set TX on +#define RFCORE_SFR_RFST_INSTR_RFOFF 0xEF // Instruction set RF off +#define RFCORE_SFR_RFST_INSTR_FLUSHRX 0xED // Instruction set flush rx buffer +#define RFCORE_SFR_RFST_INSTR_FLUSHTX 0xEE // Instruction set flush tx buffer + #define ANA_REGS_BASE 0x400D6000 // ANA_REGS #define ANA_REGS_O_IVCTRL 0x00000004 // Analog control register @@ -167,4 +177,11 @@ #define UART_IM_RXIM 0x00000010 // UART receive interrupt mask #define UART_IM_RTIM 0x00000040 // UART receive time-out interrupt +#define SOC_ADC_ADCCON1 0x400D7000 // ADC Control +#define SOC_ADC_RNDL 0x400D7014 // RNG low data +#define SOC_ADC_RNDH 0x400D7018 // RNG high data + +#define SOC_ADC_ADCCON1_RCTRL0 0x00000004 // ADCCON1 RCTRL bit 0 +#define SOC_ADC_ADCCON1_RCTRL1 0x00000008 // ADCCON1 RCTRL bit 1 + #endif diff --git a/examples/platforms/cc2538/platform.c b/examples/platforms/cc2538/platform.c index 1a60aed30..4188b190e 100644 --- a/examples/platforms/cc2538/platform.c +++ b/examples/platforms/cc2538/platform.c @@ -38,8 +38,8 @@ void PlatformInit(int argc, char *argv[]) { cc2538AlarmInit(); - cc2538RadioInit(); cc2538RandomInit(); + cc2538RadioInit(); otPlatUartEnable(); (void)argc; diff --git a/examples/platforms/cc2538/radio.c b/examples/platforms/cc2538/radio.c index f46e9756f..7e14183e3 100644 --- a/examples/platforms/cc2538/radio.c +++ b/examples/platforms/cc2538/radio.c @@ -52,15 +52,6 @@ enum IEEE802154_DSN_OFFSET = 2, }; -enum -{ - CC2538_RF_CSP_OP_ISRXON = 0xE3, - CC2538_RF_CSP_OP_ISTXON = 0xE9, - CC2538_RF_CSP_OP_ISRFOFF = 0xEF, - CC2538_RF_CSP_OP_ISFLUSHRX = 0xED, - CC2538_RF_CSP_OP_ISFLUSHTX = 0xEE, -}; - enum { CC2538_RSSI_OFFSET = 73, @@ -84,11 +75,11 @@ void enableReceiver(void) if (!sIsReceiverEnabled) { // flush rxfifo - HWREG(RFCORE_SFR_RFST) = CC2538_RF_CSP_OP_ISFLUSHRX; - HWREG(RFCORE_SFR_RFST) = CC2538_RF_CSP_OP_ISFLUSHRX; + HWREG(RFCORE_SFR_RFST) = RFCORE_SFR_RFST_INSTR_FLUSHRX; + HWREG(RFCORE_SFR_RFST) = RFCORE_SFR_RFST_INSTR_FLUSHRX; // enable receiver - HWREG(RFCORE_SFR_RFST) = CC2538_RF_CSP_OP_ISRXON; + HWREG(RFCORE_SFR_RFST) = RFCORE_SFR_RFST_INSTR_RXON; sIsReceiverEnabled = true; } } @@ -100,13 +91,13 @@ void disableReceiver(void) while (HWREG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_TX_ACTIVE); // flush rxfifo - HWREG(RFCORE_SFR_RFST) = CC2538_RF_CSP_OP_ISFLUSHRX; - HWREG(RFCORE_SFR_RFST) = CC2538_RF_CSP_OP_ISFLUSHRX; + HWREG(RFCORE_SFR_RFST) = RFCORE_SFR_RFST_INSTR_FLUSHRX; + HWREG(RFCORE_SFR_RFST) = RFCORE_SFR_RFST_INSTR_FLUSHRX; if (HWREG(RFCORE_XREG_RXENABLE) != 0) { // disable receiver - HWREG(RFCORE_SFR_RFST) = CC2538_RF_CSP_OP_ISRFOFF; + HWREG(RFCORE_SFR_RFST) = RFCORE_SFR_RFST_INSTR_RFOFF; } sIsReceiverEnabled = false; @@ -218,6 +209,11 @@ ThreadError otPlatRadioDisable(void) return error; } +bool otPlatRadioIsEnabled(void) +{ + return (sState != kStateDisabled) ? true : false; +} + ThreadError otPlatRadioSleep(void) { ThreadError error = kThreadError_Busy; @@ -263,8 +259,8 @@ ThreadError otPlatRadioTransmit(void) while (HWREG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_TX_ACTIVE); // flush txfifo - HWREG(RFCORE_SFR_RFST) = CC2538_RF_CSP_OP_ISFLUSHTX; - HWREG(RFCORE_SFR_RFST) = CC2538_RF_CSP_OP_ISFLUSHTX; + HWREG(RFCORE_SFR_RFST) = RFCORE_SFR_RFST_INSTR_FLUSHTX; + HWREG(RFCORE_SFR_RFST) = RFCORE_SFR_RFST_INSTR_FLUSHTX; // frame length HWREG(RFCORE_SFR_RFDATA) = sTransmitFrame.mLength; @@ -286,7 +282,7 @@ ThreadError otPlatRadioTransmit(void) sTransmitError = kThreadError_ChannelAccessFailure); // begin transmit - HWREG(RFCORE_SFR_RFST) = CC2538_RF_CSP_OP_ISTXON; + HWREG(RFCORE_SFR_RFST) = RFCORE_SFR_RFST_INSTR_TXON; while (HWREG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_TX_ACTIVE); } @@ -359,8 +355,8 @@ void readFrame(void) if ((HWREG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFOP) != 0 && (HWREG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFO) == 0) { - HWREG(RFCORE_SFR_RFST) = CC2538_RF_CSP_OP_ISFLUSHRX; - HWREG(RFCORE_SFR_RFST) = CC2538_RF_CSP_OP_ISFLUSHRX; + HWREG(RFCORE_SFR_RFST) = RFCORE_SFR_RFST_INSTR_FLUSHRX; + HWREG(RFCORE_SFR_RFST) = RFCORE_SFR_RFST_INSTR_FLUSHRX; } exit: diff --git a/examples/platforms/cc2538/random.c b/examples/platforms/cc2538/random.c index 30dd8223a..c4392ffda 100644 --- a/examples/platforms/cc2538/random.c +++ b/examples/platforms/cc2538/random.c @@ -28,60 +28,96 @@ /** * @file - * This file implements a pseudo-random number generator. + * This file implements a random number generator. * - * @warning - * This implementation is not a true random number generator and does @em satisfy the Thread requirements. */ #include #include +#include #include #include "platform-cc2538.h" -static uint32_t s_state = 1; +static void generateRandom(uint16_t aInputLength, uint8_t *aOutput, uint16_t *aOutputLength) +{ + HWREG(SOC_ADC_ADCCON1) &= ~(SOC_ADC_ADCCON1_RCTRL1 | SOC_ADC_ADCCON1_RCTRL0); + HWREG(SYS_CTRL_RCGCRFC) = SYS_CTRL_RCGCRFC_RFC0; + + while (HWREG(SYS_CTRL_RCGCRFC) != SYS_CTRL_RCGCRFC_RFC0); + + HWREG(RFCORE_XREG_FRMCTRL0) = RFCORE_XREG_FRMCTRL0_INFINITY_RX; + HWREG(RFCORE_SFR_RFST) = RFCORE_SFR_RFST_INSTR_RXON; + + while (!HWREG(RFCORE_XREG_RSSISTAT) & RFCORE_XREG_RSSISTAT_RSSI_VALID); + + for (uint16_t index = 0; index < aInputLength; index++) + { + aOutput[index] = 0; + + for (uint8_t offset = 0; offset < 8 * sizeof(uint8_t); offset++) + { + aOutput[index] <<= 1; + aOutput[index] |= (HWREG(RFCORE_XREG_RFRND) & RFCORE_XREG_RFRND_IRND); + } + } + + HWREG(RFCORE_SFR_RFST) = RFCORE_SFR_RFST_INSTR_RFOFF; + + if (aOutputLength) + { + *aOutputLength = aInputLength; + } +} void cc2538RandomInit(void) { - // use Extended Identifier portion of IEEE EUI-64 as the seed - s_state = HWREG(IEEE_EUI64 + 4); + uint16_t seed = 0; + + while (seed == 0x0000 || seed == 0x8003) + { + generateRandom(sizeof(seed), (uint8_t *)&seed, 0); + } + + HWREG(SOC_ADC_RNDL) = (seed >> 8) & 0xff; + HWREG(SOC_ADC_RNDL) = seed & 0xff; } uint32_t otPlatRandomGet(void) { - uint32_t mlcg, p, q; - uint64_t tmpstate; + uint32_t random = 0; - tmpstate = (uint64_t)33614 * (uint64_t)s_state; - q = tmpstate & 0xffffffff; - q = q >> 1; - p = tmpstate >> 32; - mlcg = p + q; + HWREG(SOC_ADC_ADCCON1) |= SOC_ADC_ADCCON1_RCTRL0; + random = HWREG(SOC_ADC_RNDL) | (HWREG(SOC_ADC_RNDH) << 8); - if (mlcg & 0x80000000) - { - mlcg &= 0x7fffffff; - mlcg++; - } + HWREG(SOC_ADC_ADCCON1) |= SOC_ADC_ADCCON1_RCTRL0; + random |= ((HWREG(SOC_ADC_RNDL) | (HWREG(SOC_ADC_RNDH) << 8)) << 16); - s_state = mlcg; - - return mlcg; + return random; } -ThreadError otPlatSecureRandomGet(uint16_t aInputLength, uint8_t *aOutput, uint16_t *aOutputLength) +ThreadError otPlatRandomSecureGet(uint16_t aInputLength, uint8_t *aOutput, uint16_t *aOutputLength) { ThreadError error = kThreadError_None; + uint8_t channel = 0; VerifyOrExit(aOutput && aOutputLength, error = kThreadError_InvalidArgs); - for (uint16_t length = 0; length < aInputLength; length++) + if (otPlatRadioIsEnabled()) { - aOutput[length] = (uint8_t)otPlatRandomGet(); + channel = 11 + (HWREG(RFCORE_XREG_FREQCTRL) - 11) / 5; + otPlatRadioSleep(); + otPlatRadioDisable(); } - *aOutputLength = aInputLength; + generateRandom(aInputLength, aOutput, aOutputLength); + + if (channel) + { + cc2538RadioInit(); + otPlatRadioEnable(); + otPlatRadioReceive(channel); + } exit: return error; diff --git a/examples/platforms/posix/radio.c b/examples/platforms/posix/radio.c index 3c64ee090..144376a90 100644 --- a/examples/platforms/posix/radio.c +++ b/examples/platforms/posix/radio.c @@ -377,6 +377,11 @@ ThreadError otPlatRadioDisable(void) return error; } +bool otPlatRadioIsEnabled(void) +{ + return (sState != kStateDisabled) ? true : false; +} + ThreadError otPlatRadioSleep(void) { ThreadError error = kThreadError_Busy; diff --git a/include/platform/radio.h b/include/platform/radio.h index 83524d7da..bc1fe7ebb 100644 --- a/include/platform/radio.h +++ b/include/platform/radio.h @@ -201,6 +201,14 @@ ThreadError otPlatRadioEnable(void); */ ThreadError otPlatRadioDisable(void); +/** + * Check whether radio is enabled or not. + * + * @retval ::true radio is enabled. + * @retval ::false radio is disabled. + */ +bool otPlatRadioIsEnabled(void); + /** * Transition the radio from Receive to Sleep. * Turn off the radio. diff --git a/include/platform/random.h b/include/platform/random.h index a85e78e93..0b5e67c34 100644 --- a/include/platform/random.h +++ b/include/platform/random.h @@ -55,7 +55,15 @@ extern "C" { */ /** - * Get random stream. + * Get a 32-bit random value. + * + * @returns A 32-bit random value. + * + */ +uint32_t otPlatRandomGet(void); + +/** + * Get true random stream. * * @param[in] aInputLength The expected size of random values. * @param[out] aOutput A pointer to the buffer for the generated random stream. The pointer should never be NULL. @@ -67,15 +75,7 @@ extern "C" { * @retval kThreadError_Fail Generate random fail. * @retval kThreadError_InvalidArgs Invalid args. */ -ThreadError otPlatSecureRandomGet(uint16_t aInputLength, uint8_t *aOutput, uint16_t *aOutputLength); - -/** - * Get a 32-bit true random value. - * - * @returns A 32-bit true random value. - * - */ -uint32_t otPlatRandomGet(void); +ThreadError otPlatRandomSecureGet(uint16_t aInputLength, uint8_t *aOutput, uint16_t *aOutputLength); /** * @}