diff --git a/boards/arduino-due/include/periph_conf.h b/boards/arduino-due/include/periph_conf.h index 7bb697426c..07e122f50f 100644 --- a/boards/arduino-due/include/periph_conf.h +++ b/boards/arduino-due/include/periph_conf.h @@ -79,6 +79,12 @@ #define UART_1_PINS /** @} */ +/** + * @name Random Number Generator configuration + * @{ + */ +#define RANDOM_NUMOF (1U) +/** @} */ /** * @name GPIO configuration diff --git a/cpu/sam3x8e/periph/random.c b/cpu/sam3x8e/periph/random.c new file mode 100644 index 0000000000..917e141959 --- /dev/null +++ b/cpu/sam3x8e/periph/random.c @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2014 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License v2.1. See the file LICENSE in the top level directory for more + * details. + */ + +/** + * @ingroup driver_periph + * @{ + * + * @file + * @brief Low-level random number generator driver implementation + * + * @author Hauke Petersen + * + * @} + */ + +#include "cpu.h" +#include "periph_conf.h" +#include "periph/random.h" + +/* only compile this driver if enabled in the board's periph_conf.h */ +#if RANDOM_NUMOF + +/** + * @name KEY needs to be written to the config register when en|disabling + * random number generation + */ +#define KEY (0x524e4700) + +void random_init(void) +{ + random_poweron(); +} + +int random_read(char *buf, unsigned int num) +{ + uint32_t tmp; + int count = 0; + + while (count < num) { + /* wait until new value is generated -> takes up to 84 cycles */ + while (!(TRNG->TRNG_ISR & TRNG_ISR_DATRDY)); + /* read 4 byte of random data */ + tmp = TRNG->TRNG_ODATA; + /* extract copy bytes to result */ + for (int i = 0; i < 4 && count < num; i++) { + buf[count++] = (char)tmp; + tmp = tmp >> 8; + } + } + + return count; +} + +void random_poweron(void) +{ + /* enable clock signal for TRNG module */ + PMC->PMC_PCER1 |= PMC_PCER1_PID41; + /* enable the generation of random numbers */ + TRNG->TRNG_CR |= (KEY | TRNG_CR_ENABLE); +} + +void random_poweroff(void) +{ + /* disable the generation of random numbers */ + TRNG->TRNG_CR &= ~(KEY | TRNG_CR_ENABLE); + /* disable clock signal for TRNG module */ + PMC->PMC_PCER1 &= ~(PMC_PCER1_PID41); +} + +#endif /* RANDOM_NUMOF */ diff --git a/tests/periph_random/Makefile b/tests/periph_random/Makefile new file mode 100644 index 0000000000..5bd2c194f8 --- /dev/null +++ b/tests/periph_random/Makefile @@ -0,0 +1,10 @@ +export APPLICATION = periph_random +include ../Makefile.tests_common + +BOARD_BLACKLIST := chronos mbed_lpc1768 msb-430 msb-430h native qemu-i386 redbee-econotag telosb \ + wsn430-v1_3b wsn430-v1_4 z1 +# all listed boards: no periph_conf.h defined, + +USEMODULE += vtimer + +include $(RIOTBASE)/Makefile.include diff --git a/tests/periph_random/README.md b/tests/periph_random/README.md new file mode 100644 index 0000000000..26d7b93954 --- /dev/null +++ b/tests/periph_random/README.md @@ -0,0 +1,7 @@ +Expected result +=============== +This test outputs a sequence of random bytes, starting with one, then two and so on, until 20 random bytes are printed. Then the application sleeps for a second and starts over. + +Background +========== +This test was introduced to test the implementation of the low-level random number generator driver. For most platforms the implementation is based on hardware CPU peripherals. diff --git a/tests/periph_random/main.c b/tests/periph_random/main.c new file mode 100644 index 0000000000..90c1a2cb0b --- /dev/null +++ b/tests/periph_random/main.c @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2014 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License v2.1. See the file LICENSE in the top level directory for more + * details. + */ + +/** + * @ingroup tests + * @{ + * + * @file + * @brief Low-level random number generator driver test + * + * @author Hauke Petersen + * + * @} + */ + +#include +#include +#include +#include +#include + +/* only compile test if a random number generator is defined */ +#if RANDOM_NUMOF + +#define LIMIT (20U) + +int main(void) +{ + char buf[LIMIT]; + int count = 0; + + puts("\nRandom number generator low-level driver test\n"); + printf("This test will print from 1 to %i random bytes about every second\n\n", LIMIT); + + puts("Initializing Random Number Generator driver.\n"); + random_init(); + + while (1) { + /* zero out buffer */ + memset(buf, 0, sizeof(buf)); + + /* create random numbers */ + for (int i = 1; i <= LIMIT; i++) { + printf("generating %i random byte(s)\n", i); + count = random_read(buf, i); + + if (count != i) { + printf("Error generating random bytes, got %i instead of %i", count, i); + return 0; + } + + printf("Got:"); + for (int j = 0; j < i; j++) { + printf(" 0x%02x", buf[j]); + } + printf("\n"); + } + + vtimer_usleep(1000 * 1000); + } + + return 0; +} + +#else + +int main(void) +{ + puts("Random number generator low-level driver test"); + puts("There is no (pseudo) random generator implementation for your platform"); + return 0; +} + +#endif /* RANDOM_NUMOF */