Implement CC2538 random driver (#483)

* Implement CC2538 random driver
This commit is contained in:
Lu Wang
2016-09-06 21:57:08 -07:00
committed by Jonathan Hui
parent 6e5a22080e
commit c05c632d2f
7 changed files with 118 additions and 56 deletions
+17
View File
@@ -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
+1 -1
View File
@@ -38,8 +38,8 @@
void PlatformInit(int argc, char *argv[])
{
cc2538AlarmInit();
cc2538RadioInit();
cc2538RandomInit();
cc2538RadioInit();
otPlatUartEnable();
(void)argc;
+16 -20
View File
@@ -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:
+61 -25
View File
@@ -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;
+5
View File
@@ -377,6 +377,11 @@ ThreadError otPlatRadioDisable(void)
return error;
}
bool otPlatRadioIsEnabled(void)
{
return (sState != kStateDisabled) ? true : false;
}
ThreadError otPlatRadioSleep(void)
{
ThreadError error = kThreadError_Busy;
+8
View File
@@ -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.
+10 -10
View File
@@ -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);
/**
* @}