This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 03738622a164334c4943a9723a91e98053c32616
Author: Alan C. Assis <[email protected]>
AuthorDate: Tue Sep 21 15:36:44 2021 -0300

    esp32s2: Add RNG driver support and board profile example
---
 arch/xtensa/src/esp32s2/Make.defs                  |   4 +
 arch/xtensa/src/esp32s2/esp32s2_rng.c              | 228 +++++++++++++++++++++
 arch/xtensa/src/esp32s2/hardware/wdev_reg.h        |  34 +++
 .../esp32s2-saola-1/configs/random/defconfig       |  48 +++++
 4 files changed, 314 insertions(+)

diff --git a/arch/xtensa/src/esp32s2/Make.defs 
b/arch/xtensa/src/esp32s2/Make.defs
index 84e2d78..e7d44f1 100644
--- a/arch/xtensa/src/esp32s2/Make.defs
+++ b/arch/xtensa/src/esp32s2/Make.defs
@@ -77,6 +77,10 @@ ifeq ($(CONFIG_ESP32S2_UART),y)
 CMN_CSRCS += esp32s2_serial.c
 endif
 
+ifeq ($(CONFIG_ESP32S2_RNG),y)
+CMN_CSRCS += esp32s2_rng.c
+endif
+
 ifeq ($(CONFIG_ESP32S2_TIMER),y)
 CHIP_CSRCS += esp32s2_tim.c
 ifeq ($(CONFIG_TIMER),y)
