diff options
author | Gregory Nutt <gnutt@nuttx.org> | 2013-10-20 12:08:39 -0600 |
---|---|---|
committer | Gregory Nutt <gnutt@nuttx.org> | 2013-10-20 12:08:39 -0600 |
commit | 7aa8e49278d649e46a79be8c8d2e609876a39b82 (patch) | |
tree | 1a5360552fb4d13015b29359292c99230e802578 | |
parent | 6de05c200c43f0b41e454d14a0e856797718e769 (diff) | |
download | px4-nuttx-7aa8e49278d649e46a79be8c8d2e609876a39b82.tar.gz px4-nuttx-7aa8e49278d649e46a79be8c8d2e609876a39b82.tar.bz2 px4-nuttx-7aa8e49278d649e46a79be8c8d2e609876a39b82.zip |
SAMA5 TRNG: /dev/random appears to be functional
-rw-r--r-- | nuttx/arch/arm/src/sama5/chip/sam_trng.h | 3 | ||||
-rw-r--r-- | nuttx/arch/arm/src/sama5/sam_trng.c | 144 |
2 files changed, 92 insertions, 55 deletions
diff --git a/nuttx/arch/arm/src/sama5/chip/sam_trng.h b/nuttx/arch/arm/src/sama5/chip/sam_trng.h index 0dfeffe1d..15ac49cb1 100644 --- a/nuttx/arch/arm/src/sama5/chip/sam_trng.h +++ b/nuttx/arch/arm/src/sama5/chip/sam_trng.h @@ -68,7 +68,8 @@ /* Control Register */ -#define TRNG_CR_ENABLE (1 << 0) /* Bit 0: nables the TRNG */ +#define TRNG_CR_ENABLE (1 << 0) /* Bit 0: 1=Enables the TRNG */ +# define TRNG_CR_DISABLE (0) /* Bit 0: 0=Disables the TRNG */ #define TRNG_CR_KEY_SHIFT (8) /* Bits 8-31: Security key */ #define TRNG_CR_KEY_MASK (0xffffff << TRNG_CR_KEY_SHIFT) # define TRNG_CR_KEY (0x524e47 << TRNG_CR_KEY_SHIFT) /* RNG in ASCII */ diff --git a/nuttx/arch/arm/src/sama5/sam_trng.c b/nuttx/arch/arm/src/sama5/sam_trng.c index f865d081d..c93393bbe 100644 --- a/nuttx/arch/arm/src/sama5/sam_trng.c +++ b/nuttx/arch/arm/src/sama5/sam_trng.c @@ -125,84 +125,102 @@ static int sam_interrupt(int irq, void *context) { uint32_t odata; - /* Verify that sample data is available */ + /* Loop where there are samples available to be read and/or until the user + * buffer is filled. Each sample requires only 84 clocks it is likely + * that we will loop here. + */ - if ((getreg32(SAM_TRNG_ISR) & CONFIG_SAMA5_TRNG) == 0) + for (;;) { - /* No? Then why are we here? */ + /* Read the random sample (before checking DATRDY -- but probably not + * necessary) + */ - return OK; - } + odata = getreg32(SAM_TRNG_ODATA); - /* Read the random sample */ + /* Verify that sample data is available (DATARDY is cleared when the + * interrupt status regiser is read) + */ - odata = getreg32(SAM_TRNG_ODATA); + if ((getreg32(SAM_TRNG_ISR) & TRNG_INT_DATRDY) == 0) + { + /* No? Then return and continue processing on the next interrupt. */ - /* As required by the FIPS PUB (Federal Information Processing Standard - * Publication) 140-2, the first random number generated after setting the - * RNGEN bit should not be used, but saved for comparison with the next - * generated random number. Each subsequent generated random number has to be - * compared with the previously generated number. The test fails if any two - * compared numbers are equal (continuous random number generator test). - */ + return OK; + } - if (g_trngdev.nsamples == 0) - { - /* This is the first sample we have taken. Save it for subsequent - * comparison. + /* As required by the FIPS PUB (Federal Information Processing Standard + * Publication) 140-2, the first random number generated after setting + * the RNGEN bit should not be used, but saved for comparison with the + * next generated random number. Each subsequent generated random number + * has to be compared with the previously generated number. The test + * fails if any two compared numbers are equal (continuous random number + * generator test). */ - g_trngdev.samples[0] = odata; - g_trngdev.nsamples = 1; - return OK; - } + if (g_trngdev.nsamples == 0) + { + /* This is the first sample we have taken. Save it for subsequent + * comparison. + */ - /* This is not the first sample. Check if the new sample differs from the - * preceding sample. - */ + g_trngdev.samples[0] = odata; + g_trngdev.nsamples = 1; + continue; + } + + /* This is not the first sample. Check if the new sample differs from + * the preceding sample. + */ - else if (odata == g_trngdev.samples[g_trngdev.nsamples - 1]) - { - /* Two ssamples with the same value. Discard this one and try again. */ + else if (odata == g_trngdev.samples[g_trngdev.nsamples - 1]) + { + /* Two samples with the same value. Discard this one and try again. */ - return OK; - } + continue; + } - /* The numbers differ. Have we discarded the first sample yet? */ + /* This sample differs from the previous value. Have we discarded the + * first sample yet? + */ - if (g_trngdev.first) - { - /* No, discard it now by replacing it with the new sample */ + if (g_trngdev.first) + { + /* No, discard it now by replacing it with the new sample */ - g_trngdev.samples[0] = odata; - g_trngdev.nsamples = 1; - g_trngdev.first = false; - } + g_trngdev.samples[0] = odata; + g_trngdev.nsamples = 1; + g_trngdev.first = false; + } - /* Yes.. the first sample has been dicarded */ + /* Yes.. the first sample has been dicarded */ - else - { - /* Add the new random number to the buffer */ + else + { + /* Add the new random number to the buffer */ - g_trngdev.samples[g_trngdev.nsamples] = odata; - g_trngdev.nsamples++; - } + g_trngdev.samples[g_trngdev.nsamples] = odata; + g_trngdev.nsamples++; + } - /* Have all of the requested samples been saved? */ + /* Have all of the requested samples been saved? */ - if (g_trngdev.nsamples == g_trngdev.maxsamples) - { - /* Yes.. disable any further interrupts */ + if (g_trngdev.nsamples == g_trngdev.maxsamples) + { + /* Yes.. disable any further interrupts */ - putreg32(TRNG_INT_DATRDY, SAM_TRNG_IER); + putreg32(TRNG_INT_DATRDY, SAM_TRNG_IDR); - /* And wakeup the waiting read thread. */ + /* Disable the TRNG */ - sem_post(&g_trngdev.waitsem); - } + putreg32(TRNG_CR_DISABLE | TRNG_CR_KEY, SAM_TRNG_CR); - return OK; + /* And wakeup the waiting read thread. */ + + sem_post(&g_trngdev.waitsem); + return OK; + } + } } /**************************************************************************** @@ -245,6 +263,16 @@ static ssize_t sam_read(struct file *filep, char *buffer, size_t buflen) g_trngdev.nsamples = 0; g_trngdev.first = true; + /* Enable the TRNG */ + + putreg32(TRNG_CR_ENABLE | TRNG_CR_KEY, SAM_TRNG_CR); + + /* Clear any pending TRNG interrupts by reading the interrupt status + * register + */ + + (void)getreg32(SAM_TRNG_ISR); + /* Enable TRNG interrupts */ putreg32(TRNG_INT_DATRDY, SAM_TRNG_IER); @@ -284,6 +312,10 @@ errout: putreg32(TRNG_INT_DATRDY, SAM_TRNG_IDR); + /* Disable the TRNG */ + + putreg32(TRNG_CR_DISABLE | TRNG_CR_KEY, SAM_TRNG_CR); + /* Release our lock on the TRNG hardware */ sem_post(&g_trngdev.exclsem); @@ -338,6 +370,10 @@ void up_rnginitialize(void) putreg32(TRNG_INT_DATRDY, SAM_TRNG_IDR); + /* Disable the TRNG */ + + putreg32(TRNG_CR_DISABLE | TRNG_CR_KEY, SAM_TRNG_CR); + /* Register the character driver */ ret = register_driver("/dev/random", &g_trngops, 0644, NULL); |