Implement CC2538 random driver (#483)
* Implement CC2538 random driver
diff --git a/examples/platforms/cc2538/random.c b/examples/platforms/cc2538/random.c
index 30dd822..c4392ff 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 <openthread-types.h>
#include <common/code_utils.hpp>
+#include <platform/radio.h>
#include <platform/random.h>
#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;