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/nuttx.git

commit 4c9d405a97b8ed1e14c91129da6483722d9234de
Author: raiden00pl <raide...@railab.me>
AuthorDate: Mon Aug 21 09:40:05 2023 +0200

    arch/stm32h7: add HSEM support
---
 arch/arm/src/stm32h7/CMakeLists.txt        |   7 +-
 arch/arm/src/stm32h7/Kconfig               |   4 +
 arch/arm/src/stm32h7/Make.defs             |   4 +
 arch/arm/src/stm32h7/hardware/stm32_hsem.h |  83 ++++++++
 arch/arm/src/stm32h7/stm32_hsem.c          | 291 +++++++++++++++++++++++++++++
 arch/arm/src/stm32h7/stm32_hsem.h          |  68 +++++++
 arch/arm/src/stm32h7/stm32h7x3xx_rcc.c     |   6 +
 7 files changed, 461 insertions(+), 2 deletions(-)

diff --git a/arch/arm/src/stm32h7/CMakeLists.txt 
b/arch/arm/src/stm32h7/CMakeLists.txt
index 27ed366f2d..34ad2414b1 100644
--- a/arch/arm/src/stm32h7/CMakeLists.txt
+++ b/arch/arm/src/stm32h7/CMakeLists.txt
@@ -31,13 +31,16 @@ list(
   stm32_rcc.c
   stm32_lowputc.c
   stm32_serial.c
-  stm32_uid.c
-)
+  stm32_uid.c)
 
 if(CONFIG_STM32H7_PROGMEM)
   list(APPEND SRCS stm32_flash.c)
 endif()
 
+if(CONFIG_STM32H7_HSEM)
+  list(APPEND SRCS stm32_hsem.c)
+endif()
+
 if(CONFIG_SCHED_TICKLESS)
   list(APPEND SRCS stm32_tickless.c)
 else()
diff --git a/arch/arm/src/stm32h7/Kconfig b/arch/arm/src/stm32h7/Kconfig
index fec677d2c4..f06746ab3f 100644
--- a/arch/arm/src/stm32h7/Kconfig
+++ b/arch/arm/src/stm32h7/Kconfig
@@ -633,6 +633,10 @@ config STM32H7_LPTIM
        bool
        default n
 
+config STM32H7_HSEM
+       bool "Hardware semaphore"
+       default n
+
 config STM32H7_RTC
        bool "RTC"
        default n
diff --git a/arch/arm/src/stm32h7/Make.defs b/arch/arm/src/stm32h7/Make.defs
index 8d1433e69f..aeaa171425 100644
--- a/arch/arm/src/stm32h7/Make.defs
+++ b/arch/arm/src/stm32h7/Make.defs
@@ -29,6 +29,10 @@ ifeq ($(CONFIG_STM32H7_PROGMEM),y)
 CHIP_CSRCS += stm32_flash.c
 endif
 
+ifeq ($(CONFIG_STM32H7_HSEM),y)
+CHIP_CSRCS += stm32_hsem.c
+endif
+
 # Required STM32H7 files
 
 CHIP_CSRCS += stm32_allocateheap.c stm32_exti_gpio.c stm32_gpio.c stm32_irq.c
