From edef041f9380de9fc5ace85dffd2bb21c6feaed1 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Tue, 26 Dec 2017 10:20:41 -0600 Subject: [PATCH] arch/arm/src/lpc54xx: Add support for a random number generator. --- arch/arm/src/lpc54xx/Kconfig | 7 +- arch/arm/src/lpc54xx/Make.defs | 4 + arch/arm/src/lpc54xx/chip/lpc546x_memorymap.h | 4 + arch/arm/src/lpc54xx/chip/lpc54_rom.h | 113 ++++++++++ arch/arm/src/lpc54xx/lpc54_rng.c | 193 ++++++++++++++++++ arch/arm/src/lpc54xx/lpc54_rtc.c | 2 - configs/lpcxpresso-lpc54628/README.txt | 5 + 7 files changed, 325 insertions(+), 3 deletions(-) create mode 100644 arch/arm/src/lpc54xx/chip/lpc54_rom.h create mode 100644 arch/arm/src/lpc54xx/lpc54_rng.c diff --git a/arch/arm/src/lpc54xx/Kconfig b/arch/arm/src/lpc54xx/Kconfig index 9e186a5637..6570d216ad 100644 --- a/arch/arm/src/lpc54xx/Kconfig +++ b/arch/arm/src/lpc54xx/Kconfig @@ -406,8 +406,13 @@ config LPC54_LCD default n depends on ARCH_LPC54_HAVE_LCD +config LPC54_RNG + bool "Random Number Generator (RNG)" + default n + select ARCH_HAVE_RNG + config LPC54_RTC - bool "RTC" + bool "Real Time Clock (RTC)" default n select RTC diff --git a/arch/arm/src/lpc54xx/Make.defs b/arch/arm/src/lpc54xx/Make.defs index 519d3fbf78..09be41eaa2 100644 --- a/arch/arm/src/lpc54xx/Make.defs +++ b/arch/arm/src/lpc54xx/Make.defs @@ -116,6 +116,10 @@ ifeq ($(CONFIG_LPC54_WWDT),y) CHIP_CSRCS += lpc54_wwdt.c endif +ifeq ($(CONFIG_LPC54_RNG),y) +CHIP_CSRCS += lpc54_rng.c +endif + ifeq ($(CONFIG_LPC54_HAVE_USART),y) CHIP_CSRCS += lpc54_serial.c endif diff --git a/arch/arm/src/lpc54xx/chip/lpc546x_memorymap.h b/arch/arm/src/lpc54xx/chip/lpc546x_memorymap.h index 956f00a08a..c6878580f8 100644 --- a/arch/arm/src/lpc54xx/chip/lpc546x_memorymap.h +++ b/arch/arm/src/lpc54xx/chip/lpc546x_memorymap.h @@ -70,6 +70,10 @@ #define LPC54_DRAMCS3_BASE 0xb8000000 /* Dynamic memory chip select 3 (<=256MB) */ #define LPC54_CORTEXM4_BASE 0xe0000000 /* Cortex-M4 Private Peripheral Bus */ +/* ROM Driver Table */ + +#define LPC54_ROM_DRIVERTAB 0x03000200 /* Beginning of the ROM driver table */ + /* AHB Peripherals */ #define LPC54_SPIFI_BASE 0x40080000 /* SPIFI registers */ diff --git a/arch/arm/src/lpc54xx/chip/lpc54_rom.h b/arch/arm/src/lpc54xx/chip/lpc54_rom.h new file mode 100644 index 0000000000..32f5a32c61 --- /dev/null +++ b/arch/arm/src/lpc54xx/chip/lpc54_rom.h @@ -0,0 +1,113 @@ +/******************************************************************************************** + * arch/arm/src/lpc54xx/lpc54_rom.h + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_LPC54XX_CHIP_LPC54_ROM_H +#define __ARCH_ARM_SRC_LPC54XX_CHIP_LPC54_ROM_H + +/******************************************************************************************** + * Included Files + ********************************************************************************************/ + +#include +#include "chip/lpc54_memorymap.h" + +/******************************************************************************************** + * Pre-processor Definitions + ********************************************************************************************/ + +/* Table offsets ****************************************************************************/ + +/* First level table offsets */ + +#define LPC54_USB_API_OFFSET 0x0000 +#define LPC54_OTP_API_OFFSET 0x0038 + +/* USB API table offsets (to be provided) */ + +/* OTP API driver table offsets */ + +#define LPC54_OTP_API_INIT_OFFSET 0x0000 +#define LPC54_OTP_API_ENABLEBANKWRITEMASK_OFFSET 0x0004 +#define LPC54_OTP_API_DISABLEBANKWRITEMASK_OFFSET 0x0008 +#define LPC54_OTP_API_ENABLEBANKWRITELOCK_OFFSET 0x000c +#define LPC54_OTP_API_ENABLEBANKREADLOCK_OFFSET 0x0010 +#define LPC54_OTP_API_PROGRAMREG_OFFSET 0x0014 +#define LPC54_OTP_API_RNGREAD_OFFSET 0x002c +#define LPC54_OTP_API_GETDRIVERVERSION_OFFSET 0x0030 + +/******************************************************************************************** + * Public Data + ********************************************************************************************/ + +/* Dereference the LPC54_ROM_DRIVERTAB address to get the address of the ROM driver table. + * Not often that I get to use a pointer-to-a-pointer-to-a-pointer. The result of de- + * referencing the LPC54_ROM_DRIVERTAB is a pointer to an array of type uinptr_t *. + */ + +#define lpc54_driver_vtable (*(uintptr_t ***)LPC54_ROM_DRIVERTAB) + +/* Index the ROM driver table to get the specific driver table. Perhaps in the future these + * uintptr_t * arrays would be replaced with proper vtable structures. + */ + +#define lpc54_usb_vtable lpc54_driver_vtable[LPC54_USB_API_OFFSET >> 2] +#define lpc54_otg_vtable lpc54_driver_vtable[LPC54_OTP_API_OFFSET >> 2] + +/* Then, finally, index the specific driver table to get the API entry point */ + +/******************************************************************************************** + * Public Types/Functions + ********************************************************************************************/ + +/******************************************************************************************** + * Name: lpc54_rng_read + * + * Description: + * Returns a 32 bit random number from hardware. The Random Number Generator is accessed + * through an API call located in the ROM. + * + * Input Parameters: + * None + * + * Returned Value: + * Unsigned random number + * + ********************************************************************************************/ + +typedef CODE unsigned int (*rng_read_t)(void); + +#define LPC54_RNG_READ ((rng_read_t)(lpc54_otg_vtable[LPC54_OTP_API_RNGREAD_OFFSET >> 2])) + +#endif /* __ARCH_ARM_SRC_LPC54XX_CHIP_LPC54_ROM_H */ diff --git a/arch/arm/src/lpc54xx/lpc54_rng.c b/arch/arm/src/lpc54xx/lpc54_rng.c new file mode 100644 index 0000000000..dfe9bace8e --- /dev/null +++ b/arch/arm/src/lpc54xx/lpc54_rng.c @@ -0,0 +1,193 @@ +/**************************************************************************** + * arch/arm/src/lpc54xx/lpc54_rng.c + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include + +#include "chip/lpc54_rom.h" + +#if defined(CONFIG_LPC54_RNG) +#if defined(CONFIG_DEV_RANDOM) || defined(CONFIG_DEV_URANDOM_ARCH) + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static ssize_t lpc54_read(struct file *filep, char *buffer, size_t); + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct rng_dev_s +{ + sem_t rd_devsem; /* Threads can only exclusively access the RNG */ +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct rng_dev_s g_rngdev; + +static const struct file_operations g_rngops = +{ + NULL, /* open */ + NULL, /* close */ + lpc54_read, /* read */ + NULL, /* write */ + NULL, /* seek */ + NULL /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + , NULL /* poll */ +#endif +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS + , NULL /* unlink */ +#endif +}; + +/**************************************************************************** + * Private functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lpc54_read + ****************************************************************************/ + +static ssize_t lpc54_read(struct file *filep, char *buffer, size_t buflen) +{ + union + { + uint32_t w; + uint8_t b[4]; + } value; + + ssize_t remaining; + int ret; + int i; + + /* Get exclusive access to ROM random number generator API */ + + ret = nxsem_wait(&g_rngdev.rd_devsem); + if (ret < 0) + { + return ret; + } + + /* Copy the requested number of randome bytes. */ + + for (remaining = buflen; remaining > 0;) + { + /* Read the next 32-bit random value */ + + value.w = LPC54_RNG_READ(); + + /* Return byte at a time to avoid alignment complexities (but + * sacrificing some performance). + */ + + for (i = 0; i < sizeof(uint32_t) && remaining > 0; i++, remaining--) + { + *buffer++ = value.b[i]; + } + } + + nxsem_post(&g_rngdev.rd_devsem); + return buflen; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: devrandom_register + * + * Description: + * Initialize the RNG hardware and register the /dev/random driver. + * Must be called BEFORE devurandom_register. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_DEV_RANDOM +void devrandom_register(void) +{ + nxsem_init(&g_rngdev.rd_devsem, 0, 1); + (void)register_driver("/dev/random", &g_rngops, 0444, NULL); +} +#endif + +/**************************************************************************** + * Name: devurandom_register + * + * Description: + * Register /dev/urandom + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_DEV_URANDOM_ARCH +void devurandom_register(void) +{ +#ifndef CONFIG_DEV_RANDOM + nxsem_init(&g_rngdev.rd_devsem, 0, 1); +#endif + (void)register_driver("/dev/urandom", &g_rngops, 0444, NULL); +} +#endif + +#endif /* CONFIG_DEV_RANDOM || CONFIG_DEV_URANDOM_ARCH */ +#endif /* CONFIG_LPC54_RNG */ diff --git a/arch/arm/src/lpc54xx/lpc54_rtc.c b/arch/arm/src/lpc54xx/lpc54_rtc.c index 064100b3b4..ba23c2ad84 100644 --- a/arch/arm/src/lpc54xx/lpc54_rtc.c +++ b/arch/arm/src/lpc54xx/lpc54_rtc.c @@ -147,8 +147,6 @@ static int lpc54_rtc_interrupt(int irq, void *context, FAR void *arg) int up_rtc_initialize(void) { - uint32_t regval; - /* Enable the clock to the RTC register interface and peripheral clock. */ lpc54_rtc_enableclk(); diff --git a/configs/lpcxpresso-lpc54628/README.txt b/configs/lpcxpresso-lpc54628/README.txt index b2e85c1192..140f577de3 100644 --- a/configs/lpcxpresso-lpc54628/README.txt +++ b/configs/lpcxpresso-lpc54628/README.txt @@ -75,6 +75,11 @@ STATUS non-functional without some additional investment. 2017-12-25: Added an RTC driver. It appears to be functional but has not been well tested. + 2017-12-26: Added an RNG driver. The RNG is actually controlled by a ROM + function. This driver seems to work fine when single stepping. However, + if I collect samples indefinitely, I do a reserved interrupt. I suspect + that to use the ROM at high frequencies it may be necessary to modify the + ROM access timing in some way. There is still no support for the Accelerometer, SPIFI, Ethernet, or USB. There is a complete, but not-yet-functional SD card drirver. There is a