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

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


The following commit(s) were added to refs/heads/master by this push:
     new 7a32fed5637 arch/arm/stm32h7: support for /dev/random device
7a32fed5637 is described below

commit 7a32fed563733456cfc596d8d53f27c48fc98b7b
Author: sanezek <sane...@protonmail.com>
AuthorDate: Tue Jul 8 09:51:16 2025 +0000

    arch/arm/stm32h7: support for /dev/random device
    
    Enabling support for random device on stm32h7 arch. Driver copy pasted from 
arch/arm/stm32.
    
    Signed-off-by: sanezek <sane...@protonmail.com>
---
 arch/arm/src/stm32h7/Kconfig              |  14 ++
 arch/arm/src/stm32h7/Make.defs            |   4 +
 arch/arm/src/stm32h7/hardware/stm32_rng.h |  65 +++++++
 arch/arm/src/stm32h7/stm32_rng.c          | 314 ++++++++++++++++++++++++++++++
 4 files changed, 397 insertions(+)

diff --git a/arch/arm/src/stm32h7/Kconfig b/arch/arm/src/stm32h7/Kconfig
index 3c2a780b831..c8e839b58a6 100644
--- a/arch/arm/src/stm32h7/Kconfig
+++ b/arch/arm/src/stm32h7/Kconfig
@@ -401,6 +401,7 @@ config STM32H7_STM32H7X3XX
        select STM32H7_HAVE_SPI4
        select STM32H7_HAVE_SPI5 if !STM32H7_IO_CONFIG_V
        select STM32H7_HAVE_SPI6
+       select STM32H7_HAVE_RNG
 
 config STM32H7_STM32H7B3XX
        bool
@@ -414,6 +415,7 @@ config STM32H7_STM32H7B3XX
        select STM32H7_HAVE_SPI4
        select STM32H7_HAVE_SPI5 if !STM32H7_IO_CONFIG_V
        select STM32H7_HAVE_SPI6
+       select STM32H7_HAVE_RNG
 
 config STM32H7_STM32H7X5XX
        bool
@@ -430,6 +432,7 @@ config STM32H7_STM32H7X5XX
        select STM32H7_HAVE_SPI5 if !STM32H7_IO_CONFIG_V
        select STM32H7_HAVE_SPI6
        select STM32H7_HAVE_SMPS
+       select STM32H7_HAVE_RNG
 
 config STM32H7_STM32H7X7XX
        bool
@@ -445,6 +448,7 @@ config STM32H7_STM32H7X7XX
        select STM32H7_HAVE_SPI4
        select STM32H7_HAVE_SPI5
        select STM32H7_HAVE_SPI6
+       select STM32H7_HAVE_RNG
 
 config STM32H7_FLASH_CONFIG_B
        bool
@@ -655,6 +659,10 @@ config STM32H7_HAVE_FDCAN2
        bool
        default n
 
+config STM32H7_HAVE_RNG
+       bool
+       default n
+
 # These "hidden" settings are the OR of individual peripheral selections
 # indicating that the general capability is required.
 
@@ -752,6 +760,12 @@ config STM32H7_ADC3
        default n
        select STM32H7_ADC
 
+config STM32H7_RNG
+       bool "RNG"
+       default n
+       depends on STM32H7_HAVE_RNG
+       select ARCH_HAVE_RNG
+
 config STM32H7_CRC
        bool "CRC"
        default n
diff --git a/arch/arm/src/stm32h7/Make.defs b/arch/arm/src/stm32h7/Make.defs
index 119a82d3a68..99ea4826e2d 100644
--- a/arch/arm/src/stm32h7/Make.defs
+++ b/arch/arm/src/stm32h7/Make.defs
@@ -79,6 +79,10 @@ ifeq ($(CONFIG_STM32H7_FDCAN),y)
 CHIP_CSRCS += stm32_fdcan_sock.c
 endif
 
+ifeq ($(CONFIG_STM32H7_RNG),y)
+CHIP_CSRCS += stm32_rng.c
+endif
+
 ifeq ($(CONFIG_STM32H7_BBSRAM),y)
 CHIP_CSRCS += stm32_bbsram.c
 endif