diff --git a/arch/xtensa/src/esp32s2/esp32s2_rng.c 
b/arch/xtensa/src/esp32s2/esp32s2_rng.c
new file mode 100644
index 0000000..85389c7
--- /dev/null
+++ b/arch/xtensa/src/esp32s2/esp32s2_rng.c
@@ -0,0 +1,228 @@
+/****************************************************************************
+ * arch/xtensa/src/esp32s2/esp32s2_rng.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <debug.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <nuttx/fs/fs.h>
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+#include <nuttx/semaphore.h>
+#include <nuttx/fs/ioctl.h>
+#include <nuttx/drivers/drivers.h>
+
+#include <arch/xtensa/core_macros.h>
+
+#include "xtensa.h"
+#include "xtensa_attr.h"
+#include "hardware/wdev_reg.h"
+#include "esp32s2_clockconfig.h"
+
+#if defined(CONFIG_ESP32S2_RNG)
+#if defined(CONFIG_DEV_RANDOM) || defined(CONFIG_DEV_URANDOM_ARCH)
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifndef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int esp32s2_rng_initialize(void);
+static ssize_t esp32s2_rng_read(struct file *filep, char *buffer,
+                                size_t buflen);
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct rng_dev_s
+{
+  uint8_t *rd_buf;
+  sem_t    rd_sem;         /* semaphore for read RNG data */
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct rng_dev_s g_rngdev;
+
+static const struct file_operations g_rngops =
+{
+  .read  = esp32s2_rng_read,       /* read */
+};
+
+/****************************************************************************
+ * Private functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp32s2_random
+ ****************************************************************************/
+
+uint32_t IRAM_ATTR esp_random(void)
+{
+  /* The PRNG which implements WDEV_RANDOM register gets 2 bits
+   * of extra entropy from a hardware randomness source every APB clock cycle
+   * (provided WiFi or BT are enabled). To make sure entropy is not drained
+   * faster than it is added, this function needs to wait for at least 16 APB
+   * clock cycles after reading previous word. This implementation may
+   * actually wait a bit longer due to extra time spent in arithmetic and
+   * branch statements.
+   *
+   * As a (probably unnecessary) precaution to avoid returning the
+   * RNG state as-is, the result is XORed with additional
+   * WDEV_RND_REG reads while waiting.
+   */
+
+  uint32_t cpu_to_apb_freq_ratio = esp_clk_cpu_freq() / esp_clk_apb_freq();
+
+  static uint32_t last_ccount = 0;
+  uint32_t ccount;
+  uint32_t result = 0;
+
+  do
+    {
+      ccount = XTHAL_GET_CCOUNT();
+      result ^= getreg32(WDEV_RND_REG);
+    }
+  while (ccount - last_ccount < cpu_to_apb_freq_ratio * 16);
+
+  last_ccount = ccount;
+  return result ^ getreg32(WDEV_RND_REG);
+}
+
+static int esp32s2_rng_initialize(void)
+{
+  _info("Initializing RNG\n");
+
+  memset(&g_rngdev, 0, sizeof(struct rng_dev_s));
+
+  nxsem_init(&g_rngdev.rd_sem, 0, 1);
+  nxsem_set_protocol(&g_rngdev.rd_sem, SEM_PRIO_NONE);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: esp32s2_rng_read
+ ****************************************************************************/
+
+static ssize_t esp32s2_rng_read(struct file *filep, char *buffer,
+                              size_t buflen)
+{
+  struct rng_dev_s *priv = (struct rng_dev_s *)&g_rngdev;
+  ssize_t read_len;
+  uint8_t *rd_buf = (uint8_t *)buffer;
+
+  if (nxsem_wait(&priv->rd_sem) != OK)
+    {
+      return -EBUSY;
+    }
+
+  read_len = buflen;
+
+  /* Wait until the buffer is filled */
+
+  while (buflen > 0)
+    {
+      uint32_t word = esp_random();
+      uint32_t to_copy = MIN(sizeof(word), buflen);
+
+      memcpy(rd_buf, &word, to_copy);
+      rd_buf += to_copy;
+      buflen -= to_copy;
+    }
+
+  /* Release rd_sem for next read */
+
+  nxsem_post(&priv->rd_sem);
+
+  return read_len;
+}
+
+/****************************************************************************
+ * 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)
+{
+  esp32s2_rng_initialize();
+  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
+  esp32s2_rng_initialize();
+#endif
+  register_driver("dev/urandom", &g_rngops, 0444, NULL);
+}
+#endif
+
+#endif /* CONFIG_DEV_RANDOM || CONFIG_DEV_URANDOM_ARCH */
+#endif /* CONFIG_ESP32S2_RNG */
diff --git a/arch/xtensa/src/esp32s2/hardware/wdev_reg.h 
b/arch/xtensa/src/esp32s2/hardware/wdev_reg.h
new file mode 100644
index 0000000..778352c
--- /dev/null
+++ b/arch/xtensa/src/esp32s2/hardware/wdev_reg.h
@@ -0,0 +1,34 @@
+/****************************************************************************
+ * arch/xtensa/src/esp32s2/hardware/wdev_reg.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_XTENSA_SRC_ESP32S2_HARDWARE_WDEV_REG_H
+#define __ARCH_XTENSA_SRC_ESP32S2_HARDWARE_WDEV_REG_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include "esp32s2_soc.h"
+
+/* Hardware random number generator register */
+
+#define WDEV_RND_REG 0x60035110
+
+#endif /* __ARCH_XTENSA_SRC_ESP32S2_HARDWARE_WDEV_REG_H */
diff --git a/boards/xtensa/esp32s2/esp32s2-saola-1/configs/random/defconfig 
b/boards/xtensa/esp32s2/esp32s2-saola-1/configs/random/defconfig
new file mode 100644
index 0000000..55de81e
--- /dev/null
+++ b/boards/xtensa/esp32s2/esp32s2-saola-1/configs/random/defconfig
@@ -0,0 +1,48 @@
+#
+# This file is autogenerated: PLEASE DO NOT EDIT IT.
+#
+# You can use "make menuconfig" to make any modifications to the installed 
.config file.
+# You can then do "make savedefconfig" to generate a new defconfig file that 
includes your
+# modifications.
+#
+# CONFIG_ARCH_LEDS is not set
+# CONFIG_NSH_ARGCAT is not set
+# CONFIG_NSH_CMDOPT_HEXDUMP is not set
+# CONFIG_NSH_CMDPARMS is not set
+CONFIG_ARCH="xtensa"
+CONFIG_ARCH_BOARD="esp32s2-saola-1"
+CONFIG_ARCH_BOARD_ESP32S2_SAOLA_1=y
+CONFIG_ARCH_CHIP="esp32s2"
+CONFIG_ARCH_CHIP_ESP32S2=y
+CONFIG_ARCH_CHIP_ESP32S2WROVER=y
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_ARCH_XTENSA=y
+CONFIG_BOARD_LOOPSPERMSEC=16717
+CONFIG_BUILTIN=y
+CONFIG_ESP32S2_DATA_CACHE_0KB=y
+CONFIG_ESP32S2_RNG=y
+CONFIG_ESP32S2_UART0=y
+CONFIG_EXAMPLES_RANDOM=y
+CONFIG_FS_PROCFS=y
+CONFIG_HAVE_CXX=y
+CONFIG_HAVE_CXXINITIALIZE=y
+CONFIG_IDLETHREAD_STACKSIZE=3072
+CONFIG_INTELHEX_BINARY=y
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_FILEIOSIZE=512
+CONFIG_NSH_LINELEN=64
+CONFIG_NSH_READLINE=y
+CONFIG_PREALLOC_TIMERS=4
+CONFIG_RAM_SIZE=114688
+CONFIG_RAM_START=0x20000000
+CONFIG_RAW_BINARY=y
+CONFIG_RR_INTERVAL=200
+CONFIG_SCHED_WAITPID=y
+CONFIG_SDCLONE_DISABLE=y
+CONFIG_START_DAY=6
+CONFIG_START_MONTH=12
+CONFIG_START_YEAR=2011
+CONFIG_SYSTEM_NSH=y
+CONFIG_UART0_SERIAL_CONSOLE=y
+CONFIG_USER_ENTRYPOINT="nsh_main"

Reply via email to