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

archer 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 46411495ef arch/arm/STM32H5: Initial ICACHE Support
46411495ef is described below

commit 46411495efed11e1c7fa4b9bec93bb396a0276c8
Author: Kyle Wilson <kwil...@2g-eng.com>
AuthorDate: Tue Jan 28 15:36:12 2025 -0600

    arch/arm/STM32H5: Initial ICACHE Support
    
    Add support for the STM32H5 ICACHE peripheral. The CortexM33 does not have 
typical embedded icache and dcache. Instead STM32H5 provides the ICACHE as a 
separate peripheral that needs to be configured. This commit adds the stm32h5 
specific icache driver. This driver named functions like those in 
<nuttx/cache.h>. However since the CortexM33 does not have cache itself, 
ARCH_ICACHE is not enabled. Therefore these stm32h5 specific functions were 
developed.
    
    Signed-off-by: kywwilson11 <kwil...@2g-eng.com>
---
 arch/arm/src/stm32h5/Kconfig                 | 246 ++++++++++++++++++
 arch/arm/src/stm32h5/Make.defs               |   4 +
 arch/arm/src/stm32h5/hardware/stm32_icache.h | 107 ++++++++
 arch/arm/src/stm32h5/stm32.h                 |   9 +-
 arch/arm/src/stm32h5/stm32_icache.c          | 366 +++++++++++++++++++++++++++
 arch/arm/src/stm32h5/stm32_icache.h          | 158 ++++++++++++
 arch/arm/src/stm32h5/stm32_start.c           |   5 +
 7 files changed, 891 insertions(+), 4 deletions(-)

diff --git a/arch/arm/src/stm32h5/Kconfig b/arch/arm/src/stm32h5/Kconfig
index 79514bca10..5ec9f85872 100644
--- a/arch/arm/src/stm32h5/Kconfig
+++ b/arch/arm/src/stm32h5/Kconfig
@@ -31,6 +31,7 @@ config STM32H5_STM32H5XXXX
        bool
        default n
        select ARCH_HAVE_FPU
+       select STM32H5_HAVE_ICACHE
 
 config STM32H5_STM32H56XXX
        bool
@@ -55,6 +56,7 @@ config STM32H5_STM32H56XXX
        select STM32H5_HAVE_SPI6
        select STM32H5_HAVE_USBFS
        select STM32H5_HAVE_HSI48
+       select STM32H5_HAVE_ICACHE_REMAP
 
 config STM32H5_STM32H563XX
        # STM32H552 and STM32H562 devices documented in RM0439
@@ -226,6 +228,10 @@ config STM32H5_HAVE_HSI48
        bool
        default n
 
+config STM32H5_HAVE_ICACHE
+       bool
+       default n
+
 config STM32H5_HAVE_LPUART1
        bool
        default n
@@ -333,6 +339,11 @@ config STM32H5_ETHMAC
        select ARCH_HAVE_PHY
        select STM32H5_HAVE_PHY_POLLED
 
+config STM32H5_ICACHE
+       bool "ICACHE"
+       default n
+       depends on STM32H5_HAVE_ICACHE
+
 config STM32H5_QSPI1
        bool "QSPI1"
        default n
@@ -579,6 +590,241 @@ config STM32H5_FLASH_PREFETCH
        ---help---
                Enable FLASH prefetch
 