diff --git a/arch/arm/src/stm32h7/hardware/stm32_rng.h 
b/arch/arm/src/stm32h7/hardware/stm32_rng.h
new file mode 100644
index 00000000000..53bbaa8263f
--- /dev/null
+++ b/arch/arm/src/stm32h7/hardware/stm32_rng.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+ * arch/arm/src/stm32h7/hardware/stm32_rng.h
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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_ARM_SRC_STM32H7_HARDWARE_STM32_RNG_H
+#define __ARCH_ARM_SRC_STM32H7_HARDWARE_STM32_RNG_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include "chip.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Register Offsets *********************************************************/
+
+#define STM32_RNG_CR_OFFSET       0x0000  /* RNG Control Register */
+#define STM32_RNG_SR_OFFSET       0x0004  /* RNG Status Register */
+#define STM32_RNG_DR_OFFSET       0x0008  /* RNG Data Register */
+
+/* Register Addresses *******************************************************/
+
+#define STM32_RNG_CR              (STM32_RNG_BASE+STM32_RNG_CR_OFFSET)
+#define STM32_RNG_SR              (STM32_RNG_BASE+STM32_RNG_SR_OFFSET)
+#define STM32_RNG_DR              (STM32_RNG_BASE+STM32_RNG_DR_OFFSET)
+
+/* Register Bitfield Definitions ********************************************/
+
+/* RNG Control Register */
+
+#define RNG_CR_RNGEN              (1 << 2)  /* Bit 2: RNG enable */
+#define RNG_CR_IE                 (1 << 3)  /* Bit 3: Interrupt enable */
+#define RNG_CR_CE                 (1 << 5)  /* Bit 5: Clock error detection */
+
+/* RNG Status Register */
+
+#define RNG_SR_DRDY               (1 << 0) /* Bit 0: Data ready */
+#define RNG_SR_CECS               (1 << 1) /* Bit 1: Clock error current 
status */
+#define RNG_SR_SECS               (1 << 2) /* Bit 2: Seed error current status 
*/
+#define RNG_SR_CEIS               (1 << 5) /* Bit 5: Clock error interrupt 
status */
+#define RNG_SR_SEIS               (1 << 6) /* Bit 6: Seed error interrupt 
status */
+
+#endif /* __ARCH_ARM_SRC_STM32H7_HARDWARE_STM32_RNG_H */
diff --git a/arch/arm/src/stm32h7/stm32_rng.c b/arch/arm/src/stm32h7/stm32_rng.c
new file mode 100644
index 00000000000..698ab16933f
--- /dev/null
+++ b/arch/arm/src/stm32h7/stm32_rng.c
@@ -0,0 +1,314 @@
+/****************************************************************************
+ * arch/arm/src/stm32h7/stm32_rng.c
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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 <stdint.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <debug.h>
+#include <errno.h>
+
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+#include <nuttx/mutex.h>
+#include <nuttx/semaphore.h>
+#include <nuttx/fs/fs.h>
+#include <nuttx/drivers/drivers.h>
+
+#include "hardware/stm32_rng.h"
+#include "arm_internal.h"
+
+#if defined(CONFIG_STM32H7_RNG)
+#if defined(CONFIG_DEV_RANDOM) || defined(CONFIG_DEV_URANDOM_ARCH)
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int stm32_rng_initialize(void);
+static int stm32_rng_interrupt(int irq, void *context, void *arg);
+static void stm32_rng_enable(void);
+static void stm32_rng_disable(void);
+static ssize_t stm32_rng_read(struct file *filep, char *buffer, size_t);
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct rng_dev_s
+{
+  mutex_t rd_devlock;   /* Threads can only exclusively access the RNG */
+  sem_t rd_readsem;     /* To block until the buffer is filled  */
+  char *rd_buf;
+  size_t rd_buflen;
+  uint32_t rd_lastval;
+  bool rd_first;
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct rng_dev_s g_rngdev =
+{
+  .rd_devlock = NXMUTEX_INITIALIZER,
+  .rd_readsem = SEM_INITIALIZER(0),
+};
+
+static const struct file_operations g_rngops =
+{
+  NULL,            /* open */
+  NULL,            /* close */
+  stm32_rng_read,  /* read */
+};
+
+/****************************************************************************
+ * Private functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_rng_initialize
+ ****************************************************************************/
+
+static int stm32_rng_initialize(void)
+{
+  uint32_t regval;
+
+  _info("Initializing RNG\n");
+
+  if (irq_attach(STM32_IRQ_RNG, stm32_rng_interrupt, NULL))
+    {
+      /* We could not attach the ISR to the interrupt */
+
+      _info("Could not attach IRQ.\n");
+
+      return -EAGAIN;
+    }
+
+  /* Enable interrupts */
+
+  regval = getreg32(STM32_RNG_CR);
+  regval |=  RNG_CR_IE;
+  putreg32(regval, STM32_RNG_CR);
+
+  up_enable_irq(STM32_IRQ_RNG);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: stm32_rng_enable
+ ****************************************************************************/
+
+static void stm32_rng_enable(void)
+{
+  uint32_t regval;
+
+  g_rngdev.rd_first = true;
+
+  regval = getreg32(STM32_RNG_CR);
+  regval |= RNG_CR_RNGEN;
+  putreg32(regval, STM32_RNG_CR);
+}
+
+/****************************************************************************
+ * Name: stm32_rng_disable
+ ****************************************************************************/
+
+static void stm32_rng_disable(void)
+{
+  uint32_t regval;
+  regval = getreg32(STM32_RNG_CR);
+  regval &= ~RNG_CR_RNGEN;
+  putreg32(regval, STM32_RNG_CR);
+}
+
+/****************************************************************************
+ * Name: stm32_rng_interrupt
+ ****************************************************************************/
+
+static int stm32_rng_interrupt(int irq, void *context, void *arg)
+{
+  uint32_t rngsr;
+  uint32_t data;
+
+  rngsr = getreg32(STM32_RNG_SR);
+
+  if ((rngsr & (RNG_SR_SEIS | RNG_SR_CEIS)) /* Check for error bits */
+      || !(rngsr & RNG_SR_DRDY))            /* Data ready must be set */
+    {
+      /* This random value is not valid, we will try again. */
+
+      return OK;
+    }
+
+  data = getreg32(STM32_RNG_DR);
+
+  /* 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).
+   */
+
+  if (g_rngdev.rd_first)
+    {
+      g_rngdev.rd_first = false;
+      g_rngdev.rd_lastval = data;
+      return OK;
+    }
+
+  if (g_rngdev.rd_lastval == data)
+    {
+      /* Two subsequent same numbers, we will try again. */
+
+      return OK;
+    }
+
+  /* If we get here, the random number is valid. */
+
+  g_rngdev.rd_lastval = data;
+
+  if (g_rngdev.rd_buflen >= 4)
+    {
+      g_rngdev.rd_buflen -= 4;
+      *(uint32_t *)&g_rngdev.rd_buf[g_rngdev.rd_buflen] = data;
+    }
+  else
+    {
+      while (g_rngdev.rd_buflen > 0)
+        {
+          g_rngdev.rd_buf[--g_rngdev.rd_buflen] = (char)data;
+          data >>= 8;
+        }
+    }
+
+  if (g_rngdev.rd_buflen == 0)
+    {
+      /* Buffer filled, stop further interrupts. */
+
+      stm32_rng_disable();
+      nxsem_post(&g_rngdev.rd_readsem);
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: stm32_rng_read
+ ****************************************************************************/
+
+static ssize_t stm32_rng_read(struct file *filep, char *buffer,
+                              size_t buflen)
+{
+  int ret;
+
+  ret = nxmutex_lock(&g_rngdev.rd_devlock);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  /* We've got the mutex. */
+
+  /* Reset the operation semaphore with 0 for blocking until the
+   * buffer is filled from interrupts.
+   */
+
+  nxsem_reset(&g_rngdev.rd_readsem, 0);
+
+  g_rngdev.rd_buflen = buflen;
+  g_rngdev.rd_buf = buffer;
+
+  /* Enable RNG with interrupts */
+
+  stm32_rng_enable();
+
+  /* Wait until the buffer is filled */
+
+  ret = nxsem_wait(&g_rngdev.rd_readsem);
+
+  /* Free RNG for next use */
+
+  nxmutex_unlock(&g_rngdev.rd_devlock);
+  return ret < 0 ? ret : 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)
+{
+  stm32_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
+  stm32_rng_initialize();
+#endif
+  register_driver("/dev/urandom", &g_rngops, 0444, NULL);
+}
+#endif
+
+#endif /* CONFIG_DEV_RANDOM || CONFIG_DEV_URANDOM_ARCH */
+#endif /* CONFIG_STM32H7_RNG */

Reply via email to