diff --git a/arch/arm/src/stm32h7/hardware/stm32_hsem.h 
b/arch/arm/src/stm32h7/hardware/stm32_hsem.h
new file mode 100644
index 0000000000..9aa13fe9c3
--- /dev/null
+++ b/arch/arm/src/stm32h7/hardware/stm32_hsem.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+ * arch/arm/src/stm32h7/hardware/stm32_hsem.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_ARM_SRC_STM32H7_HARDWARE_STM32_HSEM_H
+#define __ARCH_ARM_SRC_STM32H7_HARDWARE_STM32_HSEM_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include "chip.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define STM32_HSEM_CHANS             (32)
+#define HSEM_COREID_CPU1             (3)
+#define HSEM_COREID_CPU2             (1)
+
+/* Register Offsets *********************************************************/
+
+#define STM32_HSEM_RX_OFFSET(n)       (0x0000 + (0x4 * n))   /* HSEM register 
semaphore x */
+#define STM32_HSEM_RLRX_OFFSET(n)     (0x0080 + (0x4 * n))   /* HSEM read lock 
register semaphore x */
+#define STM32_HSEM_CXIER_OFFSET(n)    (0x0100 + (0x10 * n))  /* HSEM interrupt 
enable register */
+#define STM32_HSEM_CXICR_OFFSET(n)    (0x0104 + (0x10 * n))  /* HSEM interrupt 
clear register */
+#define STM32_HSEM_CXISR_OFFSET(n)    (0x0108 + (0x10 * n))  /* HSEM interrupt 
status register */
+#define STM32_HSEM_CXMISR_OFFSET(n)   (0x010c + (0x10 * n))  /* HSEM interrupt 
status register */
+#define STM32_HSEM_CR_OFFSET          (0x0140)               /* HSEM clear 
register */
+#define STM32_HSEM_KEYR_OFFSET        (0x0144)               /* HSEM semaphore 
clear key */
+
+/* Register Addresses *******************************************************/
+
+#define STM32_HSEM_RX(x)              (STM32_HSEM_BASE+STM32_HSEM_RX_OFFSET(x))
+#define STM32_HSEM_RLRX(x)            
(STM32_HSEM_BASE+STM32_HSEM_RLRX_OFFSET(x))
+#define STM32_HSEM_CXIER(x)           
(STM32_HSEM_BASE+STM32_HSEM_CXIER_OFFSET(x))
+#define STM32_HSEM_CXICR(x)           
(STM32_HSEM_BASE+STM32_HSEM_CXICR_OFFSET(x))
+#define STM32_HSEM_CXISR(x)           
(STM32_HSEM_BASE+STM32_HSEM_CXISR_OFFSET(x))
+#define STM32_HSEM_CXMISR(x)          
(STM32_HSEM_BASE+STM32_HSEM_CXMISR_OFFSET(x))
+#define STM32_HSEM_CXMISRCR           (STM32_HSEM_BASE+STM32_HSEM_CR_OFFSET)
+#define STM32_HSEM_KEYR               (STM32_HSEM_BASE+STM32_HSEM_KEYR_OFFSET)
+
+/* Register Bitfield Definitions ********************************************/
+
+/* Semaphore x registers */
+
+#define HSEM_SEMX_PROCID_SHIFT      (0)        /* Bits 0-8: Semaphore PROCID */
+#define HSEM_SEMX_PROCID_MASK       (0xff << HSEM_SEMX_PROCID_SHIFT)
+#define HSEM_SEMX_COREID_SHIFT      (8)        /* Bits 8-11: Semaphore COREID 
*/
+#define HSEM_SEMX_COREID_MASK       (0xf << HSEM_SEMX_COREID_SHIFT)
+                                               /* Bits 12-30: reserved */
+#define HSEM_SEMX_LOCK              (1 << 31)  /* Bit 31: Lock indication */
+
+/* Clear register */
+
+#define HSEM_CR_COREID_SHIFT        (8) /* Bits 8-11: COREID of semaphores to 
be cleared */
+#define HSEM_CR_COREID_MASK         (0xf << HSEM_CR_COREID_SHIFT)
+#define HSEM_CR_KEY_SHIFT           (16) /* Bits 16-31: Semaphore clear Key */
+#define HSEM_CR_KEY_MASK            (0xffff << HSEM_CR_KEY_SHIFT)
+
+/* Interrupts */
+
+#define HSEM_CHAN_ID(n)             (1 << n)
+
+#endif /* __ARCH_ARM_SRC_STM32H7_HARDWARE_STM32_HSEM_H */
diff --git a/arch/arm/src/stm32h7/stm32_hsem.c 
b/arch/arm/src/stm32h7/stm32_hsem.c
new file mode 100644
index 0000000000..8bb638501f
--- /dev/null
+++ b/arch/arm/src/stm32h7/stm32_hsem.c
@@ -0,0 +1,291 @@
+/****************************************************************************
+ * arch/arm/src/stm32h7/stm32_hsem.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 <debug.h>
+
+#include "nvic.h"
+
+#include "arm_internal.h"
+#include "stm32_hsem.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* HSEM receive channel configuration */
+
+struct stm32_hsem_recv_s
+{
+  hsem_callback_t  callback;
+  void            *args;
+};
+
+/* HSEM device */
+
+struct stm32_hsem_s
+{
+  struct stm32_hsem_recv_s recv[STM32_HSEM_CHANS];
+  uint32_t                 irq;
+  uint8_t                  block;
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+struct stm32_hsem_s g_stm32_hsem;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_hsem_interrupt
+ ****************************************************************************/
+
+static int stm32_hsem_interrupt(int irq, void *context, void *args)
+{
+  struct stm32_hsem_s *dev    = args;
+  uint32_t             regval = 0;
+  int                  i      = 0;
+
+  regval = getreg32(STM32_HSEM_CXMISR(dev->block));
+
+  _info("HSEM interrupt 0x%" PRIx32 "\n", regval);
+
+  for (i = 0; i < STM32_HSEM_CHANS; i++)
+    {
+      if (regval & HSEM_CHAN_ID(i))
+        {
+          if (dev->recv[i].callback)
+            {
+              dev->recv[i].callback(i, dev->recv[i].args);
+            }
+        }
+    }
+
+  /* Clear events */
+
+  putreg32(regval, STM32_HSEM_CXICR(dev->block));
+
+  return 0;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_hsem_subscribe
+ *
+ * Description:
+ *   Subscribe to event on a given semaphore
+ *
+ ****************************************************************************/
+
+void stm32_hsem_subscribe(uint8_t id, hsem_callback_t callback, void *args)
+{
+  struct stm32_hsem_s *dev = &g_stm32_hsem;
+
+  DEBUGASSERT(id < STM32_HSEM_CHANS);
+
+  _info("HSEM subscribe %d\n", id);
+
+  /* Register callaback */
+
+  dev->recv[id].callback = callback;
+  dev->recv[id].args = args;
+
+  if (callback)
+    {
+      /* Clear pending */
+
+      putreg32(HSEM_CHAN_ID(id), STM32_HSEM_CXICR(dev->block));
+
+      /* Enable interrupt */
+
+      modifyreg32(STM32_HSEM_CXIER(dev->block), 0, HSEM_CHAN_ID(id));
+    }
+  else
+    {
+      /* Disable interrupts */
+
+      modifyreg32(STM32_HSEM_CXIER(dev->block), HSEM_CHAN_ID(id), 0);
+    }
+}
+
+/****************************************************************************
+ * Name: stm32_hsem_signal
+ *
+ * Description:
+ *   Signal on a semaphore (free and lock again)
+ *
+ ****************************************************************************/
+
+void stm32_hsem_signal(uint8_t id)
+{
+  DEBUGASSERT(id < STM32_HSEM_CHANS);
+
+  _info("HSEM signal %d\n", id);
+
+  /* Lock semaphore */
+
+  while (stm32_hsem_take(id) == 0);
+
+  /* Free semaphore to signal event */
+
+  stm32_hsem_free(id);
+}
+
+/****************************************************************************
+ * Name: stm32_hsem_busywait_lock
+ *
+ * Description:
+ *   Busy wait for a semaphore to be locked
+ *
+ ****************************************************************************/
+
+void stm32_hsem_busywait_lock(uint8_t id)
+{
+  DEBUGASSERT(id < STM32_HSEM_CHANS);
+
+  _info("HSEM busywait lock %d\n", id);
+
+  /* Wait for semaphore lock */
+
+  while ((getreg32(STM32_HSEM_RX(id)) & HSEM_SEMX_LOCK) == 0);
+}
+
+/****************************************************************************
+ * Name: stm32_hsem_busywait_free
+ *
+ * Description:
+ *   Busy wait for a semaphore to be free
+ *
+ ****************************************************************************/
+
+void stm32_hsem_busywait_free(uint8_t id)
+{
+  DEBUGASSERT(id < STM32_HSEM_CHANS);
+
+  _info("HSEM busywait free %d\n", id);
+
+  /* Wait for semaphore free */
+
+  while ((getreg32(STM32_HSEM_RX(id)) & HSEM_SEMX_LOCK) != 0);
+}
+
+/****************************************************************************
+ * Name: stm32_hsem_wait_take
+ *
+ * Description:
+ *   Take a semaphore (1-step lock)
+ *
+ ****************************************************************************/
+
+void stm32_hsem_wait_take(uint8_t id)
+{
+  DEBUGASSERT(id < STM32_HSEM_CHANS);
+
+  _info("HSEM wait take %d\n", id);
+
+  stm32_hsem_busywait_free(id);
+  while (stm32_hsem_take(id) == 0);
+}
+
+/****************************************************************************
+ * Name: stm32_hsem_take
+ *
+ * Description:
+ *   Take a semaphore (1-step lock)
+ *
+ ****************************************************************************/
+
+bool stm32_hsem_take(uint8_t id)
+{
+  DEBUGASSERT(id < STM32_HSEM_CHANS);
+
+  _info("HSEM take %d\n", id);
+
+  /* Take semaphore */
+
+#ifdef CONFIG_ARCH_CHIP_STM32H7_CORTEXM7
+  return (getreg32(STM32_HSEM_RLRX(id)) ==
+          ((HSEM_COREID_CPU1 << HSEM_SEMX_COREID_SHIFT) | HSEM_SEMX_LOCK));
+#else
+  return (getreg32(STM32_HSEM_RLRX(id)) ==
+          ((HSEM_COREID_CPU2 << HSEM_SEMX_COREID_SHIFT) | HSEM_SEMX_LOCK));
+#endif
+}
+
+/****************************************************************************
+ * Name: stm32_hsem_free
+ *
+ * Description:
+ *   Free a semaphore
+ *
+ ****************************************************************************/
+
+void stm32_hsem_free(uint8_t id)
+{
+#ifdef CONFIG_ARCH_CHIP_STM32H7_CORTEXM7
+  putreg32((HSEM_COREID_CPU1 << HSEM_CR_COREID_SHIFT) , STM32_HSEM_RX(id));
+#else
+  putreg32((HSEM_COREID_CPU2 << HSEM_CR_COREID_SHIFT) , STM32_HSEM_RX(id));
+#endif
+}
+
+/****************************************************************************
+ * Name: stm32_hsem_init
+ *
+ * Description:
+ *   Initialize the hardware semaphore driver
+ *
+ ****************************************************************************/
+
+void stm32_hsem_init(void)
+{
+  struct stm32_hsem_s *dev = &g_stm32_hsem;
+
+  /* Reset device */
+
+  memset(dev, 0, sizeof(struct stm32_hsem_s));
+
+  /* Set block id */
+
+#ifdef CONFIG_ARCH_CHIP_STM32H7_CORTEXM7
+  dev->block = 0;
+  dev->irq   = STM32_IRQ_HSEM0;
+#else
+  dev->block = 1;
+  dev->irq   = STM32_IRQ_HSEM1;
+#endif
+
+  /* Attach and enable the IRQ */
+
+  irq_attach(dev->irq, stm32_hsem_interrupt, dev);
+  up_enable_irq(dev->irq);
+}
diff --git a/arch/arm/src/stm32h7/stm32_hsem.h 
b/arch/arm/src/stm32h7/stm32_hsem.h
new file mode 100644
index 0000000000..7cd1c36380
--- /dev/null
+++ b/arch/arm/src/stm32h7/stm32_hsem.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+ * arch/arm/src/stm32h7/stm32_hsem.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_ARM_SRC_STM32H7_STM32_HSEM_H
+#define __ARCH_ARM_SRC_STM32H7_STM32_HSEM_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+
+#include "hardware/stm32_hsem.h"
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+typedef void (*hsem_callback_t)(uint8_t id, void *arg);
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+void stm32_hsem_subscribe(uint8_t id, hsem_callback_t callback, void *args);
+void stm32_hsem_signal(uint8_t id);
+void stm32_hsem_busywait_lock(uint8_t id);
+void stm32_hsem_busywait_free(uint8_t id);
+void stm32_hsem_wait_take(uint8_t id);
+bool stm32_hsem_take(uint8_t id);
+void stm32_hsem_free(uint8_t id);
+void stm32_hsem_init(void);
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ARCH_ARM_SRC_STM32H7_STM32_HSEM_H */
diff --git a/arch/arm/src/stm32h7/stm32h7x3xx_rcc.c 
b/arch/arm/src/stm32h7/stm32h7x3xx_rcc.c
index 1068ee493f..81828fdf6e 100644
--- a/arch/arm/src/stm32h7/stm32h7x3xx_rcc.c
+++ b/arch/arm/src/stm32h7/stm32h7x3xx_rcc.c
@@ -416,6 +416,12 @@ static inline void rcc_enableahb4(void)
   regval |= RCC_AHB4ENR_BKPSRAMEN;
 #endif
 
+#ifdef CONFIG_STM32H7_HSEM
+  /* HSEM clock enable */
+
+  regval |= RCC_AHB4ENR_HSEMEN;
+#endif
+
   putreg32(regval, STM32_RCC_AHB4ENR);   /* Enable peripherals */
 }
 

Reply via email to