+menu "ICACHE Configuration"
+       depends on STM32H5_ICACHE
+
+config STM32H5_ICACHE_MONITOR_EN
+       bool "Enable ICACHE Hit/Miss Counters"
+       default n
+
+config STM32H5_ICACHE_DIRECT
+       bool "Enable 1-Way Direct Mapped Cache (N-Way = default)"
+       default n
+
+menu "ICACHE Interrupt Configuration"
+       depends on STM32H5_ICACHE
+
+config STM32H5_ICACHE_INV_INT
+       bool "Enable interrupts on full invalidation completion."
+       default n
+
+config STM32H5_ICACHE_ERR_INT
+       bool "Enable interrupts on occurrences of cache errors."
+       default n
+
+endmenu # ICACHE Interrupt Configuration
+
+menu "ICACHE Region Configuration"
+       depends on STM32H5_ICACHE
+
+config STM32H5_ICACHE_REGION0
+       bool "Enable Configuration of ICACHE Region 0"
+       default n
+
+config STM32H5_ICACHE_REGION1
+       bool "Enable Configuration of ICACHE Region 1"
+       default n
+
+config STM32H5_ICACHE_REGION2
+       bool "Enable Configuration of ICACHE Region 2"
+       default n
+
+config STM32H5_ICACHE_REGION3
+       bool "Enable Configuration of ICACHE Region 3"
+       default n
+
+menu "Region 0 Configuration"
+       depends on STM32H5_ICACHE_REGION0 && STM32H5_HAVE_ICACHE_REMAP
+
+config STM32H5_ICACHE_REGION0_BADDR
+       hex "ICACHE Region 0 Base Address Bits [28:21]"
+       default 0
+       range 0 255
+       depends on STM32H5_ICACHE_REGION0
+       ---help---
+               Set bits [28:21] of the base address for ICACHE Region 0.
+
+config STM32H5_ICACHE_REGION0_RSIZE
+       int "ICACHE Region 0 Size"
+       default 1
+       range 1 7
+       depends on STM32H5_ICACHE_REGION0
+       ---help---
+               Set the size of Region 0.
+                1 = 2 Mbytes, 2 = 4 Mbytes, 3 = 8 Mbytes, 4 = 16 Mbytes,
+                5 = 2 Mbytes, 6 = 64 Mbytes, 7 = 128 Mbytes.
+
+config STM32H5_ICACHE_REGION0_REMAPADDR
+       hex "ICACHE Region 0 Remap Address Bits [31:21]"
+       default 0
+       range 0 2047
+       depends on STM32H5_ICACHE_REGION0
+       ---help---
+               Set bits [31:21] of ICACHE Region 0 Remap Address..
+
+config STM32H5_ICACHE_REGION0_MSTSEL
+       int "ICACHE Region 0 Master Select (0 or 1)"
+       default 0
+       range 0 1
+       depends on STM32H5_ICACHE_REGION0
+       ---help---
+               Select ICACHE Region 0 Master 1 (0) or Master 2 (1).
+
+config STM32H5_ICACHE_REGION0_HBURST
+       int "ICACHE Region 0 Output Burst Type (0 = Wrap, 1 = Incr)"
+       default 0
+       range 0 1
+       depends on STM32H5_ICACHE_REGION0
+       ---help---
+               Select Wrap (0) or Increment (1) Output Burst Type.
+
+endmenu # Region 0 Configuration
+
+menu "Region 1 Configuration"
+       depends on STM32H5_ICACHE_REGION1 && STM32H5_HAVE_ICACHE_REMAP
+
+config STM32H5_ICACHE_REGION1_BADDR
+       hex "ICACHE Region 1 Base Address Bits [28:21]"
+       default 0
+       range 0 255
+       depends on STM32H5_ICACHE_REGION1
+       ---help---
+               Set bits [28:21] of the base address for ICACHE Region 1.
+
+config STM32H5_ICACHE_REGION1_RSIZE
+       int "ICACHE Region 1 Size"
+       default 1
+       range 1 7
+       depends on STM32H5_ICACHE_REGION1
+       ---help---
+               Set the size of Region 1.
+                1 = 2 Mbytes, 2 = 4 Mbytes, 3 = 8 Mbytes, 4 = 16 Mbytes,
+                5 = 2 Mbytes, 6 = 64 Mbytes, 7 = 128 Mbytes.
+
+config STM32H5_ICACHE_REGION1_REMAPADDR
+       hex "ICACHE Region 1 Remap Address Bits [31:21]"
+       default 0
+       range 0 2047
+       depends on STM32H5_ICACHE_REGION1
+       ---help---
+               Set bits [31:21] of ICACHE Region 1 Remap Address..
+
+config STM32H5_ICACHE_REGION1_MSTSEL
+       int "ICACHE Region 1 Master Select (0 or 1)"
+       default 0
+       range 0 1
+       depends on STM32H5_ICACHE_REGION1
+       ---help---
+               Select ICACHE Region 1 Master 1 (0) or Master 2 (1).
+
+config STM32H5_ICACHE_REGION1_HBURST
+       int "ICACHE Region 1 Output Burst Type (0 = Wrap, 1 = Incr)"
+       default 0
+       range 0 1
+       depends on STM32H5_ICACHE_REGION1
+       ---help---
+               Select Wrap (0) or Increment (1) Output Burst Type.
+
+endmenu # Region 1 Configuration
+
+menu "Region 2 Configuration"
+       depends on STM32H5_ICACHE_REGION2 && STM32H5_HAVE_ICACHE_REMAP
+
+config STM32H5_ICACHE_REGION2_BADDR
+       hex "ICACHE Region 2 Base Address Bits [28:21]"
+       default 0
+       range 0 255
+       depends on STM32H5_ICACHE_REGION2
+       ---help---
+               Set bits [28:21] of the base address for ICACHE Region 2.
+
+config STM32H5_ICACHE_REGION2_RSIZE
+       int "ICACHE Region 2 Size"
+       default 1
+       range 1 7
+       depends on STM32H5_ICACHE_REGION2
+       ---help---
+               Set the size of Region 2.
+                1 = 2 Mbytes, 2 = 4 Mbytes, 3 = 8 Mbytes, 4 = 16 Mbytes,
+                5 = 2 Mbytes, 6 = 64 Mbytes, 7 = 128 Mbytes.
+
+config STM32H5_ICACHE_REGION2_REMAPADDR
+       hex "ICACHE Region 2 Remap Address Bits [31:21]"
+       default 0
+       range 0 2047
+       depends on STM32H5_ICACHE_REGION2
+       ---help---
+               Set bits [31:21] of ICACHE Region 2 Remap Address..
+
+config STM32H5_ICACHE_REGION2_MSTSEL
+       int "ICACHE Region 2 Master Select (0 or 1)"
+       default 0
+       range 0 1
+       depends on STM32H5_ICACHE_REGION2
+       ---help---
+               Select ICACHE Region 2 Master 1 (0) or Master 2 (1).
+
+config STM32H5_ICACHE_REGION2_HBURST
+       int "ICACHE Region 2 Output Burst Type (0 = Wrap, 1 = Incr)"
+       default 0
+       range 0 1
+       depends on STM32H5_ICACHE_REGION2
+       ---help---
+               Select Wrap (0) or Increment (1) Output Burst Type.
+
+endmenu # Region 2 Configuration
+
+menu "Region 3 Configuration"
+       depends on STM32H5_ICACHE_REGION3 && STM32H5_HAVE_ICACHE_REMAP
+
+config STM32H5_ICACHE_REGION3_BADDR
+       hex "ICACHE Region 3 Base Address Bits [28:21]"
+       default 0
+       range 0 255
+       depends on STM32H5_ICACHE_REGION3
+       ---help---
+               Set bits [28:21] of the base address for ICACHE Region 3.
+
+config STM32H5_ICACHE_REGION3_RSIZE
+       int "ICACHE Region 3 Size"
+       default 1
+       range 1 7
+       depends on STM32H5_ICACHE_REGION3
+       ---help---
+               Set the size of Region 3.
+                1 = 2 Mbytes, 2 = 4 Mbytes, 3 = 8 Mbytes, 4 = 16 Mbytes,
+                5 = 2 Mbytes, 6 = 64 Mbytes, 7 = 128 Mbytes.
+
+config STM32H5_ICACHE_REGION3_REMAPADDR
+       hex "ICACHE Region 3 Remap Address Bits [31:21]"
+       default 0
+       range 0 2047
+       depends on STM32H5_ICACHE_REGION3
+       ---help---
+               Set bits [31:21] of ICACHE Region 3 Remap Address..
+
+config STM32H5_ICACHE_REGION3_MSTSEL
+       int "ICACHE Region 3 Master Select (0 or 1)"
+       default 0
+       range 0 1
+       depends on STM32H5_ICACHE_REGION3
+       ---help---
+               Select ICACHE Region 3 Master 1 (0) or Master 2 (1).
+
+config STM32H5_ICACHE_REGION3_HBURST
+       int "ICACHE Region 3 Output Burst Type (0 = Wrap, 1 = Incr)"
+       default 0
+       range 0 1
+       depends on STM32H5_ICACHE_REGION3
+       ---help---
+               Select Wrap (0) or Increment (1) Output Burst Type.
+
+endmenu # Region 3 Configuration
+
+endmenu # ICACHE Region Configuration
+
+endmenu # ICACHE Configuration
+
 config STM32H5_DISABLE_IDLE_SLEEP_DURING_DEBUG
        bool "Disable IDLE Sleep (WFI) in debug mode"
        default n
