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');