diff --git a/arch/arm/src/stm32h5/Make.defs b/arch/arm/src/stm32h5/Make.defs
index 1d5586a993..e878d6cb64 100644
--- a/arch/arm/src/stm32h5/Make.defs
+++ b/arch/arm/src/stm32h5/Make.defs
@@ -56,6 +56,10 @@ ifeq ($(STM32H5_FDCAN_CHARDRIVER),y)
 CHIP_CSRCS += stm32_fdcan.c
 endif
 
+ifeq ($(CONFIG_STM32H5_ICACHE),y)
+CHIP_CSRCS += stm32_icache.c
+endif
+
 ifeq ($(CONFIG_STM32H5_SPI),y)
 CHIP_CSRCS += stm32_spi.c
 endif
diff --git a/arch/arm/src/stm32h5/hardware/stm32_icache.h 
b/arch/arm/src/stm32h5/hardware/stm32_icache.h
new file mode 100644
index 0000000000..eb7efc39ca
--- /dev/null
+++ b/arch/arm/src/stm32h5/hardware/stm32_icache.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+ * arch/arm/src/stm32h5/hardware/stm32_icache.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_STM32H5_HARDWARE_STM32_ICACHE_H
+#define __ARCH_ARM_SRC_STM32H5_HARDWARE_STM32_ICACHE_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include "chip.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Register Offsets *********************************************************/
+
+#define STM32_ICACHE_CR_OFFSET        0x00             /* ICACHE Control 
Register Offset */
+#define STM32_ICACHE_SR_OFFSET        0x04             /* ICACHE Status 
Register Offset */
+#define STM32_ICACHE_IER_OFFSET       0x08             /* ICACHE Interrupt 
Enable Register Offset */
+#define STM32_ICACHE_FCR_OFFSET       0x0c             /* ICACHE Flag Clear 
Register Offset */
+#define STM32_ICACHE_HMONR_OFFSET     0x10             /* ICACHE Hit Monitor 
Register Offset */
+#define STM32_ICACHE_MMONR_OFFSET     0x14             /* ICACHE Miss Monitor 
Register Offset */
+#define STM32_ICACHE_CRR_OFFSET(x)   (0x20 + (x << 3)) /* ICACHE Region 
Configuration Register Offset */
+
+/* Register Addresses *******************************************************/
+
+#define STM32_ICACHE_CR              (STM32_ICACHE_BASE + 
STM32_ICACHE_CR_OFFSET)     /* ICACHE Control Register */
+#define STM32_ICACHE_SR              (STM32_ICACHE_BASE + 
STM32_ICACHE_SR_OFFSET)     /* ICACHE Status Register */
+#define STM32_ICACHE_IER             (STM32_ICACHE_BASE + 
STM32_ICACHE_IER_OFFSET)    /* ICACHE Interrupt Enable Register */
+#define STM32_ICACHE_FCR             (STM32_ICACHE_BASE + 
STM32_ICACHE_FCR_OFFSET)    /* ICACHE Flag Clear Register */
+#define STM32_ICACHE_HMONR           (STM32_ICACHE_BASE + 
STM32_ICACHE_HMONR_OFFSET)  /* ICACHE Hit Monitor Register */
+#define STM32_ICACHE_MMONR           (STM32_ICACHE_BASE + 
STM32_ICACHE_MMONR_OFFSET)  /* ICACHE Miss Monitor Register */
+#define STM32_ICACHE_CRR(x)          (STM32_ICACHE_BASE + 
STM32_ICACHE_CRR_OFFSET(x)) /* ICACHE Region Configuration Register */
+
+/* Register Bitfield Definitions ********************************************/
+
+/* Control Register */
+
+#define ICACHE_CR_EN                 (1 << 0)  /* Enable */
+#define ICACHE_CR_CACHEINV           (1 << 1)  /* Cache Invalidate */
+#define ICACHE_CR_WAYSEL             (1 << 2)  /* Associativity Mode Selection 
*/
+#define ICACHE_CR_HITMEN             (1 << 16) /* Hit Monitor Enable */
+#define ICACHE_CR_MISSMEN            (1 << 17) /* Miss Monitor Enable */
+#define ICACHE_CR_HITMRST            (1 << 18) /* Hit Monitor Reset */
+#define ICACHE_CR_MISSMRST           (1 << 19) /* Miss Monitor Reset */
+
+/* Status Register */
+
+#define ICACHE_SR_BUSYF              (1 << 0) /* Full Invalidate Busy Flag */
+#define ICACHE_SR_BSYENDF            (1 << 1) /* Full Invalidate FInished Flag 
*/
+#define ICACHE_SR_ERRF               (1 << 2) /* Cache Error Flag */
+
+/* Interrupt Enable Register */
+
+#define ICACHE_IER_BSYENDIE          (1 << 1) /* Full Invalidate Finished 
Interrupt Enable */
+#define ICACHE_IER_ERRIE             (1 << 2) /* Cache Error Interrupt Enable 
*/
+
+#define ICACHE_IER_ALLINTS           (ICACHE_IER_BSYENDIE | ICACHE_IER_ERRIE) 
/* All Cache Interrupts Mask */
+
+/* Flag Clear Register */
+
+#define ICACHE_FCR_CBSYENDF          (1 << 1) /* Clear Full Invalidate 
Finished Flag */
+#define ICACHE_FCR_CERRF             (1 << 2) /* Clear Cache Error Flag */
+
+/* Hit Monitor Register */
+
+/* Miss Monitor Register */
+
+#define ICACHE_MMONR_MISSMON_MASK    (0xffff) /* 16-bit Miss Monitor Mask */
+
+/* Region x Configuration Register */
+
+#define ICACHE_CRR_BASEADDR_SHIFT    (0) /* Base Address for Region x */
+#define ICACHE_CRR_BASEADDR_MASK     (0xff << ICACHE_CRR_BASEADDR_SHIFT)
+#define ICACHE_CRR_RSIZE_SHIFT       (9) /* Size for Region x (n=1..7, 
2^(11+n)) */
+#define ICACHE_CRR_RSIZE_MASK        (0x7 << ICACHE_CRR_RSIZE_SHIFT)
+#define ICACHE_CRR_REN               (1 << 15)
+#define ICACHE_CRR_REMAPADDR_SHIFT   (16) /* Remapped Address for Region x */
+#define ICACHE_CRR_REMAPADDR_MASK    (0x7ff << ICACHE_CRR_REMAPADDR_SHIFT)
+#define ICACHE_CRR_MSTSEL_SHIFT      (28) /* AHB Cache Master Selection for 
Region x */
+#define ICACHE_CRR_MSTSEL            (1 << ICACHE_CRR_MSTSEL_SHIFT)
+#define ICACHE_CRR_HBURST_SHIFT      (31) /* Output Burst Type for Region x 
(0=Wrap, 1=INCR) */
+#define ICACHE_CRR_HBURST            (1 << ICACHE_CRR_HBURST_SHIFT)
+
+#endif /* __ARCH_ARM_SRC_STM32H5_HARDWARE_STM32_ICACHE_H */
diff --git a/arch/arm/src/stm32h5/stm32.h b/arch/arm/src/stm32h5/stm32.h
index 172499e725..502f8420c7 100644
--- a/arch/arm/src/stm32h5/stm32.h
+++ b/arch/arm/src/stm32h5/stm32.h
@@ -37,15 +37,16 @@
 /* Peripherals **************************************************************/
 
 #include "chip.h"
-#include "stm32_flash.h"
+#include "stm32_adc.h"
 #include "stm32_dbgmcu.h"
+#include "stm32_flash.h"
 #include "stm32_gpio.h"
+#include "stm32_i2c.h"
+#include "stm32_icache.h"
+#include "stm32_lowputc.h"
 #include "stm32_pwr.h"
 #include "stm32_rcc.h"
 #include "stm32_uart.h"
-#include "stm32_lowputc.h"
-#include "stm32_i2c.h"
-#include "stm32_adc.h"
 #include "stm32_usbfs.h"
 
 #endif /* __ARCH_ARM_SRC_STM32H5_STM32_H */
diff --git a/arch/arm/src/stm32h5/stm32_icache.c 
b/arch/arm/src/stm32h5/stm32_icache.c
new file mode 100644
index 0000000000..8cd9c0483e
--- /dev/null
+++ b/arch/arm/src/stm32h5/stm32_icache.c
@@ -0,0 +1,366 @@
+/****************************************************************************
+ * arch/arm/src/stm32h5/stm32_icache.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 <nuttx/config.h>
+#include <nuttx/arch.h>
+#include <nuttx/spinlock.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "arm_internal.h"
+#include "stm32.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define STM32H5_ICACHE_INTERRUPT  (defined(CONFIG_STM32H5_ICACHE_INV_INT) ||\
+                                   defined(CONFIG_STM32H5_ICACHE_ERR_INT))
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct stm32_icache_s
+{
+  uint32_t          ier;        /* Saved interrupt mask bits value */
+
+  /* Has been initialized and HW is setup. */
+
+  bool              initialized;
+
+  volatile uint32_t invalidate;
+  volatile uint32_t invalidate_finished;
+  spinlock_t        lock;
+};
+
+struct stm32_icache_region
+{
+  uint8_t  num;
+  uint8_t  baseaddr;
+  uint8_t  rsize;
+  uint16_t remapaddr;
+  uint8_t  mstsel;
+  uint8_t  hburst;
+};
+
+/****************************************************************************
+ * Private Variables
+ ****************************************************************************/
+
+static struct stm32_icache_s icache1 =
+{
+  .ier                 = 0x0,
+  .initialized         = false,
+  .invalidate_finished = 0,
+  .lock                = SP_UNLOCKED,
+};
+
+#ifdef CONFIG_STM32H5_ICACHE_REGION0
+static struct stm32_icache_region region0 =
+{
+  .num = 0,
+  .baseaddr = CONFIG_STM32H5_ICACHE_REGION0_BADDR,
+  .rsize = CONFIG_STM32H5_ICACHE_REGION0_RSIZE,
+  .remapaddr = CONFIG_STM32H5_ICACHE_REGION0_REMAPADDR,
+  .mstsel = CONFIG_STM32H5_ICACHE_REGION0_MSTSEL,
+  .hburst = CONFIG_STM32H5_ICACHE_REGION0_HBURST,
+};
+#endif
+
+#ifdef CONFIG_STM32H5_ICACHE_REGION1
+static struct stm32_icache_region region1 =
+{
+  .num = 1,
+  .baseaddr = CONFIG_STM32H5_ICACHE_REGION1_BADDR,
+  .rsize = CONFIG_STM32H5_ICACHE_REGION1_RSIZE,
+  .remapaddr = CONFIG_STM32H5_ICACHE_REGION1_REMAPADDR,
+  .mstsel = CONFIG_STM32H5_ICACHE_REGION1_MSTSEL,
+  .hburst = CONFIG_STM32H5_ICACHE_REGION1_HBURST,
+};
+#endif
+
+#ifdef CONFIG_STM32H5_ICACHE_REGION2
+static struct stm32_icache_region region2 =
+{
+  .num = 2,
+  .baseaddr = CONFIG_STM32H5_ICACHE_REGION2_BADDR,
+  .rsize = CONFIG_STM32H5_ICACHE_REGION2_RSIZE,
+  .remapaddr = CONFIG_STM32H5_ICACHE_REGION2_REMAPADDR,
+  .mstsel = CONFIG_STM32H5_ICACHE_REGION2_MSTSEL,
+  .hburst = CONFIG_STM32H5_ICACHE_REGION2_HBURST,
+};
+#endif
+
+#ifdef CONFIG_STM32H5_ICACHE_REGION3
+static struct stm32_icache_region region3 =
+{
+  .num = 3,
+  .baseaddr = CONFIG_STM32H5_ICACHE_REGION3_BADDR,
+  .rsize = CONFIG_STM32H5_ICACHE_REGION3_RSIZE,
+  .remapaddr = CONFIG_STM32H5_ICACHE_REGION3_REMAPADDR,
+  .mstsel = CONFIG_STM32H5_ICACHE_REGION3_MSTSEL,
+  .hburst = CONFIG_STM32H5_ICACHE_REGION3_HBURST,
+};
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static inline void stm32_icache_interrupt(int irq, void *context, void *arg)
+{
+  uint32_t sr = getreg32(STM32_ICACHE_SR);
+
+  if ((icache1.ier & ICACHE_IER_BSYENDIE) && (sr & ICACHE_SR_BSYENDF))
+    {
+      putreg32(ICACHE_FCR_CBSYENDF, STM32_ICACHE_FCR);
+      icache1.invalidate_finished = true;
+    }
+
+  if ((icache1.ier & ICACHE_IER_ERRIE) && (sr & ICACHE_SR_ERRF))
+    {
+      /* Clear Error Flag */
+
+      putreg32(ICACHE_FCR_CERRF, STM32_ICACHE_FCR);
+    }
+}
+
+static inline void stm32_icache_invf_poll(void)
+{
+  while (!(getreg32(STM32_ICACHE_SR) & ICACHE_SR_BSYENDF))
+    {
+    }
+
+  putreg32(ICACHE_FCR_CBSYENDF, STM32_ICACHE_FCR);
+  icache1.invalidate_finished = true;
+}
+
+static inline void stm32_icache_invf_interrupt(void)
+{
+  while (!(icache1.invalidate_finished))
+    {
+    }
+
+  /* Report invalidate is finished */
+}
+
+static inline void stm32_icache_set_ier(uint32_t ier)
+{
+  icache1.ier = ier & ICACHE_IER_ALLINTS;
+  putreg32(icache1.ier, STM32_ICACHE_IER);
+}
+
+static inline void stm32_icache_reset_hmon(void)
+{
+  uint32_t regval;
+  regval = getreg32(STM32_ICACHE_CR);
+  regval |= ICACHE_CR_HITMRST;
+  putreg32(regval, STM32_ICACHE_CR);
+  regval &= ~(ICACHE_CR_HITMRST);
+  putreg32(regval, STM32_ICACHE_CR);
+}
+
+static inline void stm32_icache_reset_mmon(void)
+{
+  uint32_t regval;
+  regval = getreg32(STM32_ICACHE_CR);
+  regval |= ICACHE_CR_MISSMRST;
+  putreg32(regval, STM32_ICACHE_CR);
+  regval &= ~(ICACHE_CR_MISSMRST);
+  putreg32(regval, STM32_ICACHE_CR);
+}
+
+static inline void stm32_icache_enable_monitors(void)
+{
+  uint32_t regval;
+  regval = getreg32(STM32_ICACHE_CR);
+  regval |= (ICACHE_CR_MISSMEN | ICACHE_CR_HITMEN);
+  putreg32(regval, STM32_ICACHE_CR);
+}
+
+static inline void stm32_icache_disable_monitors(void)
+{
+  uint32_t regval;
+  regval = getreg32(STM32_ICACHE_CR);
+  regval &= ~(ICACHE_CR_MISSMEN | ICACHE_CR_HITMEN);
+  putreg32(regval, STM32_ICACHE_CR);
+}
+
+static void stm32_icache_setup_region(struct stm32_icache_region region)
+{
+  uint32_t regval = 0;
+
+  regval |= (region.baseaddr << ICACHE_CRR_BASEADDR_SHIFT);
+  regval |= ((region.rsize << ICACHE_CRR_RSIZE_SHIFT) & \
+             ICACHE_CRR_RSIZE_MASK);
+  regval |= ICACHE_CRR_REN;
+  regval |= ((region.remapaddr << ICACHE_CRR_REMAPADDR_SHIFT) & \
+             ICACHE_CRR_REMAPADDR_MASK);
+  regval |= (region.mstsel << ICACHE_CRR_MSTSEL_SHIFT);
+  regval |= (region.hburst << ICACHE_CRR_HBURST_SHIFT);
+
+  putreg32(regval, STM32_ICACHE_CRR(region.num));
+}
+
+void stm32_icache_initialize(void)
+{
+  uint32_t regval;
+
+  /* Set associativity */
+
+#ifdef CONFIG_STM32H5_ICACHE_DIRECT
+  regval = getreg32(STM32_ICACHE_CR);
+  regval &= ~(ICACHE_CR_WAYSEL);
+  putreg32(regval, STM32_ICACHE_CR);
+#endif
+
+/* Enable Hit/Miss Monitors
+ * Use CONFIG options to Enable Hit/Miss
+ * Reset Monitors on Initialization
+ */
+
+#ifdef CONFIG_STM32H5_ICACHE_MONITOR_EN
+  stm32_icache_enable_monitors();
+  stm32_icache_reset_monitors();
+#endif
+
+  /* Set up region configuration registers */
+
+#ifdef CONFIG_STM32H5_ICACHE_REGION0
+  stm32_icache_setup_region(region0);
+#endif
+#ifdef CONFIG_STM32H5_ICACHE_REGION1
+  stm32_icache_setup_region(region1);
+#endif
+#ifdef CONFIG_STM32H5_ICACHE_REGION2
+  stm32_icache_setup_region(region2);
+#endif
+#ifdef CONFIG_STM32H5_ICACHE_REGION3
+  stm32_icache_setup_region(region3);
+#endif
+
+#if STM32H5_ICACHE_INTERRUPT 
+  /* Attach ISR */
+
+  int ret;
+
+  ret = irq_attach(STM32_IRQ_ICACHE, (xcpt_t) stm32_icache_interrupt, NULL);
+
+  /* Enable Interrupts */
+
+  if (ret == OK)
+    {
+      regval = 0;
+#  ifdef CONFIG_STM32H5_ICACHE_INV_INT
+      regval |= ICACHE_IER_BSYENDIE;
+#  endif
+#  ifdef CONFIG_STM32H5_ICACHE_ERR_INT
+      regval |= ICACHE_IER_ERRIE;
+#  endif
+      stm32_icache_set_ier(regval);
+
+      up_enable_irq(STM32_IRQ_ICACHE);
+    }
+#endif
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+void stm32_icache_reset_monitors(void)
+{
+  uint32_t regval;
+  regval = getreg32(STM32_ICACHE_CR);
+  regval |= (ICACHE_CR_MISSMRST | ICACHE_CR_HITMRST);
+  putreg32(regval, STM32_ICACHE_CR);
+  regval &= ~(ICACHE_CR_MISSMRST | ICACHE_CR_HITMRST);
+  putreg32(regval, STM32_ICACHE_CR);
+}
+
+size_t stm32_get_icache_linesize(void)
+{
+  return 16;
+}
+
+size_t stm32_get_icache_size(void)
+{
+  return 8192;
+}
+
+void stm32_disable_icache(void)
+{
+  uint32_t regval;
+  regval = getreg32(STM32_ICACHE_CR);
+  regval &= ~(ICACHE_CR_EN);
+  putreg32(regval, STM32_ICACHE_CR);
+}
+
+void stm32_enable_icache(void)
+{
+  uint32_t regval;
+
+  if (icache1.initialized != true)
+    {
+      stm32_icache_initialize();
+      icache1.initialized = true;
+    }
+
+  /* Enable the ICACHE */
+
+  regval = getreg32(STM32_ICACHE_CR);
+  regval |= ICACHE_CR_EN;
+  putreg32(regval, STM32_ICACHE_CR);
+}
+
+void stm32_invalidate_icache(void)
+{
+  uint32_t regval;
+
+  /* Preemptively clear BSYENDF */
+
+  putreg32(ICACHE_FCR_CBSYENDF, STM32_ICACHE_FCR);
+
+  /* Set invalidate finished to false */
+
+  icache1.invalidate_finished = false;
+
+  /* Start the icache invalidate process */
+
+  regval = getreg32(STM32_ICACHE_CR);
+  regval |= ICACHE_CR_CACHEINV;
+  putreg32(regval, STM32_ICACHE_CR);
+
+#if defined(CONFIG_STM32H5_ICACHE_INV_INT)
+  stm32_icache_invf_interrupt();
+#else
+  stm32_icache_invf_poll();
+#endif
+}
diff --git a/arch/arm/src/stm32h5/stm32_icache.h 
b/arch/arm/src/stm32h5/stm32_icache.h
new file mode 100644
index 0000000000..13684c4f26
--- /dev/null
+++ b/arch/arm/src/stm32h5/stm32_icache.h
@@ -0,0 +1,158 @@
+/****************************************************************************
+ * arch/arm/src/stm32h5/stm32_icache.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_STM32H5_STM32_ICACHE_H
+#define __ARCH_ARM_SRC_STM32H5_STM32_ICACHE_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdbool.h>
+
+#include "chip.h"
+#include "hardware/stm32_icache.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_get_icache_linesize
+ *
+ * Description:
+ *   Returns the icache linesize.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   16
+ *
+ ****************************************************************************/
+
+size_t stm32_get_icache_linesize(void);
+
+/****************************************************************************
+ * Name: stm32_get_icache_size
+ *
+ * Description:
+ *   Returns the icache size.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   8192
+ *
+ ****************************************************************************/
+
+size_t stm32_get_icache_size(void);
+
+/****************************************************************************
+ * Name: stm32_enable_icache
+ *
+ * Description:
+ *   Initializes the STM32H5 ICACHE
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void stm32_enable_icache(void);
+
+/****************************************************************************
+ * Name: stm32_disable_icache
+ *
+ * Description:
+ *   Disables the STM32H5 ICACHE.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void stm32_disable_icache(void);
+
+/****************************************************************************
+ * Name: stm32_reset_monitors
+ *
+ * Description:
+ *   Reset the ICACHE Hit and Miss Counters
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void stm32_icache_reset_monitors(void);
+
+/****************************************************************************
+ * Name: stm32_invalidate_icache
+ *
+ * Description:
+ *   Invalidate the icache and wait for its completion.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void stm32_invalidate_icache(void);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_ARM_SRC_STM32H5_STM32_ICACHE_H */
diff --git a/arch/arm/src/stm32h5/stm32_start.c 
b/arch/arm/src/stm32h5/stm32_start.c
index 348004f1c2..b50837ec8c 100644
--- a/arch/arm/src/stm32h5/stm32_start.c
+++ b/arch/arm/src/stm32h5/stm32_start.c
@@ -229,6 +229,11 @@ void __start(void)
   stm32_board_initialize();
   showprogress('F');
 
+#ifdef CONFIG_STM32H5_ICACHE
+  stm32_enable_icache();
+#endif
+  showprogress('G');
+
   /* Then start NuttX */
 
   showprogress('\r');

Reply via email to