You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ac...@apache.org on 2020/02/29 15:33:58 UTC
[incubator-nuttx] branch master updated: Improvements to STM32H7:
(i, w)WDG Flash, Ethernet, ADC, etc
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/incubator-nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new 0ce4e15 Improvements to STM32H7: (i,w)WDG Flash, Ethernet, ADC, etc
0ce4e15 is described below
commit 0ce4e15363f8e3185d5878b91338eebaf2c8939b
Author: Joshua Lange <jl...@2g-eng.com>
AuthorDate: Sat Feb 29 12:33:25 2020 -0300
Improvements to STM32H7: (i,w)WDG Flash, Ethernet, ADC, etc
---
arch/arm/src/stm32h7/Kconfig | 10 +
arch/arm/src/stm32h7/Make.defs | 15 +
arch/arm/src/stm32h7/hardware/stm32_wdg.h | 158 ++++
arch/arm/src/stm32h7/hardware/stm32h7x3xx_flash.h | 16 +-
arch/arm/src/stm32h7/hardware/stm32h7x3xx_pwr.h | 254 ++++---
arch/arm/src/stm32h7/hardware/stm32h7x3xx_rcc.h | 20 +-
arch/arm/src/stm32h7/stm32_adc.c | 136 +++-
arch/arm/src/stm32h7/stm32_ethernet.c | 73 +-
arch/arm/src/stm32h7/stm32_ethernet.h | 6 +-
arch/arm/src/stm32h7/stm32_flash.c | 201 +++++-
.../stm32h7/{stm32_ethernet.h => stm32_flash.h} | 73 +-
arch/arm/src/stm32h7/stm32_iwdg.c | 706 ++++++++++++++++++
.../src/stm32h7/{stm32_ethernet.h => stm32_pm.h} | 91 +--
.../{stm32_ethernet.h => stm32_pminitialize.c} | 83 +--
.../stm32h7/{stm32_ethernet.h => stm32_pmsleep.c} | 108 ++-
.../{stm32_ethernet.h => stm32_pmstandby.c} | 105 ++-
.../stm32h7/{stm32_ethernet.h => stm32_pmstop.c} | 130 ++--
arch/arm/src/stm32h7/stm32_pwr.c | 130 +++-
arch/arm/src/stm32h7/stm32_pwr.h | 56 +-
.../src/stm32h7/{stm32_ethernet.h => stm32_wdg.h} | 76 +-
arch/arm/src/stm32h7/stm32_wwdg.c | 803 +++++++++++++++++++++
arch/arm/src/stm32h7/stm32h7x3xx_rcc.c | 22 +-
22 files changed, 2682 insertions(+), 590 deletions(-)
diff --git a/arch/arm/src/stm32h7/Kconfig b/arch/arm/src/stm32h7/Kconfig
index 3c07db3..2b552ce 100644
--- a/arch/arm/src/stm32h7/Kconfig
+++ b/arch/arm/src/stm32h7/Kconfig
@@ -341,6 +341,16 @@ config STM32H7_SDMMC2
select ARCH_HAVE_SDIO_PREFLIGHT
select SDIO_BLOCKSETUP
+config STM32H7_IWDG
+ bool "IWDG"
+ default n
+ select WATCHDOG
+
+config STM32H7_WWDG
+ bool "WWDG"
+ default n
+ select WATCHDOG
+
menu "STM32H7 I2C Selection"
config STM32H7_I2C1
diff --git a/arch/arm/src/stm32h7/Make.defs b/arch/arm/src/stm32h7/Make.defs
index 965f38a..4a63041 100644
--- a/arch/arm/src/stm32h7/Make.defs
+++ b/arch/arm/src/stm32h7/Make.defs
@@ -210,3 +210,18 @@ endif
ifeq ($(CONFIG_SENSORS_QENCODER),y)
CHIP_CSRCS += stm32_qencoder.c
endif
+
+ifeq ($(CONFIG_PM),y)
+CHIP_CSRCS += stm32_pmsleep.c stm32_pmstandby.c stm32_pmstop.c
+ifneq ($(CONFIG_ARCH_CUSTOM_PMINIT),y)
+CHIP_CSRCS += stm32_pminitialize.c
+endif
+endif
+
+ifeq ($(CONFIG_STM32H7_IWDG),y)
+CHIP_CSRCS += stm32_iwdg.c
+endif
+
+ifeq ($(CONFIG_STM32H7_WWDG),y)
+CHIP_CSRCS += stm32_wwdg.c
+endif
diff --git a/arch/arm/src/stm32h7/hardware/stm32_wdg.h b/arch/arm/src/stm32h7/hardware/stm32_wdg.h
new file mode 100644
index 0000000..7004b60
--- /dev/null
+++ b/arch/arm/src/stm32h7/hardware/stm32_wdg.h
@@ -0,0 +1,158 @@
+/************************************************************************************
+ * arch/arm/src/stm32h7/hardware/stm32_wdg.h
+ *
+ * Copyright (C) 2009, 2011-2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gn...@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_STM32_HARDWARE_STM32H7_WDG_H
+#define __ARCH_ARM_SRC_STM32_HARDWARE_STM32H7_WDG_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "chip.h"
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* Register Offsets *****************************************************************/
+
+#define STM32_IWDG_KR_OFFSET 0x0000 /* Key register (32-bit) */
+#define STM32_IWDG_PR_OFFSET 0x0004 /* Prescaler register (32-bit) */
+#define STM32_IWDG_RLR_OFFSET 0x0008 /* Reload register (32-bit) */
+#define STM32_IWDG_SR_OFFSET 0x000c /* Status register (32-bit) */
+#define STM32_IWDG_WINR_OFFSET 0x000c /* Window register (32-bit) */
+
+#define STM32_WWDG_CR_OFFSET 0x0000 /* Control Register (32-bit) */
+#define STM32_WWDG_CFR_OFFSET 0x0004 /* Configuration register (32-bit) */
+#define STM32_WWDG_SR_OFFSET 0x0008 /* Status register (32-bit) */
+
+/* Register Addresses ***************************************************************/
+
+#define STM32_IWDG_KR (STM32_IWDG1_BASE+STM32_IWDG_KR_OFFSET)
+#define STM32_IWDG_PR (STM32_IWDG1_BASE+STM32_IWDG_PR_OFFSET)
+#define STM32_IWDG_RLR (STM32_IWDG1_BASE+STM32_IWDG_RLR_OFFSET)
+#define STM32_IWDG_SR (STM32_IWDG1_BASE+STM32_IWDG_SR_OFFSET)
+#define STM32_IWDG_WINR (STM32_IWDG1_BASE+STM32_IWDG_WINR_OFFSET)
+
+#define STM32_WWDG_CR (STM32_WWDG1_BASE+STM32_WWDG_CR_OFFSET)
+#define STM32_WWDG_CFR (STM32_WWDG1_BASE+STM32_WWDG_CFR_OFFSET)
+#define STM32_WWDG_SR (STM32_WWDG1_BASE+STM32_WWDG_SR_OFFSET)
+
+/* Register Bitfield Definitions ****************************************************/
+
+/* Key register (32-bit) */
+
+#define IWDG_KR_KEY_SHIFT (0) /* Bits 15-0: Key value (write only, read 0000h) */
+#define IWDG_KR_KEY_MASK (0xffff << IWDG_KR_KEY_SHIFT)
+
+#define IWDG_KR_KEY_ENABLE (0x5555) /* Enable register access */
+#define IWDG_KR_KEY_DISABLE (0x0000) /* Disable register access */
+#define IWDG_KR_KEY_RELOAD (0xaaaa) /* Reload the counter */
+#define IWDG_KR_KEY_START (0xcccc) /* Start the watchdog */
+
+/* Prescaler register (32-bit) */
+
+#define IWDG_PR_SHIFT (0) /* Bits 2-0: Prescaler divider */
+#define IWDG_PR_MASK (7 << IWDG_PR_SHIFT)
+# define IWDG_PR_DIV4 (0 << IWDG_PR_SHIFT) /* 000: divider /4 */
+# define IWDG_PR_DIV8 (1 << IWDG_PR_SHIFT) /* 001: divider /8 */
+# define IWDG_PR_DIV16 (2 << IWDG_PR_SHIFT) /* 010: divider /16 */
+# define IWDG_PR_DIV32 (3 << IWDG_PR_SHIFT) /* 011: divider /32 */
+# define IWDG_PR_DIV64 (4 << IWDG_PR_SHIFT) /* 100: divider /64 */
+# define IWDG_PR_DIV128 (5 << IWDG_PR_SHIFT) /* 101: divider /128 */
+# define IWDG_PR_DIV256 (6 << IWDG_PR_SHIFT) /* 11x: divider /256 */
+
+/* Reload register (32-bit) */
+
+#define IWDG_RLR_RL_SHIFT (0) /* Bits11:0 RL[11:0]: Watchdog counter reload value */
+#define IWDG_RLR_RL_MASK (0x0fff << IWDG_RLR_RL_SHIFT)
+
+#define IWDG_RLR_MAX (0xfff)
+
+/* Status register (32-bit) */
+
+#define IWDG_SR_PVU (1 << 0) /* Bit 0: Watchdog prescaler value update */
+#define IWDG_SR_RVU (1 << 1) /* Bit 1: Watchdog counter reload value update */
+
+#if defined(CONFIG_STM32_STM32F30XX)
+# define IWDG_SR_WVU (1 << 2) /* Bit 2: */
+#endif
+
+/* Window register (32-bit) */
+
+#if defined(CONFIG_STM32_STM32F30XX)
+# define IWDG_WINR_SHIFT (0)
+# define IWDG_WINR_MASK (0x0fff << IWDG_WINR_SHIFT)
+#endif
+
+/* Control Register (32-bit) */
+
+#define WWDG_CR_T_SHIFT (0) /* Bits 6:0 T[6:0]: 7-bit counter (MSB to LSB) */
+#define WWDG_CR_T_MASK (0x7f << WWDG_CR_T_SHIFT)
+# define WWDG_CR_T_MAX (0x3f << WWDG_CR_T_SHIFT)
+# define WWDG_CR_T_RESET (0x40 << WWDG_CR_T_SHIFT)
+#define WWDG_CR_WDGA (1 << 7) /* Bit 7: Activation bit */
+
+/* Configuration register (32-bit) */
+
+#define WWDG_CFR_W_SHIFT (0) /* Bits 6:0 W[6:0] 7-bit window value */
+#define WWDG_CFR_W_MASK (0x7f << WWDG_CFR_W_SHIFT)
+#define WWDG_CFR_WDGTB_SHIFT (7) /* Bits 8:7 [1:0]: Timer Base */
+#define WWDG_CFR_WDGTB_MASK (3 << WWDG_CFR_WDGTB_SHIFT)
+# define WWDG_CFR_PCLK1 (0 << WWDG_CFR_WDGTB_SHIFT) /* 00: CK Counter Clock (PCLK1 div 4096) div 1 */
+# define WWDG_CFR_PCLK1d2 (1 << WWDG_CFR_WDGTB_SHIFT) /* 01: CK Counter Clock (PCLK1 div 4096) div 2 */
+# define WWDG_CFR_PCLK1d4 (2 << WWDG_CFR_WDGTB_SHIFT) /* 10: CK Counter Clock (PCLK1 div 4096) div 4 */
+# define WWDG_CFR_PCLK1d8 (3 << WWDG_CFR_WDGTB_SHIFT) /* 11: CK Counter Clock (PCLK1 div 4096) div 8 */
+#define WWDG_CFR_EWI (1 << 9) /* Bit 9: Early Wakeup Interrupt */
+
+/* Status register (32-bit) */
+
+#define WWDG_SR_EWIF (1 << 0) /* Bit 0: Early Wakeup Interrupt Flag */
+
+/************************************************************************************
+ * Public Types
+ ************************************************************************************/
+
+/************************************************************************************
+ * Public Data
+ ************************************************************************************/
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+#endif /* __ARCH_ARM_SRC_STM32_HARDWARE_STM32H7_WDG_H */
diff --git a/arch/arm/src/stm32h7/hardware/stm32h7x3xx_flash.h b/arch/arm/src/stm32h7/hardware/stm32h7x3xx_flash.h
index 3de570d..aa29308 100644
--- a/arch/arm/src/stm32h7/hardware/stm32h7x3xx_flash.h
+++ b/arch/arm/src/stm32h7/hardware/stm32h7x3xx_flash.h
@@ -1,4 +1,4 @@
-/******************************************************************************
+/****************************************************************************
* arch/arm/src/stm32h7/hardware/stm32h7x3xx_flash.h
*
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
@@ -31,16 +31,16 @@
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
- *****************************************************************************/
+ ****************************************************************************/
#ifndef __ARCH_ARM_SRC_STM32H7_HARDWARE_STM32H7X3XX_FLASH_H
#define __ARCH_ARM_SRC_STM32H7_HARDWARE_STM32H7X3XX_FLASH_H
-/******************************************************************************
+/****************************************************************************
* Pre-processor Definitions
- *****************************************************************************/
+ ****************************************************************************/
-/* Register Offsets *****************************************************************/
+/* Register Offsets *********************************************************/
#define STM32_FLASH_ACR_OFFSET 0x0000 /* Access control register */
#define STM32_FLASH_KEYR1_OFFSET 0x0004 /* Key register for bank 1 */
@@ -84,7 +84,7 @@
#define STM32_FLASH_BANK1_OFFSET 0x0000 /* Bank 1 registers offset */
#define STM32_FLASH_BANK2_OFFSET 0x0100 /* Bank 2 registers offset */
-/* Register Addresses ***************************************************************/
+/* Register Addresses *******************************************************/
#define STM32_FLASH_ACR (STM32_FLASHIF_BASE + STM32_FLASH_ACR_OFFSET)
#define STM32_FLASH_KEYR1 (STM32_FLASHIF_BASE + STM32_FLASH_KEYR1_OFFSET)
@@ -125,7 +125,7 @@
#define STM32_FLASH_CRCEADD2R (STM32_FLASHIF_BASE + STM32_FLASH_CRCEADD2R_OFFSET)
#define STM32_FLASH_ECC_FA2R (STM32_FLASHIF_BASE + STM32_FLASH_ECC_FA2R_OFFSET)
-/* Register Bitfield Definitions ****************************************************/
+/* Register Bitfield Definitions ********************************************/
/* Flash Access Control Register (ACR) Bank 1 or 2 */
@@ -168,7 +168,7 @@
#define FLASH_CR_START (1 << 7) /* Bit 7: Erase start */
#define FLASH_CR_SNB_SHIFT (8) /* Bits 8-10: Sector number */
#define FLASH_CR_SNB_MASK (15 << FLASH_CR_SNB_SHIFT) /* Used to clear FLASH_CR_SNB bits */
-# define FLASH_CR_SNB(n) ((uint32_t)(n & 0x7) << FLASH_CR_SNB_SHIFT) /* Sector n, n=0..7 */
+# define FLASH_CR_SNB(n) ((uint32_t)((n) & 0x7) << FLASH_CR_SNB_SHIFT) /* Sector n, n=0..7 */
/* Bits 11-13: Reserved */
#define FLASH_CR_SPSS2 (1 << 14) /* Bit 14: Bank1 Reserved, Bank 2 special sector selection bit */
#define FLASH_CR_CRCEN (1 << 15) /* Bit 15: CRC control enable */
diff --git a/arch/arm/src/stm32h7/hardware/stm32h7x3xx_pwr.h b/arch/arm/src/stm32h7/hardware/stm32h7x3xx_pwr.h
index 693c0be..13509ef 100644
--- a/arch/arm/src/stm32h7/hardware/stm32h7x3xx_pwr.h
+++ b/arch/arm/src/stm32h7/hardware/stm32h7x3xx_pwr.h
@@ -43,129 +43,185 @@
/* Register Offsets *****************************************************************/
-#define STM32_PWR_CR1_OFFSET 0x0000 /* Power control register 1 */
-#define STM32_PWR_CSR1_OFFSET 0x0004 /* Power control/status register 1 */
-#define STM32_PWR_CR2_OFFSET 0x0008 /* Power control register 2 */
-#define STM32_PWR_CR3_OFFSET 0x000c /* Power control register 3 */
-#define STM32_PWR_CPUCR_OFFSET 0x0010 /* Power CPU control register */
- /* 0x014: Reserved */
-#define STM32_PWR_D3CR_OFFSET 0x0018 /* Power D3 domain control register */
-#define STM32_PWR_WKUPCR_OFFSET 0x0020 /* Power wakeup clear register */
-#define STM32_PWR_WKUPFR_OFFSET 0x0024 /* Power wakeup flag register */
-#define STM32_PWR_WKUPEPR_OFFSET 0x0028 /* Power wakeup enable and polarity register*/
- /* 0x030: Reserved */
+#define STM32_PWR_CR1_OFFSET 0x0000 /* Power control register 1 */
+#define STM32_PWR_CSR1_OFFSET 0x0004 /* Power control/status register 1 */
+#define STM32_PWR_CR2_OFFSET 0x0008 /* Power control register 2 */
+#define STM32_PWR_CR3_OFFSET 0x000c /* Power control register 3 */
+#define STM32_PWR_CPUCR_OFFSET 0x0010 /* Power CPU control register */
+ /* 0x014: Reserved */
+#define STM32_PWR_D3CR_OFFSET 0x0018 /* Power D3 domain control register */
+#define STM32_PWR_WKUPCR_OFFSET 0x0020 /* Power wakeup clear register */
+#define STM32_PWR_WKUPFR_OFFSET 0x0024 /* Power wakeup flag register */
+#define STM32_PWR_WKUPEPR_OFFSET 0x0028 /* Power wakeup enable and polarity register*/
+ /* 0x030: Reserved */
/* Register Addresses ***************************************************************/
-#define STM32_PWR_CR1 (STM32_PWR_BASE+STM32_PWR_CR1_OFFSET)
-#define STM32_PWR_CSR1 (STM32_PWR_BASE+STM32_PWR_CSR1_OFFSET)
-#define STM32_PWR_CR2 (STM32_PWR_BASE+STM32_PWR_CR2_OFFSET)
-#define STM32_PWR_CR3 (STM32_PWR_BASE+STM32_PWR_CR3_OFFSET)
-#define STM32_PWR_CPUCR (STM32_PWR_BASE+STM32_PWR_CPUCR_OFFSET)
-#define STM32_PWR_D3CR (STM32_PWR_BASE+STM32_PWR_D3CR_OFFSET)
-#define STM32_PWR_WKUPCR (STM32_PWR_BASE+STM32_PWR_WKUPCR_OFFSET)
-#define STM32_PWR_WKUPFR (STM32_PWR_BASE+STM32_PWR_WKUPFR_OFFSET)
-#define STM32_PWR_WKUPEOR (STM32_PWR_BASE+STM32_PWR_WKUPEOR_OFFSET)
+#define STM32_PWR_CR1 (STM32_PWR_BASE+STM32_PWR_CR1_OFFSET)
+#define STM32_PWR_CSR1 (STM32_PWR_BASE+STM32_PWR_CSR1_OFFSET)
+#define STM32_PWR_CR2 (STM32_PWR_BASE+STM32_PWR_CR2_OFFSET)
+#define STM32_PWR_CR3 (STM32_PWR_BASE+STM32_PWR_CR3_OFFSET)
+#define STM32_PWR_CPUCR (STM32_PWR_BASE+STM32_PWR_CPUCR_OFFSET)
+#define STM32_PWR_D3CR (STM32_PWR_BASE+STM32_PWR_D3CR_OFFSET)
+#define STM32_PWR_WKUPCR (STM32_PWR_BASE+STM32_PWR_WKUPCR_OFFSET)
+#define STM32_PWR_WKUPFR (STM32_PWR_BASE+STM32_PWR_WKUPFR_OFFSET)
+#define STM32_PWR_WKUPEOR (STM32_PWR_BASE+STM32_PWR_WKUPEOR_OFFSET)
/* Register Bitfield Definitions ****************************************************/
/* Power control register 1 (CR1) */
-#define PWR_CR1_LPDS (1 << 0) /* Bit 0: Low-power Deepsleep with SVOS3 */
- /* Bits 1-3: Reserved */
-#define PWR_CR1_PVDE (1 << 4) /* Bit 4: Programmable voltage detector enable */
-
-
-#define PWR_CR1_PLS_SHIFT (5) /* Bits 5-7: Programmable voltage detector level */
-#define PWR_CR1_PLS_MASK (7 << PWR_CR1_PLS_SHIFT)
-# define PWR_CR1_PLS_1V95 (0 << PWR_CR1_PLS_SHIFT) /* 000: */
-# define PWR_CR1_PLS_2V1 (1 << PWR_CR1_PLS_SHIFT) /* 001: */
-# define PWR_CR1_PLS_2V25 (2 << PWR_CR1_PLS_SHIFT) /* 010: */
-# define PWR_CR1_PLS_2V4 (3 << PWR_CR1_PLS_SHIFT) /* 011: */
-# define PWR_CR1_PLS_2V55 (4 << PWR_CR1_PLS_SHIFT) /* 100: */
-# define PWR_CR1_PLS_2V7 (5 << PWR_CR1_PLS_SHIFT) /* 101: */
-# define PWR_CR1_PLS_2V85 (6 << PWR_CR1_PLS_SHIFT) /* 110: */
-# define PWR_CR1_PLS_EXT (7 << PWR_CR1_PLS_SHIFT) /* 111: */
-#define PWR_CR1_DBP (1 << 8) /* Bit 8: Disable backup domain write protection */
-#define PWR_CR1_FLPS (1 << 9) /* Bit 9: */
- /* Bits 10-13: Reserved */
-#define PWR_CR1_SVOS_SHIFT (1 << 14) /* Bits 14-15: */
-#define PWR_CR1_SVOS_MASK (3 << PWR_CR1_SVOS_SHIFT)
- /* 00: Reserved */
-# define PWR_CR1_SVOS_S5 (1 << PWR_CR1_SVOS_SHIFT) /* 01: */
-# define PWR_CR1_SVOS_S4 (2 << PWR_CR1_SVOS_SHIFT) /* 10: */
-# define PWR_CR1_SVOS_S3 (3 << PWR_CR1_SVOS_SHIFT) /* 11: */
-#define PWR_CR1_AVDEN (1 << 16) /* Bit 16: */
-#define PWR_CR1_ALS_SHIFT (17) /* Bits 17-18: Analog voltage detector level selection */
-#define PWR_CR1_ALS_MASK (3 << PWR_CR1_ALS_SHIFT)
-# define PWR_CR1_ALS_1V7 (0 << PWR_CR1_ALS_SHIFT) /* 00: */
-# define PWR_CR1_ALS_2V1 (1 << PWR_CR1_ALS_SHIFT) /* 01 */
-# define PWR_CR1_ALS_2V5 (2 << PWR_CR1_ALS_SHIFT) /* 10: */
-# define PWR_CR1_ALS_2V8 (3 << PWR_CR1_ALS_SHIFT) /* 11: */
- /* Bits 19-31: Reserved */
-
-/* Power control/status register 1 (CRS1) */
-
+#define PWR_CR1_LPDS (1 << 0) /* Bit 0: Low-power Deepsleep with SVOS3 */
+ /* Bits 1-3: Reserved */
+#define PWR_CR1_PVDE (1 << 4) /* Bit 4: Programmable voltage detector enable */
+
+#define PWR_CR1_PLS_SHIFT (5) /* Bits 5-7: Programmable voltage detector level */
+#define PWR_CR1_PLS_MASK (7 << PWR_CR1_PLS_SHIFT)
+# define PWR_CR1_PLS_1V95 (0 << PWR_CR1_PLS_SHIFT) /* 000: */
+# define PWR_CR1_PLS_2V1 (1 << PWR_CR1_PLS_SHIFT) /* 001: */
+# define PWR_CR1_PLS_2V25 (2 << PWR_CR1_PLS_SHIFT) /* 010: */
+# define PWR_CR1_PLS_2V4 (3 << PWR_CR1_PLS_SHIFT) /* 011: */
+# define PWR_CR1_PLS_2V55 (4 << PWR_CR1_PLS_SHIFT) /* 100: */
+# define PWR_CR1_PLS_2V7 (5 << PWR_CR1_PLS_SHIFT) /* 101: */
+# define PWR_CR1_PLS_2V85 (6 << PWR_CR1_PLS_SHIFT) /* 110: */
+# define PWR_CR1_PLS_EXT (7 << PWR_CR1_PLS_SHIFT) /* 111: */
+#define PWR_CR1_DBP (1 << 8) /* Bit 8: Disable backup domain write protection */
+#define PWR_CR1_FLPS (1 << 9) /* Bit 9: */
+ /* Bits 10-13: Reserved */
+#define PWR_CR1_SVOS_SHIFT (14) /* Bits 14-15: */
+#define PWR_CR1_SVOS_MASK (3 << PWR_CR1_SVOS_SHIFT)
+ /* 00: Reserved */
+# define PWR_CR1_SVOS_S5 (1 << PWR_CR1_SVOS_SHIFT) /* 01: */
+# define PWR_CR1_SVOS_S4 (2 << PWR_CR1_SVOS_SHIFT) /* 10: */
+# define PWR_CR1_SVOS_S3 (3 << PWR_CR1_SVOS_SHIFT) /* 11: */
+#define PWR_CR1_AVDEN (1 << 16) /* Bit 16: */
+#define PWR_CR1_ALS_SHIFT (17) /* Bits 17-18: Analog voltage detector level selection */
+#define PWR_CR1_ALS_MASK (3 << PWR_CR1_ALS_SHIFT)
+# define PWR_CR1_ALS_1V7 (0 << PWR_CR1_ALS_SHIFT) /* 00: */
+# define PWR_CR1_ALS_2V1 (1 << PWR_CR1_ALS_SHIFT) /* 01 */
+# define PWR_CR1_ALS_2V5 (2 << PWR_CR1_ALS_SHIFT) /* 10: */
+# define PWR_CR1_ALS_2V8 (3 << PWR_CR1_ALS_SHIFT) /* 11: */
+ /* Bits 19-31: Reserved */
+
+/* Power control/status register 1 (CSR1) */
+
+ /* Bits 0-3: Reserved */
+#define PWR_CSR1_PVDO (1 << 4) /* Bit 4: Programmable voltage detect output*/
+ /* Bits 5-12: Reserved */
+#define PWR_CSR1_ACTVOSRDY (1 << 13) /* Bit 13: VOS voltage level ready */
+#define PWR_CSR1_ACTVOS_SHIFT (14) /* Bits 14-15: Current VOS applied */
+# define PWR_CSR1_VOS_SCALE_3R (0 << PWR_CSR1_ACTVOS_SHIFT)
+# define PWR_CSR1_VOS_SCALE_3 (1 << PWR_CSR1_ACTVOS_SHIFT)
+# define PWR_CSR1_VOS_SCALE_2 (2 << PWR_CSR1_ACTVOS_SHIFT)
+# define PWR_CSR1_VOS_SCALE_1 (3 << PWR_CSR1_ACTVOS_SHIFT)
+# define PWR_CSR1_VOS_SCALE_0 (3 << PWR_CSR1_ACTVOS_SHIFT)
+#define PWR_CSR1_AVDO (1 << 16) /* Bit 16: Analog voltage detector output */
+ /* Bits 17-31: Reserved */
/* Power control register 2 (CR2) */
-#define PWR_CR2_BREN (1 << 0) /* Bit 0: Backup regulator enable */
- /* Bits 1-3: Reserved */
-#define PWR_CR2_MONEN (1 << 4) /* Bit 4: VBAT and temperature monitoring enable */
- /* Bits 5-15: Reserved */
-#define PWR_CR2_BRRDY (1 << 16) /* Bit 16: Backup regulator ready */
- /* Bits 17-19: Reserved */
-#define PWR_CR2_VBATL (1 << 20) /* Bit 20: VBAT level monitoring versus low threshold */
-#define PWR_CR2_VBATH (1 << 21) /* Bit 21: VBAT level monitoring versus high threshold */
-#define PWR_CR2_TEMPL (1 << 22) /* Bit 22: Temperature level monitoring versus low threshold */
-#define PWR_CR2_TEMPH (1 << 23) /* Bit 23: Temperature level monitoring versus high threshold */
- /* Bits 24-31: Reserved */
+#define PWR_CR2_BREN (1 << 0) /* Bit 0: Backup regulator enable */
+ /* Bits 1-3: Reserved */
+#define PWR_CR2_MONEN (1 << 4) /* Bit 4: VBAT and temperature monitoring enable */
+ /* Bits 5-15: Reserved */
+#define PWR_CR2_BRRDY (1 << 16) /* Bit 16: Backup regulator ready */
+ /* Bits 17-19: Reserved */
+#define PWR_CR2_VBATL (1 << 20) /* Bit 20: VBAT level monitoring versus low threshold */
+#define PWR_CR2_VBATH (1 << 21) /* Bit 21: VBAT level monitoring versus high threshold */
+#define PWR_CR2_TEMPL (1 << 22) /* Bit 22: Temperature level monitoring versus low threshold */
+#define PWR_CR2_TEMPH (1 << 23) /* Bit 23: Temperature level monitoring versus high threshold */
+ /* Bits 24-31: Reserved */
/* Power control register 3 (CR3) */
-#define STM32_PWR_CR3_BYPASS (1 << 0) /* Bit 0: Power management unit bypass */
-#define STM32_PWR_CR3_LDOEN (1 << 1) /* Bit 1: Low drop-out regulator enable */
-#define STM32_PWR_CR3_LDOESCUEN (1 << 2) /* Bit 2: Supply configuration update enable */
- /* Bits 3-7: Reserved */
-#define STM32_PWR_CR3_VBE (1 << 8) /* Bit 8: VBAT charging enable */
-#define STM32_PWR_CR3_VBRS (1 << 9) /* Bit 9: VBAT charging resistor selection */
- /* Bits 10-23: Reserved */
-#define STM32_PWR_CR3_USB33DEN (1 << 24) /* Bit 24: VDD33USB voltage level detector enable */
-#define STM32_PWR_CR3_USBREGEN (1 << 25) /* Bit 25: USB regulator enable */
-#define STM32_PWR_CR3_USB33RDY (1 << 26) /* Bit 26: USB supply ready */
+#define STM32_PWR_CR3_BYPASS (1 << 0) /* Bit 0: Power management unit bypass */
+#define STM32_PWR_CR3_LDOEN (1 << 1) /* Bit 1: Low drop-out regulator enable */
+#define STM32_PWR_CR3_LDOESCUEN (1 << 2) /* Bit 2: Supply configuration update enable */
+ /* Bits 3-7: Reserved */
+#define STM32_PWR_CR3_VBE (1 << 8) /* Bit 8: VBAT charging enable */
+#define STM32_PWR_CR3_VBRS (1 << 9) /* Bit 9: VBAT charging resistor selection */
+ /* Bits 10-23: Reserved */
+#define STM32_PWR_CR3_USB33DEN (1 << 24) /* Bit 24: VDD33USB voltage level detector enable */
+#define STM32_PWR_CR3_USBREGEN (1 << 25) /* Bit 25: USB regulator enable */
+#define STM32_PWR_CR3_USB33RDY (1 << 26) /* Bit 26: USB supply ready */
/* Power CPU control register (CPUCR) */
-#define STM32_PWR_CPUCR_PDDS_D1 (1 << 0) /* Bit 0: D1 domain Power Down Deepsleep selection */
-#define STM32_PWR_CPUCR_PDDS_D2 (1 << 1) /* Bit 1: D2 domain Power Down Deepsleep */
-#define STM32_PWR_CPUCR_PDDS_D3 (1 << 2) /* Bit 2: System D3 domain Power Down Deepsleep */
- /* Bits 3-4: Reserved */
-#define STM32_PWR_CPUCR_STOPF (1 << 5) /* Bit 5: STOP flag */
-#define STM32_PWR_CPUCR_SBF (1 << 6) /* Bit 6: System Standby flag */
-#define STM32_PWR_CPUCR_SBF_D1 (1 << 7) /* Bit 7: D1 domain DStandby flag */
-#define STM32_PWR_CPUCR_SBF_D2 (1 << 8) /* Bit 8: D2 domain DStandby flag */
-#define STM32_PWR_CPUCR_CSSF (1 << 9) /* Bit 9: Clear Standby and Stop flags (always read as 0) */
- /* Bit 10: Reserved */
-#define STM32_PWR_CPUCR_RUN_D3 (1 << 11) /* Bit 11: Keep system D3 domain in Run mode regardless of the CPU subsystem modes */
- /* Bits 12-31: Reserved */
+#define STM32_PWR_CPUCR_PDDS_D1 (1 << 0) /* Bit 0: D1 domain Power Down Deepsleep selection */
+#define STM32_PWR_CPUCR_PDDS_D2 (1 << 1) /* Bit 1: D2 domain Power Down Deepsleep */
+#define STM32_PWR_CPUCR_PDDS_D3 (1 << 2) /* Bit 2: System D3 domain Power Down Deepsleep */
+ /* Bits 3-4: Reserved */
+#define STM32_PWR_CPUCR_STOPF (1 << 5) /* Bit 5: STOP flag */
+#define STM32_PWR_CPUCR_SBF (1 << 6) /* Bit 6: System Standby flag */
+#define STM32_PWR_CPUCR_SBF_D1 (1 << 7) /* Bit 7: D1 domain DStandby flag */
+#define STM32_PWR_CPUCR_SBF_D2 (1 << 8) /* Bit 8: D2 domain DStandby flag */
+#define STM32_PWR_CPUCR_CSSF (1 << 9) /* Bit 9: Clear Standby and Stop flags (always read as 0) */
+ /* Bit 10: Reserved */
+#define STM32_PWR_CPUCR_RUN_D3 (1 << 11) /* Bit 11: Keep system D3 domain in Run mode regardless of the CPU subsystem modes */
+ /* Bits 12-31: Reserved */
/* Power D3 domain control register (D3CR) */
- /* Bits 0-12: Reserved */
-#define STM32_PWR_D3CR_VOSRDY (1 << 13) /* Bit 13: */
-#define STM32_PWR_D3CR_VOS_SHIFT (14) /* Bits 14-15: Voltage scaling selection according to performance */
-#define STM32_PWR_D3CR_VOS_MASK (3 << STM32_PWR_D3CR_VOS_SHIFT)
-# define PWR_D3CR_VOS_SCALE_3R (0 << STM32_PWR_D3CR_VOS_SHIFT) /* Fmax = 200MHz */
-# define PWR_D3CR_VOS_SCALE_3 (1 << STM32_PWR_D3CR_VOS_SHIFT) /* Fmax = 200MHz */
-# define PWR_D3CR_VOS_SCALE_2 (2 << STM32_PWR_D3CR_VOS_SHIFT) /* Fmax = 300MHz */
-# define PWR_D3CR_VOS_SCALE_1 (3 << STM32_PWR_D3CR_VOS_SHIFT) /* Fmax = 400MHz */
-# define PWR_D3CR_VOS_SCALE_0 (3 << STM32_PWR_D3CR_VOS_SHIFT) /* Fmax = 480MHz with ODN */
- /* Bits 15-31: Reserved */
-
+ /* Bits 0-12: Reserved */
+#define STM32_PWR_D3CR_VOSRDY (1 << 13) /* Bit 13: */
+#define STM32_PWR_D3CR_VOS_SHIFT (14) /* Bits 14-15: Voltage scaling selection according to performance */
+#define STM32_PWR_D3CR_VOS_MASK (3 << STM32_PWR_D3CR_VOS_SHIFT)
+# define PWR_D3CR_VOS_SCALE_3R (0 << STM32_PWR_D3CR_VOS_SHIFT) /* Fmax = 200MHz */
+# define PWR_D3CR_VOS_SCALE_3 (1 << STM32_PWR_D3CR_VOS_SHIFT) /* Fmax = 200MHz */
+# define PWR_D3CR_VOS_SCALE_2 (2 << STM32_PWR_D3CR_VOS_SHIFT) /* Fmax = 300MHz */
+# define PWR_D3CR_VOS_SCALE_1 (3 << STM32_PWR_D3CR_VOS_SHIFT) /* Fmax = 400MHz */
+# define PWR_D3CR_VOS_SCALE_0 (3 << STM32_PWR_D3CR_VOS_SHIFT) /* Fmax = 480MHz with ODN */
+ /* Bits 15-31: Reserved */
/* Power wakeup clear register (WKUPCR) */
+#define STM32_PWR_WKUPC1 (1 << 0) /* Bit 0: Clear wakeup pin flag for WKUP1 */
+#define STM32_PWR_WKUPC2 (1 << 1) /* Bit 1: Clear wakeup pin flag for WKUP2 */
+#define STM32_PWR_WKUPC3 (1 << 2) /* Bit 2: Clear wakeup pin flag for WKUP3 */
+#define STM32_PWR_WKUPC4 (1 << 3) /* Bit 3: Clear wakeup pin flag for WKUP4 */
+#define STM32_PWR_WKUPC5 (1 << 4) /* Bit 4: Clear wakeup pin flag for WKUP5 */
+#define STM32_PWR_WKUPC6 (1 << 5) /* Bit 5: Clear wakeup pin flag for WKUP6 */
+ /* Bits 6-31: Reserved */
+
/* Power wakeup flag register (WKUPFR) */
+#define STM32_PWR_WKUPF1 (1 << 0) /* Bit 0: Wakeup pin flag for WKUP1 */
+#define STM32_PWR_WKUPF2 (1 << 1) /* Bit 1: Wakeup pin flag for WKUP2 */
+#define STM32_PWR_WKUPF3 (1 << 2) /* Bit 2: Wakeup pin flag for WKUP3 */
+#define STM32_PWR_WKUPF4 (1 << 3) /* Bit 3: Wakeup pin flag for WKUP4 */
+#define STM32_PWR_WKUPF5 (1 << 4) /* Bit 4: Wakeup pin flag for WKUP5 */
+#define STM32_PWR_WKUPF6 (1 << 5) /* Bit 5: Wakeup pin flag for WKUP6 */
+ /* Bits 6-31: Reserved */
+
/* Power wakeup enable and polarity register (WKUPEPR) */
+#define STM32_PWR_WKUPEN(n) (1 << (n))
+#define STM32_PWR_WKUPEN1 (1 << 0) /* Bit 0: Enable wakeup pin WKUP1 */
+#define STM32_PWR_WKUPEN2 (1 << 1) /* Bit 1: Enable wakeup pin WKUP2 */
+#define STM32_PWR_WKUPEN3 (1 << 2) /* Bit 2: Enable wakeup pin WKUP3 */
+#define STM32_PWR_WKUPEN4 (1 << 3) /* Bit 3: Enable wakeup pin WKUP4 */
+#define STM32_PWR_WKUPEN5 (1 << 4) /* Bit 4: Enable wakeup pin WKUP5 */
+#define STM32_PWR_WKUPEN6 (1 << 5) /* Bit 5: Enable wakeup pin WKUP6 */
+ /* Bits 6-7: Reserved */
+#define STM32_PWR_WKUPP(n) (1 << (n + 8))
+#define STM32_PWR_WKUPP1 (1 << 8) /* Bit 8: Wakeup pin polarity for WKUP1 */
+#define STM32_PWR_WKUPP2 (1 << 9) /* Bit 9: Wakeup pin polarity for WKUP2 */
+#define STM32_PWR_WKUPP3 (1 << 10) /* Bit 10: Wakeup pin polarity for WKUP3 */
+#define STM32_PWR_WKUPP4 (1 << 11) /* Bit 11: Wakeup pin polarity for WKUP4 */
+#define STM32_PWR_WKUPP5 (1 << 12) /* Bit 12: Wakeup pin polarity for WKUP5 */
+#define STM32_PWR_WKUPP6 (1 << 13) /* Bit 13: Wakeup pin polarity for WKUP6 */
+ /* Bits 14-15: Reserved */
+#define STM32_PWR_WKUPPUPD_SHIFT(n) (n * 2 + 16)
+#define STM32_PWR_WKUPPUPD1_SHIFT (16) /* Bits 16-17: Wakeup pin pull config for WKUP1 */
+#define STM32_PWR_WKUPPUPD2_SHIFT (18) /* Bits 18-19: Wakeup pin pull config for WKUP2 */
+#define STM32_PWR_WKUPPUPD3_SHIFT (20) /* Bits 20-21: Wakeup pin pull config for WKUP3 */
+#define STM32_PWR_WKUPPUPD4_SHIFT (22) /* Bits 22-23: Wakeup pin pull config for WKUP4 */
+#define STM32_PWR_WKUPPUPD5_SHIFT (24) /* Bits 24-25: Wakeup pin pull config for WKUP5 */
+#define STM32_PWR_WKUPPUPD6_SHIFT (26) /* Bits 26-27: Wakeup pin pull config for WKUP6 */
+# define STM32_PWR_WKUPPUPD_NONE (0) /* No pull-up */
+# define STM32_PWR_WKUPPUPD_PULLUP (1) /* Pull-up enabled */
+# define STM32_PWR_WKUPPUPD_PULLDN (2) /* Pull-down enabled */
+ /* 3 is reserved */
+# define STM32_PWR_WKUPPUPD_MASK (3)
+ /* Bits 28-31: Reserved */
+
#endif /* __ARCH_ARM_SRC_STM32H7_HARDWARE_STM32H7X3XX_PWR_H */
diff --git a/arch/arm/src/stm32h7/hardware/stm32h7x3xx_rcc.h b/arch/arm/src/stm32h7/hardware/stm32h7x3xx_rcc.h
index dacd1ed..b4afa87 100644
--- a/arch/arm/src/stm32h7/hardware/stm32h7x3xx_rcc.h
+++ b/arch/arm/src/stm32h7/hardware/stm32h7x3xx_rcc.h
@@ -828,7 +828,25 @@
/* TODO: D3 Autonomous mode register */
-/* TODO: RCC Reset Status register */
+/* RCC Reset Status register */
+
+ /* Bits 0-15: Reserved */
+#define RCC_RSR_RMVF (1 << 16) /* Bit 16: Remove reset flag */
+#define RCC_RSR_CPURSTF (1 << 17) /* Bit 17: CPU reset flag */
+ /* Bit 18: Reserved */
+#define RCC_RSR_D1RSTF (1 << 19) /* Bit 19: D1 domain power switch reset flag */
+#define RCC_RSR_D2RSTF (1 << 20) /* Bit 20: D2 domain power switch reset flag */
+#define RCC_RSR_BORRSTF (1 << 21) /* Bit 21: BOR reset flag */
+#define RCC_RSR_PINRSTF (1 << 22) /* Bit 22: Pin reset flag */
+#define RCC_RSR_PORRSTF (1 << 23) /* Bit 23: POR/PDR reset flag */
+#define RCC_RSR_SFTRSTF (1 << 24) /* Bit 24: System reset from CPU flag */
+ /* Bit 25: Reserved */
+#define RCC_RSR_IWDG1RSTF (1 << 26) /* Bit 26: Independent watchdog reset flag */
+ /* Bit 27: Reserved */
+#define RCC_RSR_WWDG1RSTF (1 << 28) /* Bit 28: Window watchdog reset flag */
+ /* Bit 29: Reserved */
+#define RCC_RSR_LPWRRSTF (1 << 30) /* Bit 30: Reset due to illegal D1 DStandby or CPU Cstop flag */
+ /* Bit 31: Reserved */
/* AHB3 Peripheral Clock enable register */
diff --git a/arch/arm/src/stm32h7/stm32_adc.c b/arch/arm/src/stm32h7/stm32_adc.c
index 7f0415e..db2290b 100644
--- a/arch/arm/src/stm32h7/stm32_adc.c
+++ b/arch/arm/src/stm32h7/stm32_adc.c
@@ -86,7 +86,8 @@
((type *)((intptr_t)(ptr) - offsetof(type, member)))
#endif
-/* ADC Channels/DMA ********************************************************/
+/* ADC Channels/DMA *********************************************************/
+
/* The maximum number of channels that can be sampled. While DMA support is
* very nice for reliable multi-channel sampling, the STM32H7 can function
* without, although there is a risk of overrun.
@@ -173,6 +174,9 @@ struct stm32_dev_s
xcpt_t isr; /* Interrupt handler for this ADC block */
uint32_t base; /* Base address of registers unique to this ADC
* block */
+ uint32_t mbase; /* Base address of master ADC (allows for access to
+ * shared common registers) */
+ bool initialized; /* Keeps track of the initialization status of the ADC */
#ifdef ADC_HAVE_TIMER
uint32_t tbase; /* Base address of timer used by this ADC block */
uint32_t trcc_enr; /* RCC ENR Register */
@@ -225,10 +229,11 @@ static void tim_dumpregs(FAR struct stm32_dev_s *priv,
static void adc_rccreset(FAR struct stm32_dev_s *priv, bool reset);
static void adc_enable(FAR struct stm32_dev_s *priv);
-static uint32_t adc_sqrbits(FAR struct stm32_dev_s *priv, int first, int last,
- int offset);
+static uint32_t adc_sqrbits(FAR struct stm32_dev_s *priv, int first,
+ int last, int offset);
static int adc_set_ch(FAR struct adc_dev_s *dev, uint8_t ch);
-static bool adc_internal(FAR struct stm32_dev_s * priv, uint32_t *adc_ccr);
+static bool adc_internal(FAR struct stm32_dev_s * priv,
+ uint32_t *adc_ccr);
#ifdef ADC_HAVE_TIMER
static void adc_timstart(FAR struct stm32_dev_s *priv, bool enable);
@@ -297,6 +302,8 @@ static struct stm32_dev_s g_adcpriv1 =
.isr = adc12_interrupt,
.intf = 1,
.base = STM32_ADC1_BASE,
+ .mbase = STM32_ADC1_BASE,
+ .initialized = false,
#ifdef ADC1_HAVE_TIMER
.trigger = CONFIG_STM32H7_ADC1_TIMTRIG,
.tbase = ADC1_TIMER_BASE,
@@ -337,6 +344,8 @@ static struct stm32_dev_s g_adcpriv2 =
.isr = adc12_interrupt,
.intf = 2,
.base = STM32_ADC2_BASE,
+ .mbase = STM32_ADC1_BASE,
+ .initialized = false,
#ifdef ADC2_HAVE_TIMER
.trigger = CONFIG_STM32H7_ADC2_TIMTRIG,
.tbase = ADC2_TIMER_BASE,
@@ -377,6 +386,8 @@ static struct stm32_dev_s g_adcpriv3 =
.isr = adc3_interrupt,
.intf = 3,
.base = STM32_ADC3_BASE,
+ .mbase = STM32_ADC3_BASE,
+ .initialized = false,
#ifdef ADC3_HAVE_TIMER
.trigger = CONFIG_STM32H7_ADC3_TIMTRIG,
.tbase = ADC3_TIMER_BASE,
@@ -478,6 +489,72 @@ static void adc_modifyreg(FAR struct stm32_dev_s *priv, int offset,
}
/****************************************************************************
+ * Name: adc_getregm
+ *
+ * Description:
+ * Read the value of an ADC register from the associated ADC master.
+ *
+ * Input Parameters:
+ * priv - A reference to the ADC block status
+ * offset - The offset to the register to read
+ *
+ * Returned Value:
+ * The current contents of the specified register in the ADC master.
+ *
+ ****************************************************************************/
+
+static uint32_t adc_getregm(FAR struct stm32_dev_s *priv, int offset)
+{
+ return getreg32(priv->mbase + offset);
+}
+
+/****************************************************************************
+ * Name: adc_putregm
+ *
+ * Description:
+ * Write a value to an ADC register in the associated ADC master.
+ *
+ * Input Parameters:
+ * priv - A reference to the ADC block status
+ * offset - The offset to the register to write to
+ * value - The value to write to the register
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void adc_putregm(FAR struct stm32_dev_s *priv, int offset,
+ uint32_t value)
+{
+ putreg32(value, priv->mbase + offset);
+}
+
+/****************************************************************************
+ * Name: adc_modifyregm
+ *
+ * Description:
+ * Modify the value of an ADC register in the associated ADC master
+ * (not atomic).
+ *
+ * Input Parameters:
+ * priv - A reference to the ADC block status
+ * offset - The offset to the register to modify
+ * clrbits - The bits to clear
+ * setbits - The bits to set
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void adc_modifyregm(FAR struct stm32_dev_s *priv, int offset,
+ uint32_t clrbits, uint32_t setbits)
+{
+ adc_putregm(priv, offset, (adc_getregm(priv, offset) & ~clrbits) | setbits);
+}
+
+/****************************************************************************
* Name: tim_getreg
*
* Description:
@@ -774,7 +851,7 @@ static int adc_timinit(FAR struct stm32_dev_s *priv)
/* Set the reload and prescaler values */
- tim_putreg(priv, STM32_GTIM_PSC_OFFSET, prescaler-1);
+ tim_putreg(priv, STM32_GTIM_PSC_OFFSET, prescaler - 1);
tim_putreg(priv, STM32_GTIM_ARR_OFFSET, reload);
/* Clear the advanced timers repetition counter in TIM1 */
@@ -875,6 +952,7 @@ static int adc_timinit(FAR struct stm32_dev_s *priv)
case 4: /* TimerX TRGO event */
{
/* TODO: TRGO support not yet implemented */
+
/* Set the event TRGO */
ccenable = 0;
@@ -979,9 +1057,11 @@ static int adc_timinit(FAR struct stm32_dev_s *priv)
*
* Description:
* Called by power management framework when it wants to enter low power
- * states. Check if ADC is in progress and if so prevent from entering STOP.
+ * states. Check if ADC is in progress and if so prevent from entering
+ * STOP.
*
****************************************************************************/
+
#ifdef CONFIG_PM
static int adc_pm_prepare(struct pm_callback_s *cb, int domain,
enum pm_state_e state)
@@ -1093,7 +1173,7 @@ static void adc_rccreset(FAR struct stm32_dev_s *priv, bool reset)
bit = RCC_AHB1RSTR_ADC12RST;
}
- /* First must disable interrupts because the AHB2RSTR register is used by
+ /* First must disable interrupts because the AHB2RSTR register is used by
* several different drivers.
*/
@@ -1175,8 +1255,8 @@ static void adc_enable(FAR struct stm32_dev_s *priv)
* Name: adc_bind
*
* Description:
- * Bind the upper-half driver callbacks to the lower-half implementation. This
- * must be called early in order to receive ADC event notifications.
+ * Bind the upper-half driver callbacks to the lower-half implementation.
+ * This must be called early in order to receive ADC event notifications.
*
****************************************************************************/
@@ -1253,9 +1333,21 @@ static int adc_setup(FAR struct adc_dev_s *dev)
flags = enter_critical_section();
- /* Make sure that the ADC device is in the powered up, reset state. */
+ /* Make sure that the ADC device is in the powered up, reset state.
+ * Since reset is shared between ADC1 and ADC2, don't reset one if the
+ * other has already been reset. (We only need to worry about this if both
+ * ADC1 and ADC2 are enabled.)
+ */
- adc_reset(dev);
+#if defined(CONFIG_STM32H7_ADC1) && defined(CONFIG_STM32H7_ADC2)
+ if ((dev == &g_adcdev1 &&
+ !((FAR struct stm32_dev_s *)g_adcdev2.ad_priv)->initialized) ||
+ (dev == &g_adcdev2 &&
+ !((FAR struct stm32_dev_s *)g_adcdev1.ad_priv)->initialized))
+#endif
+ {
+ adc_reset(dev);
+ }
/* Initialize the same sample time for each ADC.
* During sample cycles channel selection bits must remain unchanged.
@@ -1320,7 +1412,7 @@ static int adc_setup(FAR struct adc_dev_s *dev)
adc_internal(priv, &setbits);
- adc_modifyreg(priv, STM32_ADC_CCR_OFFSET, clrbits, setbits);
+ adc_modifyregm(priv, STM32_ADC_CCR_OFFSET, clrbits, setbits);
#ifdef ADC_HAVE_DMA
@@ -1353,13 +1445,14 @@ static int adc_setup(FAR struct adc_dev_s *dev)
setbits = 0;
clrbits = ADC_PCSEL_PCSEL_ALL;
- for (i = 0; i < priv->cchannels && priv->chanlist[i]; i++)
+ for (i = 0; i < priv->cchannels; i++)
{
setbits |= 1 << priv->chanlist[i];
}
- adc_modifyreg(priv, STM32_ADC_PCSEL_OFFSET, clrbits, setbits);
+ setbits &= ADC_PCSEL_PCSEL_ALL;
+ adc_modifyreg(priv, STM32_ADC_PCSEL_OFFSET, clrbits, setbits);
/* Set ADEN to wake up the ADC from Power Down. */
@@ -1390,13 +1483,15 @@ static int adc_setup(FAR struct adc_dev_s *dev)
adc_getreg(priv, STM32_ADC_SQR2_OFFSET),
adc_getreg(priv, STM32_ADC_SQR3_OFFSET),
adc_getreg(priv, STM32_ADC_SQR4_OFFSET));
- ainfo("CCR: 0x%08x\n", getreg32(STM32_ADC_CCR));
+ ainfo("CCR: 0x%08x\n", adc_getregm(priv, STM32_ADC_CCR_OFFSET));
/* Enable the ADC interrupt */
ainfo("Enable the ADC interrupt: irq=%d\n", priv->irq);
up_enable_irq(priv->irq);
+ priv->initialized = true;
+
return ret;
}
@@ -1429,6 +1524,8 @@ static void adc_shutdown(FAR struct adc_dev_s *dev)
/* Disable and reset the ADC module */
adc_reset(dev);
+
+ priv->initialized = false;
}
/****************************************************************************
@@ -1463,6 +1560,7 @@ static void adc_rxint(FAR struct adc_dev_s *dev, bool enable)
regval &= ~ADC_INT_MASK;
}
+
adc_putreg(priv, STM32_ADC_IER_OFFSET, regval);
}
@@ -1517,9 +1615,9 @@ static bool adc_internal(FAR struct stm32_dev_s * priv, uint32_t *adc_ccr)
break;
}
}
-
}
}
+
return internal;
}
@@ -1695,7 +1793,7 @@ static int adc_ioctl(FAR struct adc_dev_s *dev, int cmd, unsigned long arg)
/* Set the watchdog threshold register */
- regval= ((arg << ADC_LTR1_LT_SHIFT) & ADC_LTR1_LT_MASK);
+ regval = ((arg << ADC_LTR1_LT_SHIFT) & ADC_LTR1_LT_MASK);
adc_putreg(priv, STM32_ADC_LTR1_OFFSET, regval);
/* Ensure analog watchdog is enabled */
@@ -1850,6 +1948,7 @@ static int adc12_interrupt(int irq, FAR void *context, FAR void *arg)
* Returned Value:
*
****************************************************************************/
+
#ifdef CONFIG_STM32H7_ADC3
static int adc3_interrupt(int irq, FAR void *context, FAR void *arg)
{
@@ -1903,7 +2002,8 @@ static void adc_dmaconvcallback(DMA_HANDLE handle, uint8_t isr, FAR void *arg)
for (i = 0; i < priv->nchannels; i++)
{
- priv->cb->au_receive(dev, priv->chanlist[priv->current], priv->dmabuffer[priv->current]);
+ priv->cb->au_receive(dev, priv->chanlist[priv->current],
+ priv->dmabuffer[priv->current]);
priv->current++;
if (priv->current >= priv->nchannels)
{
diff --git a/arch/arm/src/stm32h7/stm32_ethernet.c b/arch/arm/src/stm32h7/stm32_ethernet.c
index d9903cf..c8035dd 100644
--- a/arch/arm/src/stm32h7/stm32_ethernet.c
+++ b/arch/arm/src/stm32h7/stm32_ethernet.c
@@ -786,6 +786,7 @@ static int stm32_ethconfig(struct stm32_ethmac_s *priv);
/****************************************************************************
* Private Functions
****************************************************************************/
+
/****************************************************************************
* Name: stm32_getreg
*
@@ -834,14 +835,14 @@ static uint32_t stm32_getreg(uint32_t addr)
else
{
- /* Did we print "..." for the previous value? */
+ /* Did we print "..." for the previous value? */
- if (count > 3)
- {
- /* Yes.. then show how many times the value repeated */
+ if (count > 3)
+ {
+ /* Yes.. then show how many times the value repeated */
- ninfo("[repeats %d more times]\n", count - 3);
- }
+ ninfo("[repeats %d more times]\n", count - 3);
+ }
/* Save the new address, value, and count */
@@ -1038,6 +1039,7 @@ static inline bool stm32_isfreebuffer(struct stm32_ethmac_s *priv)
* pointer to the next tx descriptor for the current interface
*
****************************************************************************/
+
static struct eth_desc_s *stm32_get_next_txdesc(struct stm32_ethmac_s *priv,
struct eth_desc_s * curr)
{
@@ -1081,8 +1083,8 @@ static int stm32_transmit(struct stm32_ethmac_s *priv)
struct eth_desc_s *txdesc;
struct eth_desc_s *txfirst;
- /* The internal (optimal) network buffer size may be configured to be larger
- * than the Ethernet buffer size.
+ /* The internal (optimal) network buffer size may be configured to be
+ * larger than the Ethernet buffer size.
*/
#if OPTIMAL_ETH_BUFSIZE > ALIGNED_BUFSIZE
@@ -1116,24 +1118,24 @@ static int stm32_transmit(struct stm32_ethmac_s *priv)
#if OPTIMAL_ETH_BUFSIZE > ALIGNED_BUFSIZE
if (priv->dev.d_len > ALIGNED_BUFSIZE)
- {
- /* Yes... how many buffers will be need to send the packet? */
+ {
+ /* Yes... how many buffers will be need to send the packet? */
- bufcount = (priv->dev.d_len + (ALIGNED_BUFSIZE - 1)) / ALIGNED_BUFSIZE;
- lastsize = priv->dev.d_len - (bufcount - 1) * ALIGNED_BUFSIZE;
+ bufcount = (priv->dev.d_len + (ALIGNED_BUFSIZE - 1)) / ALIGNED_BUFSIZE;
+ lastsize = priv->dev.d_len - (bufcount - 1) * ALIGNED_BUFSIZE;
- ninfo("bufcount: %d lastsize: %d\n", bufcount, lastsize);
+ ninfo("bufcount: %d lastsize: %d\n", bufcount, lastsize);
- /* Set the first segment bit in the first TX descriptor */
+ /* Set the first segment bit in the first TX descriptor */
- txdesc->des3 = ETH_TDES3_RD_FD;
+ txdesc->des3 = ETH_TDES3_RD_FD;
- /* Set up all but the last TX descriptor */
+ /* Set up all but the last TX descriptor */
- buffer = priv->dev.d_buf;
+ buffer = priv->dev.d_buf;
- for (i = 0; i < bufcount; i++)
- {
+ for (i = 0; i < bufcount; i++)
+ {
/* This could be a normal event but the design does not handle it */
DEBUGASSERT((txdesc->des3 & ETH_TDES3_RD_OWN) == 0);
@@ -1541,6 +1543,7 @@ static void stm32_disableint(struct stm32_ethmac_s *priv, uint32_t ierbit)
* pointer to the next rx descriptor for the current interface
*
****************************************************************************/
+
static struct eth_desc_s *stm32_get_next_rxdesc(struct stm32_ethmac_s *priv,
struct eth_desc_s * curr)
{
@@ -1660,7 +1663,7 @@ static void stm32_freesegment(struct stm32_ethmac_s *priv,
static int stm32_recvframe(struct stm32_ethmac_s *priv)
{
struct eth_desc_s *rxdesc;
- struct eth_desc_s *rxcurr;
+ struct eth_desc_s *rxcurr = NULL;
uint8_t *buffer;
int i;
@@ -1818,6 +1821,7 @@ static int stm32_recvframe(struct stm32_ethmac_s *priv)
{
/* Drop the context descriptors, we are not interested */
+ DEBUGASSERT(rxcurr != NULL);
stm32_freesegment(priv, rxcurr, 1);
}
@@ -2886,7 +2890,6 @@ static int stm32_rmmac(struct net_driver_s *dev, const uint8_t *mac)
static void stm32_txdescinit(struct stm32_ethmac_s *priv,
union stm32_desc_u *txtable)
-
{
struct eth_desc_s *txdesc;
int i;
@@ -4285,18 +4288,18 @@ static int stm32_ethconfig(struct stm32_ethmac_s *priv)
ninfo("Initialize the PHY\n");
ret = stm32_phyinit(priv);
if (ret < 0)
- {
- return ret;
- }
+ {
+ return ret;
+ }
/* Initialize the MAC and DMA */
ninfo("Initialize the MAC and DMA\n");
ret = stm32_macconfig(priv);
if (ret < 0)
- {
- return ret;
- }
+ {
+ return ret;
+ }
/* Enable normal MAC operation */
@@ -4328,11 +4331,11 @@ static int stm32_ethconfig(struct stm32_ethmac_s *priv)
*
****************************************************************************/
-#if STM32H7_NETHERNET == 1 || defined(CONFIG_NETDEV_LATEINIT)
-static inline
-#endif
-
+#if STM32H7_NETHERNET > 1 || defined(CONFIG_NETDEV_LATEINIT)
int stm32_ethinitialize(int intf)
+#else
+static inline int stm32_ethinitialize(int intf)
+#endif
{
struct stm32_ethmac_s *priv;
@@ -4371,11 +4374,11 @@ int stm32_ethinitialize(int intf)
/* Attach the IRQ to the driver */
if (irq_attach(STM32_IRQ_ETH, stm32_interrupt, NULL))
- {
- /* We could not attach the ISR to the interrupt */
+ {
+ /* We could not attach the ISR to the interrupt */
- return -EAGAIN;
- }
+ return -EAGAIN;
+ }
/* Put the interface in the down state. */
diff --git a/arch/arm/src/stm32h7/stm32_ethernet.h b/arch/arm/src/stm32h7/stm32_ethernet.h
index fdb1ad5..fc17197 100644
--- a/arch/arm/src/stm32h7/stm32_ethernet.h
+++ b/arch/arm/src/stm32h7/stm32_ethernet.h
@@ -48,7 +48,7 @@
#ifndef __ASSEMBLY__
/****************************************************************************
- * Public Functions
+ * Public Function Prototypes
****************************************************************************/
#undef EXTERN
@@ -80,7 +80,7 @@ extern "C"
*
****************************************************************************/
-#if STM32H7_NETHERNET > 1
+#if STM32H7_NETHERNET > 1 || defined(CONFIG_NETDEV_LATEINIT)
int stm32_ethinitialize(int intf);
#endif
@@ -103,7 +103,7 @@ int stm32_ethinitialize(int intf);
*
* Assumptions:
*
- ***************************************************************************/
+ ****************************************************************************/
#ifdef CONFIG_STM32H7_PHYINIT
int stm32_phy_boardinitialize(int intf);
diff --git a/arch/arm/src/stm32h7/stm32_flash.c b/arch/arm/src/stm32h7/stm32_flash.c
index e676697..c7dc127 100644
--- a/arch/arm/src/stm32h7/stm32_flash.c
+++ b/arch/arm/src/stm32h7/stm32_flash.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * arch/arm/src/stm32h7/stm32h7_flash.c
+ * arch/arm/src/stm32h7/stm32_flash.c
*
* Copyright (C) 2019 Gregory Nutt. All rights reserved.
* Authors: Gregory Nutt <gn...@nuttx.org>
@@ -76,8 +76,8 @@
/* Flash size is known from the chip selection:
*
* When CONFIG_STM32H7_FLASH_OVERRIDE_DEFAULT is set the
- * CONFIG_STM32H7_FLASH_CONFIG_x selects the default FLASH size based on the
- * chip part number. This value can be overridden with
+ * CONFIG_STM32H7_FLASH_CONFIG_x selects the default FLASH size based on
+ * the chip part number. This value can be overridden with
* CONFIG_STM32H7_FLASH_OVERRIDE_x
*
* Parts STM32H74xxE have 512Kb of FLASH
@@ -147,7 +147,7 @@
#define PROGMEM_NBLOCKS STM32_FLASH_NPAGES
-/*****************************************************************************
+/****************************************************************************
* Private Types
****************************************************************************/
@@ -184,21 +184,21 @@ static struct stm32h7_flash_priv_s stm32h7_flash_bank2_priv =
* Private Functions
****************************************************************************/
-/*****************************************************************************
+/****************************************************************************
* Name: stm32h7_flash_getreg32
*
* Description:
* Get a 32-bit register value by offset
*
- *****************************************************************************/
+ ****************************************************************************/
static inline uint32_t stm32h7_flash_getreg32(FAR struct stm32h7_flash_priv_s
- *priv, uint8_t offset)
+ *priv, uint32_t offset)
{
return getreg32(priv->ifbase + offset);
}
-/*****************************************************************************
+/****************************************************************************
* Name: stm32h7_flash_putreg32
*
* Description:
@@ -207,48 +207,48 @@ static inline uint32_t stm32h7_flash_getreg32(FAR struct stm32h7_flash_priv_s
****************************************************************************/
static inline void stm32h7_flash_putreg32(FAR struct stm32h7_flash_priv_s
- *priv, uint8_t offset,
+ *priv, uint32_t offset,
uint32_t value)
{
putreg32(value, priv->ifbase + offset);
}
-/*****************************************************************************
+/****************************************************************************
* Name: stm32h7_flash_modifyreg32
*
* Description:
* Modify a 32-bit register value by offset
*
- *****************************************************************************/
+ ****************************************************************************/
static inline void stm32h7_flash_modifyreg32(FAR struct stm32h7_flash_priv_s
- *priv, uint8_t offset,
+ *priv, uint32_t offset,
uint32_t clearbits,
uint32_t setbits)
{
modifyreg32(priv->ifbase + offset, clearbits, setbits);
}
-/*****************************************************************************
+/****************************************************************************
* Name: stm32h7_flash_sem_lock
*
* Description:
* Take the Bank exclusive access semaphore
*
- *****************************************************************************/
+ ****************************************************************************/
static void stm32h7_flash_sem_lock(FAR struct stm32h7_flash_priv_s *priv)
{
nxsem_wait_uninterruptible(&priv->sem);
}
-/*****************************************************************************
+/****************************************************************************
* Name: stm32h7_flash_sem_unlock
*
* Description:
* Release the Bank exclusive access semaphore
*
- *****************************************************************************/
+ ****************************************************************************/
static inline void stm32h7_flash_sem_unlock(FAR struct stm32h7_flash_priv_s
*priv)
@@ -256,13 +256,13 @@ static inline void stm32h7_flash_sem_unlock(FAR struct stm32h7_flash_priv_s
nxsem_post(&priv->sem);
}
-/*****************************************************************************
+/****************************************************************************
* Name: stm32h7_unlock_flash
*
* Description:
* Unlock the Bank
*
- *****************************************************************************/
+ ****************************************************************************/
static void stm32h7_unlock_flash(FAR struct stm32h7_flash_priv_s *priv)
{
@@ -279,38 +279,39 @@ static void stm32h7_unlock_flash(FAR struct stm32h7_flash_priv_s *priv)
}
}
-/*****************************************************************************
+/****************************************************************************
* Name: stm32h7_lock_flash
*
* Description:
* Lock the Bank
*
- *****************************************************************************/
+ ****************************************************************************/
static void stm32h7_lock_flash(FAR struct stm32h7_flash_priv_s *priv)
{
stm32h7_flash_modifyreg32(priv, STM32_FLASH_CR1_OFFSET, 0, FLASH_CR_LOCK);
}
-/*****************************************************************************
+/****************************************************************************
* Name: stm32h7_flash_size
*
* Description:
* Returns the size in bytes of FLASH
*
- *****************************************************************************/
+ ****************************************************************************/
static inline uint32_t stm32h7_flash_size(FAR struct stm32h7_flash_priv_s *priv)
{
return FLASH_SECTOR_SIZE * PROGMEM_NBLOCKS;
}
-/*****************************************************************************
+
+/****************************************************************************
* Name: stm32h7_flash_bank
*
* Description:
* Returns the priv pointer to the correct bank
*
- *****************************************************************************/
+ ****************************************************************************/
static inline
FAR struct stm32h7_flash_priv_s * stm32h7_flash_bank(size_t address)
@@ -320,6 +321,7 @@ FAR struct stm32h7_flash_priv_s * stm32h7_flash_bank(size_t address)
{
return NULL;
}
+
#if STM32_FLASH_NPAGES > 1
if (address >= stm32h7_flash_bank2_priv.base)
{
@@ -331,16 +333,88 @@ FAR struct stm32h7_flash_priv_s * stm32h7_flash_bank(size_t address)
}
/****************************************************************************
+ * Name: stm32h7_unlock_flashopt
+ *
+ * Description:
+ * Unlock the flash option bytes
+ *
+ ****************************************************************************/
+
+static void stm32h7_unlock_flashopt(FAR struct stm32h7_flash_priv_s *priv)
+{
+ while (stm32h7_flash_getreg32(priv, STM32_FLASH_SR1_OFFSET) & FLASH_SR_BSY)
+ {
+ }
+
+ if (stm32h7_flash_getreg32(priv, STM32_FLASH_OPTCR_OFFSET) & FLASH_OPTCR_OPTLOCK)
+ {
+ /* Unlock sequence */
+
+ stm32h7_flash_putreg32(priv, STM32_FLASH_OPTKEYR_OFFSET, FLASH_OPTKEY1);
+ stm32h7_flash_putreg32(priv, STM32_FLASH_OPTKEYR_OFFSET, FLASH_OPTKEY2);
+ }
+}
+
+/****************************************************************************
+ * Name: stm32h7_lock_flashopt
+ *
+ * Description:
+ * Lock the flash option bytes
+ *
+ ****************************************************************************/
+
+static void stm32h7_lock_flashopt(FAR struct stm32h7_flash_priv_s *priv)
+{
+ stm32h7_flash_modifyreg32(priv, STM32_FLASH_OPTCR_OFFSET, 0, FLASH_OPTCR_OPTLOCK);
+}
+
+/****************************************************************************
+ * Name: stm32h7_save_flashopt
+ *
+ * Description:
+ * Save the flash option bytes to non-volatile storage.
+ *
+ ****************************************************************************/
+
+static void stm32h7_save_flashopt(FAR struct stm32h7_flash_priv_s *priv)
+{
+ while (stm32h7_flash_getreg32(priv, STM32_FLASH_SR1_OFFSET) &
+ (FLASH_SR_BSY | FLASH_SR_CRCBUSY))
+ {
+ }
+ while (stm32h7_flash_getreg32(priv, STM32_FLASH_SR2_OFFSET) &
+ (FLASH_SR_BSY | FLASH_SR_CRCBUSY))
+ {
+ }
+
+ /* Can only write flash options if the option control reg is unlocked */
+
+ if (!(stm32h7_flash_getreg32(priv, STM32_FLASH_OPTCR_OFFSET) &
+ FLASH_OPTCR_OPTLOCK))
+ {
+ stm32h7_flash_modifyreg32(priv, STM32_FLASH_OPTCR_OFFSET, 0,
+ FLASH_OPTCR_OPTSTRT);
+ }
+
+ /* Wait for the update to complete */
+
+ while (stm32h7_flash_getreg32(priv, STM32_FLASH_OPTSR_CUR_OFFSET) &
+ FLASH_OPTSR_BUSYV)
+ {
+ }
+}
+
+/****************************************************************************
* Public Functions
****************************************************************************/
-/*****************************************************************************
+/****************************************************************************
* Name: stm32h7_flash_unlock
*
* Description:
* Unlocks a bank
*
- *****************************************************************************/
+ ****************************************************************************/
int stm32h7_flash_unlock(size_t addr)
{
@@ -358,13 +432,13 @@ int stm32h7_flash_unlock(size_t addr)
return rv;
}
-/*****************************************************************************
+/****************************************************************************
* Name: stm32h7_flash_lock
*
* Description:
* Locks a bank
*
- *****************************************************************************/
+ ****************************************************************************/
int stm32h7_flash_lock(size_t addr)
{
@@ -423,6 +497,68 @@ int stm32h7_flash_writeprotect(size_t block, bool enabled)
return rv;
}
+/****************************************************************************
+ * Name: stm32h7_flash_getopt
+ *
+ * Description:
+ * Returns the current flash option bytes from the FLASH_OPTSR_CR register.
+ *
+ ****************************************************************************/
+
+uint32_t stm32h7_flash_getopt(void)
+{
+ struct stm32h7_flash_priv_s *priv;
+ priv = stm32h7_flash_bank(STM32_FLASH_BANK1);
+ if (priv)
+ {
+ return stm32h7_flash_getreg32(priv, STM32_FLASH_OPTSR_CUR_OFFSET);
+ }
+
+ return 0;
+}
+
+/****************************************************************************
+ * Name: stm32h7_flash_optmodify
+ *
+ * Description:
+ * Modifies the current flash option bytes, given bits to set and clear.
+ *
+ ****************************************************************************/
+
+void stm32h7_flash_optmodify(uint32_t clear, uint32_t set)
+{
+ struct stm32h7_flash_priv_s *priv;
+ priv = stm32h7_flash_bank(STM32_FLASH_BANK1);
+ if (priv)
+ {
+ stm32h7_unlock_flashopt(priv);
+ stm32h7_flash_modifyreg32(priv, STM32_FLASH_OPTSR_PRG_OFFSET, clear, set);
+ stm32h7_save_flashopt(priv);
+ }
+}
+
+/****************************************************************************
+ * Name: stm32h7_flash_swapbanks
+ *
+ * Description:
+ * Swaps banks 1 and 2 in the processor's memory map. Takes effect
+ * the next time the system is reset.
+ *
+ ****************************************************************************/
+
+void stm32h7_flash_swapbanks(void)
+{
+ uint32_t opts = stm32h7_flash_getopt();
+ if (opts & FLASH_OPTCR_SWAPBANK)
+ {
+ stm32h7_flash_optmodify(FLASH_OPTCR_SWAPBANK, 0);
+ }
+ else
+ {
+ stm32h7_flash_optmodify(0, FLASH_OPTCR_SWAPBANK);
+ }
+}
+
size_t up_progmem_pagesize(size_t page)
{
return FLASH_SECTOR_SIZE;
@@ -438,6 +574,7 @@ ssize_t up_progmem_getpage(size_t addr)
{
return -EFAULT;
}
+
return priv->stblock + ((addr - priv->base) / FLASH_SECTOR_SIZE);
}
@@ -508,11 +645,12 @@ ssize_t up_progmem_eraseblock(size_t block)
stm32h7_flash_modifyreg32(priv, STM32_FLASH_CR1_OFFSET, 0, FLASH_CR_SER);
stm32h7_flash_modifyreg32(priv, STM32_FLASH_CR1_OFFSET, FLASH_CR_SNB_MASK,
- FLASH_CR_SNB(block));
+ FLASH_CR_SNB(block - priv->stblock));
stm32h7_flash_modifyreg32(priv, STM32_FLASH_CR1_OFFSET, 0, FLASH_CR_START);
- while (stm32h7_flash_getreg32(priv, STM32_FLASH_CR1_OFFSET) & FLASH_SR_BSY)
+ while (stm32h7_flash_getreg32(priv, STM32_FLASH_SR1_OFFSET) &
+ (FLASH_SR_BSY | FLASH_SR_QW))
{
}
@@ -600,7 +738,7 @@ ssize_t up_progmem_write(size_t addr, const void *buf, size_t count)
ARM_ISB();
while (stm32h7_flash_getreg32(priv, STM32_FLASH_SR1_OFFSET) &
- FLASH_SR_BSY)
+ (FLASH_SR_BSY | FLASH_SR_QW))
{
}
@@ -682,6 +820,7 @@ ssize_t up_progmem_write(size_t addr, const void *buf, size_t count)
}
}
}
+
stm32h7_flash_modifyreg32(priv, STM32_FLASH_CR1_OFFSET, FLASH_CR_PG, 0);
stm32h7_flash_sem_unlock(priv);
return written;
diff --git a/arch/arm/src/stm32h7/stm32_ethernet.h b/arch/arm/src/stm32h7/stm32_flash.h
similarity index 61%
copy from arch/arm/src/stm32h7/stm32_ethernet.h
copy to arch/arm/src/stm32h7/stm32_flash.h
index fdb1ad5..abc4301 100644
--- a/arch/arm/src/stm32h7/stm32_ethernet.h
+++ b/arch/arm/src/stm32h7/stm32_flash.h
@@ -1,8 +1,8 @@
/****************************************************************************
- * arch/arm/src/stm32h7/stm32_ethernet.h
+ * arch/arm/src/stm32h7/stm32_flash.h
*
- * Copyright (C) 2015 Gregory Nutt. All rights reserved.
- * Author: Gregory Nutt <gn...@nuttx.org>
+ * Copyright (C) 2020 Gregory Nutt. All rights reserved.
+ * Author: Joshua Lange <jl...@2g-eng.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -33,8 +33,8 @@
*
****************************************************************************/
-#ifndef __ARCH_ARM_SRC_STM32H7_STM32_ETHERNET_H
-#define __ARCH_ARM_SRC_STM32H7_STM32_ETHERNET_H
+#ifndef __ARCH_ARM_SRC_STM32H7_STM32_FLASH_H
+#define __ARCH_ARM_SRC_STM32H7_STM32_FLASH_H
/****************************************************************************
* Included Files
@@ -42,15 +42,15 @@
#include <nuttx/config.h>
-#include "hardware/stm32_ethernet.h"
-
-#if STM32H7_NETHERNET > 0
-#ifndef __ASSEMBLY__
+#include "chip.h"
+#include "hardware/stm32_flash.h"
/****************************************************************************
- * Public Functions
+ * Public Function Prototypes
****************************************************************************/
+#ifndef __ASSEMBLY__
+
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
@@ -61,53 +61,35 @@ extern "C"
#endif
/****************************************************************************
- * Function: stm32_ethinitialize
+ * Name: stm32h7_flash_getopt
*
* Description:
- * Initialize the Ethernet driver for one interface. If the STM32 chip
- * supports multiple Ethernet controllers, then board specific logic must
- * implement up_netinitialize() and call this function to initialize the
- * desired interfaces.
- *
- * Parameters:
- * intf - In the case where there are multiple EMACs, this value identifies
- * which EMAC is to be initialized.
- *
- * Returned Value:
- * OK on success; Negated errno on failure.
- *
- * Assumptions:
+ * Returns the current flash option bytes from the FLASH_OPTSR_CR register.
*
****************************************************************************/
-#if STM32H7_NETHERNET > 1
-int stm32_ethinitialize(int intf);
-#endif
+uint32_t stm32h7_flash_getopt(void);
/****************************************************************************
- * Function: stm32_phy_boardinitialize
+ * Name: stm32h7_flash_optmodify
*
* Description:
- * Some boards require specialized initialization of the PHY before it can
- * be used. This may include such things as configuring GPIOs, resetting
- * the PHY, etc. If CONFIG_STM32H7_PHYINIT is defined in the configuration
- * then the board specific logic must provide stm32_phyinitialize(); The
- * STM32 Ethernet driver will call this function one time before it first
- * uses the PHY.
+ * Modifies the current flash option bytes, given bits to set and clear.
*
- * Parameters:
- * intf - Always zero for now.
- *
- * Returned Value:
- * OK on success; Negated errno on failure.
+ ****************************************************************************/
+
+void stm32h7_flash_optmodify(uint32_t clear, uint32_t set);
+
+/****************************************************************************
+ * Name: stm32h7_flash_swapbanks
*
- * Assumptions:
+ * Description:
+ * Swaps banks 1 and 2 in the processor's memory map. Takes effect
+ * the next time the system is reset.
*
- ***************************************************************************/
+ ****************************************************************************/
-#ifdef CONFIG_STM32H7_PHYINIT
-int stm32_phy_boardinitialize(int intf);
-#endif
+void stm32h7_flash_swapbanks(void);
#undef EXTERN
#if defined(__cplusplus)
@@ -115,5 +97,4 @@ int stm32_phy_boardinitialize(int intf);
#endif
#endif /* __ASSEMBLY__ */
-#endif /* STM32H7_NETHERNET > 0 */
-#endif /* __ARCH_ARM_SRC_STM32H7_STM32_ETHERNET_H */
+#endif /* __ARCH_ARM_SRC_STM32H7_STM32_FLASH_H */
diff --git a/arch/arm/src/stm32h7/stm32_iwdg.c b/arch/arm/src/stm32h7/stm32_iwdg.c
new file mode 100644
index 0000000..12d95d4
--- /dev/null
+++ b/arch/arm/src/stm32h7/stm32_iwdg.c
@@ -0,0 +1,706 @@
+/****************************************************************************
+ * arch/arm/src/stm32h7/stm32_iwdg.c
+ *
+ * Copyright (C) 2012, 2016, 2020 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gn...@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/arch.h>
+
+#include <stdint.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/irq.h>
+#include <nuttx/clock.h>
+#include <nuttx/timers/watchdog.h>
+#include <arch/board/board.h>
+
+#include "up_arch.h"
+#include "stm32_rcc.h"
+#include "stm32_wdg.h"
+
+#if defined(CONFIG_WATCHDOG) && defined(CONFIG_STM32H7_IWDG)
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Clocking *****************************************************************/
+
+/* The minimum frequency of the IWDG clock is:
+ *
+ * Fmin = Flsi / 256
+ *
+ * So the maximum delay (in milliseconds) is then:
+ *
+ * 1000 * IWDG_RLR_MAX / Fmin
+ *
+ * For example, if Flsi = 30Khz (the nominal, uncalibrated value), then the
+ * maximum delay is:
+ *
+ * Fmin = 117.1875
+ * 1000 * 4095 / Fmin = 34,944 MSec
+ */
+
+#define IWDG_FMIN (STM32_LSI_FREQUENCY / 256)
+#define IWDG_MAXTIMEOUT (1000 * IWDG_RLR_MAX / IWDG_FMIN)
+
+/* Configuration ************************************************************/
+
+#ifndef CONFIG_STM32H7_IWDG_DEFTIMOUT
+# define CONFIG_STM32H7_IWDG_DEFTIMOUT IWDG_MAXTIMEOUT
+#endif
+
+#ifndef CONFIG_DEBUG_WATCHDOG_INFO
+# undef CONFIG_STM32H7_IWDG_REGDEBUG
+#endif
+
+/* REVISIT: It appears that you can only setup the prescaler and reload
+ * registers once. After that, the SR register's PVU and RVU bits never go
+ * to zero. So we defer setting up these registers until the watchdog
+ * is started, then refuse any further attempts to change timeout.
+ */
+
+#define CONFIG_STM32H7_IWDG_ONETIMESETUP 1
+
+/* REVISIT: Another possibility is that we CAN change the prescaler and
+ * reload values after starting the timer. This option is untested but the
+ * implementation place conditioned on the following:
+ */
+
+#undef CONFIG_STM32H7_IWDG_DEFERREDSETUP
+
+/* But you can only try one at a time */
+
+#if defined(CONFIG_STM32H7_IWDG_ONETIMESETUP) && defined(CONFIG_STM32H7_IWDG_DEFERREDSETUP)
+# error "Both CONFIG_STM32H7_IWDG_ONETIMESETUP and CONFIG_STM32H7_IWDG_DEFERREDSETUP are defined"
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* This structure provides the private representation of the "lower-half"
+ * driver state structure. This structure must be cast-compatible with the
+ * well-known watchdog_lowerhalf_s structure.
+ */
+
+struct stm32_lowerhalf_s
+{
+ FAR const struct watchdog_ops_s *ops; /* Lower half operations */
+ uint32_t lsifreq; /* The calibrated frequency of the LSI oscillator */
+ uint32_t timeout; /* The (actual) selected timeout */
+ uint32_t lastreset; /* The last reset time */
+ bool started; /* true: The watchdog timer has been started */
+ uint8_t prescaler; /* Clock prescaler value */
+ uint16_t reload; /* Timer reload value */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* Register operations ******************************************************/
+
+#ifdef CONFIG_STM32H7_IWDG_REGDEBUG
+static uint16_t stm32_getreg(uint32_t addr);
+static void stm32_putreg(uint16_t val, uint32_t addr);
+#else
+# define stm32_getreg(addr) getreg16(addr)
+# define stm32_putreg(val,addr) putreg16(val,addr)
+#endif
+
+static inline void stm32_setprescaler(FAR struct stm32_lowerhalf_s *priv);
+
+/* "Lower half" driver methods **********************************************/
+
+static int stm32_start(FAR struct watchdog_lowerhalf_s *lower);
+static int stm32_stop(FAR struct watchdog_lowerhalf_s *lower);
+static int stm32_keepalive(FAR struct watchdog_lowerhalf_s *lower);
+static int stm32_getstatus(FAR struct watchdog_lowerhalf_s *lower,
+ FAR struct watchdog_status_s *status);
+static int stm32_settimeout(FAR struct watchdog_lowerhalf_s *lower,
+ uint32_t timeout);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* "Lower half" driver methods */
+
+static const struct watchdog_ops_s g_wdgops =
+{
+ .start = stm32_start,
+ .stop = stm32_stop,
+ .keepalive = stm32_keepalive,
+ .getstatus = stm32_getstatus,
+ .settimeout = stm32_settimeout,
+ .capture = NULL,
+ .ioctl = NULL,
+};
+
+/* "Lower half" driver state */
+
+static struct stm32_lowerhalf_s g_wdgdev;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_getreg
+ *
+ * Description:
+ * Get the contents of an STM32 IWDG register
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_STM32H7_IWDG_REGDEBUG
+static uint16_t stm32_getreg(uint32_t addr)
+{
+ static uint32_t prevaddr = 0;
+ static uint32_t count = 0;
+ static uint16_t preval = 0;
+
+ /* Read the value from the register */
+
+ uint16_t val = getreg16(addr);
+
+ /* Is this the same value that we read from the same register last time?
+ * Are we polling the register? If so, suppress some of the output.
+ */
+
+ if (addr == prevaddr && val == preval)
+ {
+ if (count == 0xffffffff || ++count > 3)
+ {
+ if (count == 4)
+ {
+ wdinfo("...\n");
+ }
+
+ return val;
+ }
+ }
+
+ /* No this is a new address or value */
+
+ else
+ {
+ /* Did we print "..." for the previous value? */
+
+ if (count > 3)
+ {
+ /* Yes.. then show how many times the value repeated */
+
+ wdinfo("[repeats %d more times]\n", count - 3);
+ }
+
+ /* Save the new address, value, and count */
+
+ prevaddr = addr;
+ preval = val;
+ count = 1;
+ }
+
+ /* Show the register value read */
+
+ wdinfo("%08x->%04x\n", addr, val);
+ return val;
+}
+#endif
+
+/****************************************************************************
+ * Name: stm32_putreg
+ *
+ * Description:
+ * Set the contents of an STM32 register to a value
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_STM32H7_IWDG_REGDEBUG
+static void stm32_putreg(uint16_t val, uint32_t addr)
+{
+ /* Show the register value being written */
+
+ wdinfo("%08x<-%04x\n", addr, val);
+
+ /* Write the value */
+
+ putreg16(val, addr);
+}
+#endif
+
+/****************************************************************************
+ * Name: stm32_setprescaler
+ *
+ * Description:
+ * Set up the prescaler and reload values. This seems to be something
+ * that can only be done one time.
+ *
+ * Input Parameters:
+ * priv - a pointer to the internal representation of the
+ * "lower-half" driver state structure.
+ *
+ ****************************************************************************/
+
+static inline void stm32_setprescaler(FAR struct stm32_lowerhalf_s *priv)
+{
+ /* Enable write access to IWDG_PR and IWDG_RLR registers */
+
+ stm32_putreg(IWDG_KR_KEY_ENABLE, STM32_IWDG_KR);
+
+ /* Wait for the PVU and RVU bits to be reset be hardware. These bits
+ * were set the last time that the PR register was written and may not
+ * yet be cleared.
+ *
+ * If the setup is only permitted one time, then this wait should not
+ * be necessary.
+ */
+
+#ifndef CONFIG_STM32H7_IWDG_ONETIMESETUP
+ while ((stm32_getreg(STM32_IWDG_SR) & (IWDG_SR_PVU | IWDG_SR_RVU)) != 0);
+#endif
+
+ /* Set the prescaler */
+
+ stm32_putreg((uint16_t)priv->prescaler << IWDG_PR_SHIFT, STM32_IWDG_PR);
+
+ /* Set the reload value */
+
+ stm32_putreg((uint16_t)priv->reload, STM32_IWDG_RLR);
+
+ /* Reload the counter (and disable write access) */
+
+ stm32_putreg(IWDG_KR_KEY_RELOAD, STM32_IWDG_KR);
+}
+
+/****************************************************************************
+ * Name: stm32_start
+ *
+ * Description:
+ * Start the watchdog timer, resetting the time to the current timeout,
+ *
+ * Input Parameters:
+ * lower - a pointer to the publicly visible representation of the
+ * "lower-half" driver state structure.
+ *
+ * Returned Value:
+ * Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int stm32_start(FAR struct watchdog_lowerhalf_s *lower)
+{
+ FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower;
+ irqstate_t flags;
+
+ wdinfo("Entry: started=%d\n");
+ DEBUGASSERT(priv);
+
+ /* Have we already been started? */
+
+ if (!priv->started)
+ {
+ /* REVISIT: It appears that you can only setup the prescaler and
+ * reload registers once. After that, the SR register's PVU and RVU
+ * bits never go to zero. So we defer setting up these registers until
+ * the watchdog is started, then refuse any further attempts to change
+ * timeout.
+ */
+
+ /* Set up prescaler and reload value for the selected timeout before
+ * starting the watchdog timer.
+ */
+
+#if defined(CONFIG_STM32H7_IWDG_ONETIMESETUP) || defined(CONFIG_STM32H7_IWDG_DEFERREDSETUP)
+ stm32_setprescaler(priv);
+#endif
+
+ /* Enable IWDG (the LSI oscillator will be enabled by hardware). NOTE:
+ * If the "Hardware watchdog" feature is enabled through the device
+ * option bits, the watchdog is automatically enabled at power-on.
+ */
+
+ flags = enter_critical_section();
+ stm32_putreg(IWDG_KR_KEY_START, STM32_IWDG_KR);
+ priv->lastreset = clock_systimer();
+ priv->started = true;
+ leave_critical_section(flags);
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: stm32_stop
+ *
+ * Description:
+ * Stop the watchdog timer
+ *
+ * Input Parameters:
+ * lower - a pointer to the publicly visible representation of the
+ * "lower-half" driver state structure.
+ *
+ * Returned Value:
+ * Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int stm32_stop(FAR struct watchdog_lowerhalf_s *lower)
+{
+ /* There is no way to disable the IDWG timer once it has been started */
+
+ wdinfo("Entry\n");
+ return -ENOSYS;
+}
+
+/****************************************************************************
+ * Name: stm32_keepalive
+ *
+ * Description:
+ * Reset the watchdog timer to the current timeout value, prevent any
+ * imminent watchdog timeouts. This is sometimes referred as "pinging"
+ * the watchdog timer or "petting the dog".
+ *
+ * Input Parameters:
+ * lower - a pointer to the publicly visible representation of the
+ * "lower-half" driver state structure.
+ *
+ * Returned Value:
+ * Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int stm32_keepalive(FAR struct watchdog_lowerhalf_s *lower)
+{
+ FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower;
+ irqstate_t flags;
+
+ wdinfo("Entry\n");
+
+ /* Reload the IWDG timer */
+
+ flags = enter_critical_section();
+ stm32_putreg(IWDG_KR_KEY_RELOAD, STM32_IWDG_KR);
+ priv->lastreset = clock_systimer();
+ leave_critical_section(flags);
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: stm32_getstatus
+ *
+ * Description:
+ * Get the current watchdog timer status
+ *
+ * Input Parameters:
+ * lower - a pointer to the publicly visible representation of the
+ * "lower-half" driver state structure.
+ * status - The location to return the watchdog status information.
+ *
+ * Returned Value:
+ * Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int stm32_getstatus(FAR struct watchdog_lowerhalf_s *lower,
+ FAR struct watchdog_status_s *status)
+{
+ FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower;
+ uint32_t ticks;
+ uint32_t elapsed;
+
+ wdinfo("Entry\n");
+ DEBUGASSERT(priv);
+
+ /* Return the status bit */
+
+ status->flags = WDFLAGS_RESET;
+ if (priv->started)
+ {
+ status->flags |= WDFLAGS_ACTIVE;
+ }
+
+ /* Return the actual timeout in milliseconds */
+
+ status->timeout = priv->timeout;
+
+ /* Get the elapsed time since the last ping */
+
+ ticks = clock_systimer() - priv->lastreset;
+ elapsed = (int32_t)TICK2MSEC(ticks);
+
+ if (elapsed > priv->timeout)
+ {
+ elapsed = priv->timeout;
+ }
+
+ /* Return the approximate time until the watchdog timer expiration */
+
+ status->timeleft = priv->timeout - elapsed;
+
+ wdinfo("Status :\n");
+ wdinfo(" flags : %08x\n", status->flags);
+ wdinfo(" timeout : %d\n", status->timeout);
+ wdinfo(" timeleft : %d\n", status->timeleft);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: stm32_settimeout
+ *
+ * Description:
+ * Set a new timeout value (and reset the watchdog timer)
+ *
+ * Input Parameters:
+ * lower - A pointer to the publicly visible representation of the
+ * "lower-half" driver state structure.
+ * timeout - The new timeout value in milliseconds.
+ *
+ * Returned Value:
+ * Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int stm32_settimeout(FAR struct watchdog_lowerhalf_s *lower,
+ uint32_t timeout)
+{
+ FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower;
+ uint32_t fiwdg;
+ uint64_t reload;
+ int prescaler;
+ int shift;
+
+ wdinfo("Entry: timeout=%d\n", timeout);
+ DEBUGASSERT(priv);
+
+ /* Can this timeout be represented? */
+
+ if (timeout < 1 || timeout > IWDG_MAXTIMEOUT)
+ {
+ wderr("ERROR: Cannot represent timeout=%d > %d\n",
+ timeout, IWDG_MAXTIMEOUT);
+ return -ERANGE;
+ }
+
+ /* REVISIT: It appears that you can only setup the prescaler and reload
+ * registers once. After that, the SR register's PVU and RVU bits never go
+ * to zero.
+ */
+
+#ifdef CONFIG_STM32H7_IWDG_ONETIMESETUP
+ if (priv->started)
+ {
+ wdwarn("WARNING: Timer is already started\n");
+ return -EBUSY;
+ }
+#endif
+
+ /* Select the smallest prescaler that will result in a reload value that is
+ * less than the maximum.
+ */
+
+ for (prescaler = 0; ; prescaler++)
+ {
+ /* PR = 0 -> Divider = 4 = 1 << 2
+ * PR = 1 -> Divider = 8 = 1 << 3
+ * PR = 2 -> Divider = 16 = 1 << 4
+ * PR = 3 -> Divider = 32 = 1 << 5
+ * PR = 4 -> Divider = 64 = 1 << 6
+ * PR = 5 -> Divider = 128 = 1 << 7
+ * PR = 6 -> Divider = 256 = 1 << 8
+ * PR = n -> Divider = 1 << (n+2)
+ */
+
+ shift = prescaler + 2;
+
+ /* Get the IWDG counter frequency in Hz. For a nominal 32Khz LSI clock,
+ * this is value in the range of 7500 and 125.
+ */
+
+ fiwdg = priv->lsifreq >> shift;
+
+ /* We want:
+ * 1000 * reload / Fiwdg = timeout
+ * Or:
+ * reload = Fiwdg * timeout / 1000
+ */
+
+ reload = (uint64_t)fiwdg * (uint64_t)timeout / 1000;
+
+ /* If this reload valid is less than the maximum or we are not ready
+ * at the prescaler value, then break out of the loop to use these
+ * settings.
+ */
+
+ if (reload <= IWDG_RLR_MAX || prescaler == 6)
+ {
+ /* Note that we explicitly break out of the loop rather than using
+ * the 'for' loop termination logic because we do not want the
+ * value of prescaler to be incremented.
+ */
+
+ break;
+ }
+ }
+
+ /* Make sure that the final reload value is within range */
+
+ if (reload > IWDG_RLR_MAX)
+ {
+ reload = IWDG_RLR_MAX;
+ }
+
+ /* Get the actual timeout value in milliseconds.
+ *
+ * We have:
+ * reload = Fiwdg * timeout / 1000
+ * So we want:
+ * timeout = 1000 * reload / Fiwdg
+ */
+
+ priv->timeout = (1000 * (uint32_t)reload) / fiwdg;
+
+ /* Save setup values for later use */
+
+ priv->prescaler = prescaler;
+ priv->reload = reload;
+
+ /* Write the prescaler and reload values to the IWDG registers.
+ *
+ * REVISIT: It appears that you can only setup the prescaler and reload
+ * registers once. After that, the SR register's PVU and RVU bits never go
+ * to zero.
+ */
+
+#ifndef CONFIG_STM32H7_IWDG_ONETIMESETUP
+ /* If CONFIG_STM32H7_IWDG_DEFERREDSETUP is selected, then perform the
+ * register configuration only if the timer has been started.
+ */
+
+#ifdef CONFIG_STM32H7_IWDG_DEFERREDSETUP
+ if (priv->started)
+#endif
+ {
+ stm32_setprescaler(priv);
+ }
+#endif
+
+ wdinfo("prescaler=%d fiwdg=%d reload=%d\n", prescaler, fiwdg, reload);
+
+ return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_iwdginitialize
+ *
+ * Description:
+ * Initialize the IWDG watchdog timer. The watchdog timer is initialized
+ * and registers as 'devpath'. The initial state of the watchdog timer is
+ * disabled.
+ *
+ * Input Parameters:
+ * devpath - The full path to the watchdog. This should be of the form
+ * /dev/watchdog0
+ * lsifreq - The calibrated LSI clock frequency
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void stm32_iwdginitialize(FAR const char *devpath, uint32_t lsifreq)
+{
+ FAR struct stm32_lowerhalf_s *priv = &g_wdgdev;
+
+ wdinfo("Entry: devpath=%s lsifreq=%d\n", devpath, lsifreq);
+
+ /* NOTE we assume that clocking to the IWDG has already been provided by
+ * the RCC initialization logic.
+ */
+
+ /* Initialize the driver state structure. */
+
+ priv->ops = &g_wdgops;
+ priv->lsifreq = lsifreq;
+ priv->started = false;
+
+ /* Make sure that the LSI oscillator is enabled. NOTE: The LSI oscillator
+ * is enabled here but is not disabled by this file, because this file does
+ * not know the global usage of the oscillator. Any clock management
+ * logic (say, as part of a power management scheme) needs handle other
+ * LSI controls outside of this file.
+ */
+
+ stm32_rcc_enablelsi();
+ wdinfo("RCC CSR: %08x\n", getreg32(STM32_RCC_CSR));
+
+ /* Select an arbitrary initial timeout value. But don't start the watchdog
+ * yet. NOTE: If the "Hardware watchdog" feature is enabled through the
+ * device option bits, the watchdog is automatically enabled at power-on.
+ */
+
+ stm32_settimeout((FAR struct watchdog_lowerhalf_s *)priv,
+ CONFIG_STM32H7_IWDG_DEFTIMOUT);
+
+ /* Register the watchdog driver as /dev/watchdog0 */
+
+ watchdog_register(devpath, (FAR struct watchdog_lowerhalf_s *)priv);
+
+ /* When the microcontroller enters debug mode (Cortex-M4F core halted),
+ * the IWDG counter either continues to work normally or stops, depending
+ * on DBG_IWDG_STOP configuration bit in DBG module.
+ */
+
+#if defined(CONFIG_STM32H7_JTAG_FULL_ENABLE) || \
+ defined(CONFIG_STM32H7_JTAG_NOJNTRST_ENABLE) || \
+ defined(CONFIG_STM32H7_JTAG_SW_ENABLE)
+ {
+ uint32_t cr = getreg32(STM32_DBGMCU_APB4_FZ1);
+ cr |= DBGMCU_APB4_WDGLSD1;
+ putreg32(cr, STM32_DBGMCU_APB4_FZ1);
+ }
+#endif
+}
+
+#endif /* CONFIG_WATCHDOG && CONFIG_STM32H7_IWDG */
diff --git a/arch/arm/src/stm32h7/stm32_ethernet.h b/arch/arm/src/stm32h7/stm32_pm.h
similarity index 60%
copy from arch/arm/src/stm32h7/stm32_ethernet.h
copy to arch/arm/src/stm32h7/stm32_pm.h
index fdb1ad5..bcbc899 100644
--- a/arch/arm/src/stm32h7/stm32_ethernet.h
+++ b/arch/arm/src/stm32h7/stm32_pm.h
@@ -1,8 +1,8 @@
/****************************************************************************
- * arch/arm/src/stm32h7/stm32_ethernet.h
+ * arch/arm/src/stm32h7/stm32_pm.h
*
- * Copyright (C) 2015 Gregory Nutt. All rights reserved.
- * Author: Gregory Nutt <gn...@nuttx.org>
+ * Copyright (C) 2018 Haltian Ltd. All rights reserved.
+ * Author: Juha Niskanen <ju...@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -33,8 +33,8 @@
*
****************************************************************************/
-#ifndef __ARCH_ARM_SRC_STM32H7_STM32_ETHERNET_H
-#define __ARCH_ARM_SRC_STM32H7_STM32_ETHERNET_H
+#ifndef __ARCH_ARM_SRC_STM32H7_STM32_PM_H
+#define __ARCH_ARM_SRC_STM32H7_STM32_PM_H
/****************************************************************************
* Included Files
@@ -42,17 +42,17 @@
#include <nuttx/config.h>
-#include "hardware/stm32_ethernet.h"
+#include <stdbool.h>
-#if STM32H7_NETHERNET > 0
-#ifndef __ASSEMBLY__
+#include "chip.h"
+#include "up_internal.h"
/****************************************************************************
- * Public Functions
+ * Public Function Prototypes
****************************************************************************/
-#undef EXTERN
-#if defined(__cplusplus)
+#ifndef __ASSEMBLY__
+#ifdef __cplusplus
#define EXTERN extern "C"
extern "C"
{
@@ -61,59 +61,62 @@ extern "C"
#endif
/****************************************************************************
- * Function: stm32_ethinitialize
+ * Name: stm32_pmstop
*
* Description:
- * Initialize the Ethernet driver for one interface. If the STM32 chip
- * supports multiple Ethernet controllers, then board specific logic must
- * implement up_netinitialize() and call this function to initialize the
- * desired interfaces.
+ * Enter STOP mode.
*
- * Parameters:
- * intf - In the case where there are multiple EMACs, this value identifies
- * which EMAC is to be initialized.
+ * Input Parameters:
+ * lpds - true: To further reduce power consumption in Stop mode, put the
+ * internal voltage regulator in low-power under-drive mode using
+ * the LPDS and LPUDS bits of the Power control register (PWR_CR1).
*
* Returned Value:
- * OK on success; Negated errno on failure.
- *
- * Assumptions:
+ * None
*
****************************************************************************/
-#if STM32H7_NETHERNET > 1
-int stm32_ethinitialize(int intf);
-#endif
+void stm32_pmstop(bool lpds);
/****************************************************************************
- * Function: stm32_phy_boardinitialize
+ * Name: stm32_pmstandby
*
* Description:
- * Some boards require specialized initialization of the PHY before it can
- * be used. This may include such things as configuring GPIOs, resetting
- * the PHY, etc. If CONFIG_STM32H7_PHYINIT is defined in the configuration
- * then the board specific logic must provide stm32_phyinitialize(); The
- * STM32 Ethernet driver will call this function one time before it first
- * uses the PHY.
+ * Enter STANDBY mode.
*
- * Parameters:
- * intf - Always zero for now.
+ * Input Parameters:
+ * None
*
* Returned Value:
- * OK on success; Negated errno on failure.
+ * None
*
- * Assumptions:
+ ****************************************************************************/
+
+void stm32_pmstandby(void);
+
+/****************************************************************************
+ * Name: stm32_pmsleep
*
- ***************************************************************************/
+ * Description:
+ * Enter SLEEP mode.
+ *
+ * Input Parameters:
+ * sleeponexit - true: SLEEPONEXIT bit is set when the WFI instruction is
+ * executed, the MCU enters Sleep mode as soon as it
+ * exits the lowest priority ISR.
+ * - false: SLEEPONEXIT bit is cleared, the MCU enters Sleep
+ * mode as soon as WFI or WFE instruction is executed.
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
-#ifdef CONFIG_STM32H7_PHYINIT
-int stm32_phy_boardinitialize(int intf);
-#endif
+void stm32_pmsleep(bool sleeponexit);
#undef EXTERN
-#if defined(__cplusplus)
+#ifdef __cplusplus
}
#endif
-
#endif /* __ASSEMBLY__ */
-#endif /* STM32H7_NETHERNET > 0 */
-#endif /* __ARCH_ARM_SRC_STM32H7_STM32_ETHERNET_H */
+
+#endif /* __ARCH_ARM_SRC_STM32H7_STM32_PM_H */
diff --git a/arch/arm/src/stm32h7/stm32_ethernet.h b/arch/arm/src/stm32h7/stm32_pminitialize.c
similarity index 54%
copy from arch/arm/src/stm32h7/stm32_ethernet.h
copy to arch/arm/src/stm32h7/stm32_pminitialize.c
index fdb1ad5..14914b4 100644
--- a/arch/arm/src/stm32h7/stm32_ethernet.h
+++ b/arch/arm/src/stm32h7/stm32_pminitialize.c
@@ -1,7 +1,7 @@
/****************************************************************************
- * arch/arm/src/stm32h7/stm32_ethernet.h
+ * arch/arm/src/stm32h7/stm32_pminitialize.c
*
- * Copyright (C) 2015 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2012, 2017, 2020 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gn...@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -33,87 +33,46 @@
*
****************************************************************************/
-#ifndef __ARCH_ARM_SRC_STM32H7_STM32_ETHERNET_H
-#define __ARCH_ARM_SRC_STM32H7_STM32_ETHERNET_H
-
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
-#include "hardware/stm32_ethernet.h"
+#include <nuttx/power/pm.h>
+
+#include "up_internal.h"
+#include "stm32_pm.h"
-#if STM32H7_NETHERNET > 0
-#ifndef __ASSEMBLY__
+#ifdef CONFIG_PM
/****************************************************************************
* Public Functions
****************************************************************************/
-#undef EXTERN
-#if defined(__cplusplus)
-#define EXTERN extern "C"
-extern "C"
-{
-#else
-#define EXTERN extern
-#endif
-
/****************************************************************************
- * Function: stm32_ethinitialize
+ * Name: up_pminitialize
*
* Description:
- * Initialize the Ethernet driver for one interface. If the STM32 chip
- * supports multiple Ethernet controllers, then board specific logic must
- * implement up_netinitialize() and call this function to initialize the
- * desired interfaces.
+ * This function is called by MCU-specific logic at power-on reset in
+ * order to provide one-time initialization the power management subsystem.
+ * This function must be called *very* early in the initialization sequence
+ * *before* any other device drivers are initialized (since they may
+ * attempt to register with the power management subsystem).
*
- * Parameters:
- * intf - In the case where there are multiple EMACs, this value identifies
- * which EMAC is to be initialized.
+ * Input Parameters:
+ * None.
*
* Returned Value:
- * OK on success; Negated errno on failure.
- *
- * Assumptions:
+ * None.
*
****************************************************************************/
-#if STM32H7_NETHERNET > 1
-int stm32_ethinitialize(int intf);
-#endif
-
-/****************************************************************************
- * Function: stm32_phy_boardinitialize
- *
- * Description:
- * Some boards require specialized initialization of the PHY before it can
- * be used. This may include such things as configuring GPIOs, resetting
- * the PHY, etc. If CONFIG_STM32H7_PHYINIT is defined in the configuration
- * then the board specific logic must provide stm32_phyinitialize(); The
- * STM32 Ethernet driver will call this function one time before it first
- * uses the PHY.
- *
- * Parameters:
- * intf - Always zero for now.
- *
- * Returned Value:
- * OK on success; Negated errno on failure.
- *
- * Assumptions:
- *
- ***************************************************************************/
-
-#ifdef CONFIG_STM32H7_PHYINIT
-int stm32_phy_boardinitialize(int intf);
-#endif
+void up_pminitialize(void)
+{
+ /* Then initialize the NuttX power management subsystem proper */
-#undef EXTERN
-#if defined(__cplusplus)
+ pm_initialize();
}
-#endif
-#endif /* __ASSEMBLY__ */
-#endif /* STM32H7_NETHERNET > 0 */
-#endif /* __ARCH_ARM_SRC_STM32H7_STM32_ETHERNET_H */
+#endif /* CONFIG_PM */
diff --git a/arch/arm/src/stm32h7/stm32_ethernet.h b/arch/arm/src/stm32h7/stm32_pmsleep.c
similarity index 53%
copy from arch/arm/src/stm32h7/stm32_ethernet.h
copy to arch/arm/src/stm32h7/stm32_pmsleep.c
index fdb1ad5..d77da01 100644
--- a/arch/arm/src/stm32h7/stm32_ethernet.h
+++ b/arch/arm/src/stm32h7/stm32_pmsleep.c
@@ -1,8 +1,9 @@
/****************************************************************************
- * arch/arm/src/stm32h7/stm32_ethernet.h
+ * arch/arm/src/stm32h7/stm32_pmsleep.c
*
- * Copyright (C) 2015 Gregory Nutt. All rights reserved.
- * Author: Gregory Nutt <gn...@nuttx.org>
+ * Copyright (C) 2012, 2017, 2020 Gregory Nutt. All rights reserved.
+ * Authors: Gregory Nutt <gn...@nuttx.org>
+ * Diego Sanchez <ds...@nx-engineering.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -33,87 +34,68 @@
*
****************************************************************************/
-#ifndef __ARCH_ARM_SRC_STM32H7_STM32_ETHERNET_H
-#define __ARCH_ARM_SRC_STM32H7_STM32_ETHERNET_H
-
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
-#include "hardware/stm32_ethernet.h"
+#include <stdbool.h>
-#if STM32H7_NETHERNET > 0
-#ifndef __ASSEMBLY__
+#include "up_arch.h"
+#include "nvic.h"
+#include "stm32_pwr.h"
+#include "stm32_pm.h"
/****************************************************************************
* Public Functions
****************************************************************************/
-#undef EXTERN
-#if defined(__cplusplus)
-#define EXTERN extern "C"
-extern "C"
-{
-#else
-#define EXTERN extern
-#endif
-
/****************************************************************************
- * Function: stm32_ethinitialize
+ * Name: stm32_pmsleep
*
* Description:
- * Initialize the Ethernet driver for one interface. If the STM32 chip
- * supports multiple Ethernet controllers, then board specific logic must
- * implement up_netinitialize() and call this function to initialize the
- * desired interfaces.
- *
- * Parameters:
- * intf - In the case where there are multiple EMACs, this value identifies
- * which EMAC is to be initialized.
+ * Enter SLEEP mode.
*
+ * Input Parameters:
+ * sleeponexit - true: SLEEPONEXIT bit is set when the WFI instruction is
+ * executed, the MCU enters Sleep mode as soon as it
+ * exits the lowest priority ISR.
+ * - false: SLEEPONEXIT bit is cleared, the MCU enters Sleep
+ * mode as soon as WFI or WFE instruction is executed.
* Returned Value:
- * OK on success; Negated errno on failure.
- *
- * Assumptions:
+ * None
*
****************************************************************************/
-#if STM32H7_NETHERNET > 1
-int stm32_ethinitialize(int intf);
-#endif
+void stm32_pmsleep(bool sleeponexit)
+{
+ uint32_t regval;
-/****************************************************************************
- * Function: stm32_phy_boardinitialize
- *
- * Description:
- * Some boards require specialized initialization of the PHY before it can
- * be used. This may include such things as configuring GPIOs, resetting
- * the PHY, etc. If CONFIG_STM32H7_PHYINIT is defined in the configuration
- * then the board specific logic must provide stm32_phyinitialize(); The
- * STM32 Ethernet driver will call this function one time before it first
- * uses the PHY.
- *
- * Parameters:
- * intf - Always zero for now.
- *
- * Returned Value:
- * OK on success; Negated errno on failure.
- *
- * Assumptions:
- *
- ***************************************************************************/
+ /* Clear SLEEPDEEP bit of Cortex System Control Register */
-#ifdef CONFIG_STM32H7_PHYINIT
-int stm32_phy_boardinitialize(int intf);
-#endif
+ regval = getreg32(NVIC_SYSCON);
+ regval &= ~NVIC_SYSCON_SLEEPDEEP;
+ if (sleeponexit)
+ {
+ regval |= NVIC_SYSCON_SLEEPONEXIT;
+ }
+ else
+ {
+ regval &= ~NVIC_SYSCON_SLEEPONEXIT;
+ }
-#undef EXTERN
-#if defined(__cplusplus)
-}
-#endif
+ putreg32(regval, NVIC_SYSCON);
-#endif /* __ASSEMBLY__ */
-#endif /* STM32H7_NETHERNET > 0 */
-#endif /* __ARCH_ARM_SRC_STM32H7_STM32_ETHERNET_H */
+ /* Sleep until the wakeup interrupt or event occurs */
+
+#ifdef CONFIG_PM_WFE
+ /* Mode: SLEEP + Entry with WFE */
+
+ asm("wfe");
+#else
+ /* Mode: SLEEP + Entry with WFI */
+
+ asm("wfi");
+#endif
+}
diff --git a/arch/arm/src/stm32h7/stm32_ethernet.h b/arch/arm/src/stm32h7/stm32_pmstandby.c
similarity index 53%
copy from arch/arm/src/stm32h7/stm32_ethernet.h
copy to arch/arm/src/stm32h7/stm32_pmstandby.c
index fdb1ad5..bddcfc1 100644
--- a/arch/arm/src/stm32h7/stm32_ethernet.h
+++ b/arch/arm/src/stm32h7/stm32_pmstandby.c
@@ -1,8 +1,8 @@
/****************************************************************************
- * arch/arm/src/stm32h7/stm32_ethernet.h
+ * arch/arm/src/stm32h7/stm32_pmstandby.c
*
- * Copyright (C) 2015 Gregory Nutt. All rights reserved.
- * Author: Gregory Nutt <gn...@nuttx.org>
+ * Copyright (C) 2018 Haltian Ltd. All rights reserved.
+ * Author: Juha Niskanen <ju...@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -33,87 +33,68 @@
*
****************************************************************************/
-#ifndef __ARCH_ARM_SRC_STM32H7_STM32_ETHERNET_H
-#define __ARCH_ARM_SRC_STM32H7_STM32_ETHERNET_H
-
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
-#include "hardware/stm32_ethernet.h"
+#include <stdbool.h>
-#if STM32H7_NETHERNET > 0
-#ifndef __ASSEMBLY__
+#include "up_arch.h"
+#include "nvic.h"
+#include "stm32_rcc.h"
+#include "stm32_pwr.h"
+#include "stm32_pm.h"
/****************************************************************************
* Public Functions
****************************************************************************/
-#undef EXTERN
-#if defined(__cplusplus)
-#define EXTERN extern "C"
-extern "C"
-{
-#else
-#define EXTERN extern
-#endif
-
/****************************************************************************
- * Function: stm32_ethinitialize
+ * Name: stm32_pmstandby
*
* Description:
- * Initialize the Ethernet driver for one interface. If the STM32 chip
- * supports multiple Ethernet controllers, then board specific logic must
- * implement up_netinitialize() and call this function to initialize the
- * desired interfaces.
+ * Enter STANDBY mode.
*
- * Parameters:
- * intf - In the case where there are multiple EMACs, this value identifies
- * which EMAC is to be initialized.
+ * Input Parameters:
+ * None
*
* Returned Value:
- * OK on success; Negated errno on failure.
- *
- * Assumptions:
+ * None
*
****************************************************************************/
-#if STM32H7_NETHERNET > 1
-int stm32_ethinitialize(int intf);
-#endif
+void stm32_pmstandby(void)
+{
+ uint32_t regval;
-/****************************************************************************
- * Function: stm32_phy_boardinitialize
- *
- * Description:
- * Some boards require specialized initialization of the PHY before it can
- * be used. This may include such things as configuring GPIOs, resetting
- * the PHY, etc. If CONFIG_STM32H7_PHYINIT is defined in the configuration
- * then the board specific logic must provide stm32_phyinitialize(); The
- * STM32 Ethernet driver will call this function one time before it first
- * uses the PHY.
- *
- * Parameters:
- * intf - Always zero for now.
- *
- * Returned Value:
- * OK on success; Negated errno on failure.
- *
- * Assumptions:
- *
- ***************************************************************************/
+ /* Clear the wake-up flags before reseting. */
-#ifdef CONFIG_STM32H7_PHYINIT
-int stm32_phy_boardinitialize(int intf);
-#endif
+ modifyreg32(STM32_PWR_CPUCR, 0, STM32_PWR_CPUCR_CSSF);
+ modifyreg32(STM32_PWR_WKUPCR, 0, STM32_PWR_WKUPC1 | STM32_PWR_WKUPC2 |
+ STM32_PWR_WKUPC3 | STM32_PWR_WKUPC4 |
+ STM32_PWR_WKUPC5 | STM32_PWR_WKUPC6);
-#undef EXTERN
-#if defined(__cplusplus)
-}
-#endif
+ /* Clear reset flags. */
+
+ modifyreg32(STM32_RCC_CSR, 0, RCC_RSR_RMVF);
+
+ /* Set the domain Power Down Deep Sleep (PDDS) bits in the power control
+ * register so that D1, D2, and D3 will go into the DStop state.
+ */
-#endif /* __ASSEMBLY__ */
-#endif /* STM32H7_NETHERNET > 0 */
-#endif /* __ARCH_ARM_SRC_STM32H7_STM32_ETHERNET_H */
+ modifyreg32(STM32_PWR_CPUCR, 0, STM32_PWR_CPUCR_PDDS_D1 |
+ STM32_PWR_CPUCR_PDDS_D2 |
+ STM32_PWR_CPUCR_PDDS_D3);
+
+ /* Set SLEEPDEEP bit of Cortex System Control Register */
+
+ regval = getreg32(NVIC_SYSCON);
+ regval |= NVIC_SYSCON_SLEEPDEEP;
+ putreg32(regval, NVIC_SYSCON);
+
+ /* Sleep until the wakeup reset occurs */
+
+ asm("wfi");
+}
diff --git a/arch/arm/src/stm32h7/stm32_ethernet.h b/arch/arm/src/stm32h7/stm32_pmstop.c
similarity index 53%
copy from arch/arm/src/stm32h7/stm32_ethernet.h
copy to arch/arm/src/stm32h7/stm32_pmstop.c
index fdb1ad5..5c6f005 100644
--- a/arch/arm/src/stm32h7/stm32_ethernet.h
+++ b/arch/arm/src/stm32h7/stm32_pmstop.c
@@ -1,8 +1,8 @@
/****************************************************************************
- * arch/arm/src/stm32h7/stm32_ethernet.h
+ * arch/arm/src/stm32h7/stm32_pmstop.c
*
- * Copyright (C) 2015 Gregory Nutt. All rights reserved.
- * Author: Gregory Nutt <gn...@nuttx.org>
+ * Copyright (C) 2018 Haltian Ltd. All rights reserved.
+ * Author: Juha Niskanen <ju...@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -33,87 +33,95 @@
*
****************************************************************************/
-#ifndef __ARCH_ARM_SRC_STM32H7_STM32_ETHERNET_H
-#define __ARCH_ARM_SRC_STM32H7_STM32_ETHERNET_H
-
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
-#include "hardware/stm32_ethernet.h"
+#include <stdbool.h>
-#if STM32H7_NETHERNET > 0
-#ifndef __ASSEMBLY__
+#include "up_arch.h"
+#include "nvic.h"
+#include "stm32_pwr.h"
+#include "stm32_pm.h"
/****************************************************************************
* Public Functions
****************************************************************************/
-#undef EXTERN
-#if defined(__cplusplus)
-#define EXTERN extern "C"
-extern "C"
-{
-#else
-#define EXTERN extern
-#endif
-
/****************************************************************************
- * Function: stm32_ethinitialize
+ * Name: stm32_pmstop
*
* Description:
- * Initialize the Ethernet driver for one interface. If the STM32 chip
- * supports multiple Ethernet controllers, then board specific logic must
- * implement up_netinitialize() and call this function to initialize the
- * desired interfaces.
+ * Enter STOP mode.
*
- * Parameters:
- * intf - In the case where there are multiple EMACs, this value identifies
- * which EMAC is to be initialized.
+ * Input Parameters:
+ * lpds - true: To further reduce power consumption in Stop mode, put the
+ * internal voltage regulator in low-power under-drive mode using
+ * the LPDS and LPUDS bits of the Power control register (PWR_CR1).
*
* Returned Value:
- * OK on success; Negated errno on failure.
- *
- * Assumptions:
+ * None
*
****************************************************************************/
-#if STM32H7_NETHERNET > 1
-int stm32_ethinitialize(int intf);
-#endif
+void stm32_pmstop(bool lpds)
+{
+ uint32_t regval;
-/****************************************************************************
- * Function: stm32_phy_boardinitialize
- *
- * Description:
- * Some boards require specialized initialization of the PHY before it can
- * be used. This may include such things as configuring GPIOs, resetting
- * the PHY, etc. If CONFIG_STM32H7_PHYINIT is defined in the configuration
- * then the board specific logic must provide stm32_phyinitialize(); The
- * STM32 Ethernet driver will call this function one time before it first
- * uses the PHY.
- *
- * Parameters:
- * intf - Always zero for now.
- *
- * Returned Value:
- * OK on success; Negated errno on failure.
- *
- * Assumptions:
- *
- ***************************************************************************/
+ /* Clear the Low Power Deep Sleep (LPDS) bit in the CPU power control
+ * register.
+ */
-#ifdef CONFIG_STM32H7_PHYINIT
-int stm32_phy_boardinitialize(int intf);
-#endif
+ regval = getreg32(STM32_PWR_CR1);
+ regval &= ~(PWR_CR1_LPDS | PWR_CR1_SVOS_MASK);
-#undef EXTERN
-#if defined(__cplusplus)
-}
+ /* Set low-power regulator mode and voltage scaling. */
+
+ if (lpds)
+ {
+ regval |= PWR_CR1_LPDS | PWR_CR1_SVOS_S5;
+ }
+ else
+ {
+ /* Set regulator to normal (S3) mode */
+
+ regval |= PWR_CR1_SVOS_S3;
+ }
+
+ putreg32(regval, STM32_PWR_CR1);
+
+ /* Clear the domain standby bits so D1, D2 and D3 remain in DStop mode */
+
+ regval = getreg32(STM32_PWR_CPUCR);
+ regval &= ~(STM32_PWR_CPUCR_PDDS_D1 | STM32_PWR_CPUCR_PDDS_D2 |
+ STM32_PWR_CPUCR_PDDS_D3);
+ putreg32(regval, STM32_PWR_CPUCR);
+
+ /* Set SLEEPDEEP bit of Cortex System Control Register */
+
+ regval = getreg32(NVIC_SYSCON);
+ regval |= NVIC_SYSCON_SLEEPDEEP;
+ putreg32(regval, NVIC_SYSCON);
+
+ /* Sleep until the wakeup interrupt or event occurs */
+
+#ifdef CONFIG_PM_WFE
+ /* Mode: SLEEP + Entry with WFE */
+
+ asm volatile ("wfe");
+#else
+ /* Mode: SLEEP + Entry with WFI */
+
+ asm volatile ("wfi");
#endif
-#endif /* __ASSEMBLY__ */
-#endif /* STM32H7_NETHERNET > 0 */
-#endif /* __ARCH_ARM_SRC_STM32H7_STM32_ETHERNET_H */
+ /* Clear deep sleep bits, so that MCU does not go into deep sleep in idle. */
+
+ /* Clear SLEEPDEEP bit of Cortex System Control Register */
+
+ regval = getreg32(NVIC_SYSCON);
+ regval &= ~NVIC_SYSCON_SLEEPDEEP;
+ putreg32(regval, NVIC_SYSCON);
+}
diff --git a/arch/arm/src/stm32h7/stm32_pwr.c b/arch/arm/src/stm32h7/stm32_pwr.c
index 71c041c..e087b4f 100644
--- a/arch/arm/src/stm32h7/stm32_pwr.c
+++ b/arch/arm/src/stm32h7/stm32_pwr.c
@@ -50,6 +50,7 @@
#include "barriers.h"
#include "up_arch.h"
#include "stm32_pwr.h"
+#include "stm32_gpio.h"
#if defined(CONFIG_STM32H7_PWR)
@@ -269,12 +270,13 @@ void stm32_pwr_disablepvd(void)
* Description:
* Enables the Backup regulator, the Backup regulator (used to maintain backup
* SRAM content in Standby and VBAT modes) is enabled. If BRE is reset, the backup
- * regulator is switched off. The backup SRAM can still be used but its content will
- * be lost in the Standby and VBAT modes. Once set, the application must wait that
- * the Backup Regulator Ready flag (BRR) is set to indicate that the data written
- * into the RAM will be maintained in the Standby and VBAT modes.
+ * regulator is switched off. The backup SRAM can still be used but its content
+ * will be lost in the Standby and VBAT modes. Once set, the application must wait
+ * that the Backup Regulator Ready flag (BRR) is set to indicate that the data
+ * written into the RAM will be maintained in the Standby and VBAT modes.
*
- * This function need to be called after stm32_pwr_enablebkp(true) has ben called.
+ * This function needs to be called after stm32_pwr_enablebkp(true) has been
+ * called.
*
* Input Parameters:
* region - state to set it to
@@ -316,4 +318,122 @@ void stm32_pwr_enablebreg(bool region)
leave_critical_section(flags);
}
+
+/************************************************************************************
+ * Name: stm32_pwr_configurewkup
+ *
+ * Description:
+ * Configures the external wakeup (WKUP) signals for wakeup from standby mode.
+ * Sets rising/falling edge sensitivity and pull state.
+ *
+ *
+ * Input Parameters:
+ * pin - WKUP pin number (0-5) to work on
+ * en - Enables the specified WKUP pin if true
+ * rising - If true, wakeup is triggered on rising edge, otherwise,
+ * it is triggered on the falling edge.
+ * pull - Specifies the WKUP pin pull resistor configuration
+ * (GPIO_FLOAT, GPIO_PULLUP, or GPIO_PULLDOWN)
+ *
+ * Returned Value:
+ * None
+ *
+ ************************************************************************************/
+
+void stm32_pwr_configurewkup(uint32_t pin, bool en, bool rising, uint32_t pull)
+{
+ irqstate_t flags;
+ uint32_t regval;
+
+ DEBUGASSERT(pin < 6);
+
+ flags = enter_critical_section();
+
+ regval = stm32_pwr_getreg(STM32_PWR_WKUPEPR_OFFSET);
+
+ if (en)
+ {
+ regval |= STM32_PWR_WKUPEN(pin);
+ }
+ else
+ {
+ regval &= ~STM32_PWR_WKUPEN(pin);
+ }
+
+ if (rising)
+ {
+ regval &= ~STM32_PWR_WKUPP(pin);
+ }
+ else
+ {
+ regval |= STM32_PWR_WKUPP(pin);
+ }
+
+ /* Set to the no pull-up state by default*/
+
+ regval &= ~ (STM32_PWR_WKUPPUPD_MASK << STM32_PWR_WKUPPUPD_SHIFT(pin));
+
+ if (pull == GPIO_PULLUP)
+ {
+ regval |= STM32_PWR_WKUPPUPD_PULLUP << STM32_PWR_WKUPPUPD_SHIFT(pin);
+ }
+ else if (pull == GPIO_PULLDOWN)
+ {
+ regval |= STM32_PWR_WKUPPUPD_PULLDN << STM32_PWR_WKUPPUPD_SHIFT(pin);
+ }
+
+ stm32_pwr_putreg(STM32_PWR_WKUPEPR_OFFSET, regval);
+
+ leave_critical_section(flags);
+}
+
+/************************************************************************************
+ * Name: stm32_pwr_setvbatcharge
+ *
+ * Description:
+ * Configures the internal charge resistor to charge a battery attached to
+ * the VBAT pin.
+ *
+ *
+ * Input Parameters:
+ * enable - Enables the charge resistor if true, disables it if false
+ * resistor - Sets charge resistor to 1.5 KOhm if true,
+ * sets it to 5 KOhm if false.
+ *
+ * Returned Value:
+ * None
+ *
+ ************************************************************************************/
+
+void stm32_pwr_setvbatcharge(bool enable, bool resistor)
+{
+ irqstate_t flags;
+ uint32_t regval;
+
+ flags = enter_critical_section();
+
+ regval = stm32_pwr_getreg(STM32_PWR_CR3_OFFSET);
+
+ if (enable)
+ {
+ regval |= STM32_PWR_CR3_VBE;
+ }
+ else
+ {
+ regval &= ~STM32_PWR_CR3_VBE;
+ }
+
+ if (resistor)
+ {
+ regval |= STM32_PWR_CR3_VBRS;
+ }
+ else
+ {
+ regval &= ~STM32_PWR_CR3_VBRS;
+ }
+
+ stm32_pwr_putreg(STM32_PWR_CR3_OFFSET, regval);
+
+ leave_critical_section(flags);
+}
#endif /* CONFIG_STM32_PWR */
diff --git a/arch/arm/src/stm32h7/stm32_pwr.h b/arch/arm/src/stm32h7/stm32_pwr.h
index a9b529c..eb4d614 100644
--- a/arch/arm/src/stm32h7/stm32_pwr.h
+++ b/arch/arm/src/stm32h7/stm32_pwr.h
@@ -63,7 +63,7 @@ extern "C"
#endif
/************************************************************************************
- * Public Functions
+ * Public Function Prototypes
************************************************************************************/
/************************************************************************************
@@ -110,10 +110,13 @@ void stm32_pwr_enablebkp(bool writable);
* Description:
* Enables the Backup regulator, the Backup regulator (used to maintain backup
* SRAM content in Standby and VBAT modes) is enabled. If BRE is reset, the backup
- * regulator is switched off. The backup SRAM can still be used but its content will
- * be lost in the Standby and VBAT modes. Once set, the application must wait that
- * the Backup Regulator Ready flag (BRR) is set to indicate that the data written
- * into the RAM will be maintained in the Standby and VBAT modes.
+ * regulator is switched off. The backup SRAM can still be used but its content
+ * will be lost in the Standby and VBAT modes. Once set, the application must wait
+ * that the Backup Regulator Ready flag (BRR) is set to indicate that the data
+ * written into the RAM will be maintained in the Standby and VBAT modes.
+ *
+ * This function needs to be called after stm32_pwr_enablebkp(true) has been
+ * called.
*
* Input Parameters:
* region - state to set it to
@@ -125,6 +128,49 @@ void stm32_pwr_enablebkp(bool writable);
void stm32_pwr_enablebreg(bool region);
+/************************************************************************************
+ * Name: stm32_pwr_configurewkup
+ *
+ * Description:
+ * Configures the external wakeup (WKUP) signals for wakeup from standby mode.
+ * Sets rising/falling edge sensitivity and pull state.
+ *
+ *
+ * Input Parameters:
+ * pin - WKUP pin number (0-5) to work on
+ * en - Enables the specified WKUP pin if true
+ * rising - If true, wakeup is triggered on rising edge, otherwise,
+ * it is triggered on the falling edge.
+ * pull - Specifies the WKUP pin pull resistor configuration
+ * (GPIO_FLOAT, GPIO_PULLUP, or GPIO_PULLDOWN)
+ *
+ * Returned Value:
+ * None
+ *
+ ************************************************************************************/
+
+void stm32_pwr_configurewkup(uint32_t pin, bool en, bool rising, uint32_t pull);
+
+/************************************************************************************
+ * Name: stm32_pwr_setvbatcharge
+ *
+ * Description:
+ * Configures the internal charge resistor to charge a battery attached to
+ * the VBAT pin.
+ *
+ *
+ * Input Parameters:
+ * enable - Enables the charge resistor if true, disables it if false
+ * resistor - Sets charge resistor to 1.5 KOhm if true,
+ * sets it to 5 KOhm if false.
+ *
+ * Returned Value:
+ * None
+ *
+ ************************************************************************************/
+
+void stm32_pwr_setvbatcharge(bool enable, bool resistor);
+
#undef EXTERN
#if defined(__cplusplus)
}
diff --git a/arch/arm/src/stm32h7/stm32_ethernet.h b/arch/arm/src/stm32h7/stm32_wdg.h
similarity index 63%
copy from arch/arm/src/stm32h7/stm32_ethernet.h
copy to arch/arm/src/stm32h7/stm32_wdg.h
index fdb1ad5..290d39f 100644
--- a/arch/arm/src/stm32h7/stm32_ethernet.h
+++ b/arch/arm/src/stm32h7/stm32_wdg.h
@@ -1,7 +1,7 @@
/****************************************************************************
- * arch/arm/src/stm32h7/stm32_ethernet.h
+ * arch/arm/src/stm32h7/stm32_wdg.h
*
- * Copyright (C) 2015 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2012, 2015, 2020 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gn...@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -33,8 +33,8 @@
*
****************************************************************************/
-#ifndef __ARCH_ARM_SRC_STM32H7_STM32_ETHERNET_H
-#define __ARCH_ARM_SRC_STM32H7_STM32_ETHERNET_H
+#ifndef __ARCH_ARM_SRC_STM32_STM32_WDG_H
+#define __ARCH_ARM_SRC_STM32_STM32_WDG_H
/****************************************************************************
* Included Files
@@ -42,15 +42,17 @@
#include <nuttx/config.h>
-#include "hardware/stm32_ethernet.h"
+#include "chip.h"
+#include "hardware/stm32_wdg.h"
-#if STM32H7_NETHERNET > 0
-#ifndef __ASSEMBLY__
+#ifdef CONFIG_WATCHDOG
/****************************************************************************
- * Public Functions
+ * Pre-processor Definitions
****************************************************************************/
+#ifndef __ASSEMBLY__
+
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
@@ -61,52 +63,50 @@ extern "C"
#endif
/****************************************************************************
- * Function: stm32_ethinitialize
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_iwdginitialize
*
* Description:
- * Initialize the Ethernet driver for one interface. If the STM32 chip
- * supports multiple Ethernet controllers, then board specific logic must
- * implement up_netinitialize() and call this function to initialize the
- * desired interfaces.
+ * Initialize the IWDG watchdog time. The watchdog timer is initialized
+ * and registers as 'devpath'. The initial state of the watchdog time is
+ * disabled.
*
- * Parameters:
- * intf - In the case where there are multiple EMACs, this value identifies
- * which EMAC is to be initialized.
+ * Input Parameters:
+ * devpath - The full path to the watchdog. This should be of the form
+ * /dev/watchdog0
+ * lsifreq - The calibrated LSI clock frequency
*
* Returned Value:
- * OK on success; Negated errno on failure.
- *
- * Assumptions:
+ * None
*
****************************************************************************/
-#if STM32H7_NETHERNET > 1
-int stm32_ethinitialize(int intf);
+#ifdef CONFIG_STM32H7_IWDG
+void stm32_iwdginitialize(FAR const char *devpath, uint32_t lsifreq);
#endif
/****************************************************************************
- * Function: stm32_phy_boardinitialize
+ * Name: stm32_wwdginitialize
*
* Description:
- * Some boards require specialized initialization of the PHY before it can
- * be used. This may include such things as configuring GPIOs, resetting
- * the PHY, etc. If CONFIG_STM32H7_PHYINIT is defined in the configuration
- * then the board specific logic must provide stm32_phyinitialize(); The
- * STM32 Ethernet driver will call this function one time before it first
- * uses the PHY.
+ * Initialize the WWDG watchdog time. The watchdog timer is initialized
+ * and registers as 'devpath'. The initial state of the watchdog time is
+ * disabled.
*
- * Parameters:
- * intf - Always zero for now.
+ * Input Parameters:
+ * devpath - The full path to the watchdog. This should be of the form
+ * /dev/watchdog0
*
* Returned Value:
- * OK on success; Negated errno on failure.
+ * None
*
- * Assumptions:
- *
- ***************************************************************************/
+ ****************************************************************************/
-#ifdef CONFIG_STM32H7_PHYINIT
-int stm32_phy_boardinitialize(int intf);
+#ifdef CONFIG_STM32H7_WWDG
+void stm32_wwdginitialize(FAR const char *devpath);
#endif
#undef EXTERN
@@ -115,5 +115,5 @@ int stm32_phy_boardinitialize(int intf);
#endif
#endif /* __ASSEMBLY__ */
-#endif /* STM32H7_NETHERNET > 0 */
-#endif /* __ARCH_ARM_SRC_STM32H7_STM32_ETHERNET_H */
+#endif /* CONFIG_WATCHDOG */
+#endif /* __ARCH_ARM_SRC_STM32_STM32_WDG_H */
diff --git a/arch/arm/src/stm32h7/stm32_wwdg.c b/arch/arm/src/stm32h7/stm32_wwdg.c
new file mode 100644
index 0000000..23a9101
--- /dev/null
+++ b/arch/arm/src/stm32h7/stm32_wwdg.c
@@ -0,0 +1,803 @@
+/****************************************************************************
+ * arch/arm/src/stm32h7/stm32_wwdg.c
+ *
+ * Copyright (C) 2012, 2016, 2020 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gn...@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/arch.h>
+
+#include <stdint.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/irq.h>
+#include <nuttx/timers/watchdog.h>
+#include <arch/board/board.h>
+
+#include "up_arch.h"
+#include "stm32_wdg.h"
+
+#if defined(CONFIG_WATCHDOG) && defined(CONFIG_STM32H7_WWDG)
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Clocking *****************************************************************/
+
+/* The minimum frequency of the WWDG clock is:
+ *
+ * Fmin = PCLK1 / 4096 / 8
+ *
+ * So the maximum delay (in milliseconds) is then:
+ *
+ * 1000 * (WWDG_CR_T_MAX+1) / Fmin
+ *
+ * For example, if PCLK1 = 42MHz, then the maximum delay is:
+ *
+ * Fmin = 1281.74
+ * 1000 * 64 / Fmin = 49.93 msec
+ */
+
+#define WWDG_FMIN (STM32_PCLK1_FREQUENCY / 4096 / 8)
+#define WWDG_MAXTIMEOUT (1000 * (WWDG_CR_T_MAX+1) / WWDG_FMIN)
+
+/* Configuration ************************************************************/
+
+#ifndef CONFIG_STM32H7_WWDG_DEFTIMOUT
+# define CONFIG_STM32H7_WWDG_DEFTIMOUT WWDG_MAXTIMEOUT
+#endif
+
+#ifndef CONFIG_DEBUG_WATCHDOG_INFO
+# undef CONFIG_STM32H7_WWDG_REGDEBUG
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* This structure provides the private representation of the "lower-half"
+ * driver state structure. This structure must be cast-compatible with the
+ * well-known watchdog_lowerhalf_s structure.
+ */
+
+struct stm32_lowerhalf_s
+{
+ FAR const struct watchdog_ops_s *ops; /* Lower half operations */
+ xcpt_t handler; /* Current EWI interrupt handler */
+ uint32_t timeout; /* The actual timeout value */
+ uint32_t fwwdg; /* WWDG clock frequency */
+ bool started; /* The timer has been started */
+ uint8_t reload; /* The 7-bit reload field reset value */
+ uint8_t window; /* The 7-bit window (W) field value */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* Register operations ******************************************************/
+
+#ifdef CONFIG_STM32H7_WWDG_REGDEBUG
+static uint16_t stm32_getreg(uint32_t addr);
+static void stm32_putreg(uint16_t val, uint32_t addr);
+#else
+# define stm32_getreg(addr) getreg32(addr)
+# define stm32_putreg(val,addr) putreg32(val,addr)
+#endif
+static void stm32_setwindow(FAR struct stm32_lowerhalf_s *priv,
+ uint8_t window);
+
+/* Interrupt hanlding *******************************************************/
+
+static int stm32_interrupt(int irq, FAR void *context, FAR void *arg);
+
+/* "Lower half" driver methods **********************************************/
+
+static int stm32_start(FAR struct watchdog_lowerhalf_s *lower);
+static int stm32_stop(FAR struct watchdog_lowerhalf_s *lower);
+static int stm32_keepalive(FAR struct watchdog_lowerhalf_s *lower);
+static int stm32_getstatus(FAR struct watchdog_lowerhalf_s *lower,
+ FAR struct watchdog_status_s *status);
+static int stm32_settimeout(FAR struct watchdog_lowerhalf_s *lower,
+ uint32_t timeout);
+static xcpt_t stm32_capture(FAR struct watchdog_lowerhalf_s *lower,
+ xcpt_t handler);
+static int stm32_ioctl(FAR struct watchdog_lowerhalf_s *lower, int cmd,
+ unsigned long arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* "Lower half" driver methods */
+
+static const struct watchdog_ops_s g_wdgops =
+{
+ .start = stm32_start,
+ .stop = stm32_stop,
+ .keepalive = stm32_keepalive,
+ .getstatus = stm32_getstatus,
+ .settimeout = stm32_settimeout,
+ .capture = stm32_capture,
+ .ioctl = stm32_ioctl,
+};
+
+/* "Lower half" driver state */
+
+static struct stm32_lowerhalf_s g_wdgdev;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_getreg
+ *
+ * Description:
+ * Get the contents of an STM32 register
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_STM32H7_WWDG_REGDEBUG
+static uint16_t stm32_getreg(uint32_t addr)
+{
+ static uint32_t prevaddr = 0;
+ static uint32_t count = 0;
+ static uint16_t preval = 0;
+
+ /* Read the value from the register */
+
+ uint16_t val = getreg16(addr);
+
+ /* Is this the same value that we read from the same register last time?
+ * Are we polling the register? If so, suppress some of the output.
+ */
+
+ if (addr == prevaddr && val == preval)
+ {
+ if (count == 0xffffffff || ++count > 3)
+ {
+ if (count == 4)
+ {
+ wdinfo("...\n");
+ }
+
+ return val;
+ }
+ }
+
+ /* No this is a new address or value */
+
+ else
+ {
+ /* Did we print "..." for the previous value? */
+
+ if (count > 3)
+ {
+ /* Yes.. then show how many times the value repeated */
+
+ wdinfo("[repeats %d more times]\n", count - 3);
+ }
+
+ /* Save the new address, value, and count */
+
+ prevaddr = addr;
+ preval = val;
+ count = 1;
+ }
+
+ /* Show the register value read */
+
+ wdinfo("%08x->%04x\n", addr, val);
+ return val;
+}
+#endif
+
+/****************************************************************************
+ * Name: stm32_putreg
+ *
+ * Description:
+ * Set the contents of an STM32 register to a value
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_STM32H7_WWDG_REGDEBUG
+static void stm32_putreg(uint16_t val, uint32_t addr)
+{
+ /* Show the register value being written */
+
+ wdinfo("%08x<-%04x\n", addr, val);
+
+ /* Write the value */
+
+ putreg16(val, addr);
+}
+#endif
+
+/****************************************************************************
+ * Name: stm32_setwindow
+ *
+ * Description:
+ * Set the CFR window value. The window value is compared to the down-
+ * counter when the counter is updated. The WWDG counter should be updated
+ * only when the counter is below this window value (and greater than 64)
+ * otherwise a reset will be generated
+ *
+ ****************************************************************************/
+
+static void stm32_setwindow(FAR struct stm32_lowerhalf_s *priv, uint8_t window)
+{
+ uint16_t regval;
+
+ /* Set W[6:0] bits according to selected window value */
+
+ regval = stm32_getreg(STM32_WWDG_CFR);
+ regval &= ~WWDG_CFR_W_MASK;
+ regval |= window << WWDG_CFR_W_SHIFT;
+ stm32_putreg(regval, STM32_WWDG_CFR);
+
+ /* Remember the window setting */
+
+ priv->window = window;
+}
+
+/****************************************************************************
+ * Name: stm32_interrupt
+ *
+ * Description:
+ * WWDG early warning interrupt
+ *
+ * Input Parameters:
+ * Usual interrupt handler arguments.
+ *
+ * Returned Value:
+ * Always returns OK.
+ *
+ ****************************************************************************/
+
+static int stm32_interrupt(int irq, FAR void *context, FAR void *arg)
+{
+ FAR struct stm32_lowerhalf_s *priv = &g_wdgdev;
+ uint16_t regval;
+
+ /* Check if the EWI interrupt is really pending */
+
+ regval = stm32_getreg(STM32_WWDG_SR);
+ if ((regval & WWDG_SR_EWIF) != 0)
+ {
+ /* Is there a registered handler? */
+
+ if (priv->handler)
+ {
+ /* Yes... NOTE: This interrupt service routine (ISR) must reload
+ * the WWDG counter to prevent the reset. Otherwise, we will reset
+ * upon return.
+ */
+
+ priv->handler(irq, context, arg);
+ }
+
+ /* The EWI interrupt is cleared by writing '0' to the EWIF bit in the
+ * WWDG_SR register.
+ */
+
+ regval &= ~WWDG_SR_EWIF;
+ stm32_putreg(regval, STM32_WWDG_SR);
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: stm32_start
+ *
+ * Description:
+ * Start the watchdog timer, resetting the time to the current timeout,
+ *
+ * Input Parameters:
+ * lower - A pointer to the publicly visible representation of the
+ * "lower-half" driver state structure.
+ *
+ * Returned Value:
+ * Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int stm32_start(FAR struct watchdog_lowerhalf_s *lower)
+{
+ FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower;
+
+ wdinfo("Entry\n");
+ DEBUGASSERT(priv);
+
+ /* The watchdog is always disabled after a reset. It is enabled by setting
+ * the WDGA bit in the WWDG_CR register, then it cannot be disabled again
+ * except by a reset.
+ */
+
+ stm32_putreg(WWDG_CR_WDGA | WWDG_CR_T_RESET | priv->reload, STM32_WWDG_CR);
+ priv->started = true;
+ return OK;
+}
+
+/****************************************************************************
+ * Name: stm32_stop
+ *
+ * Description:
+ * Stop the watchdog timer
+ *
+ * Input Parameters:
+ * lower - A pointer to the publicly visible representation of the
+ * "lower-half" driver state structure.
+ *
+ * Returned Value:
+ * Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int stm32_stop(FAR struct watchdog_lowerhalf_s *lower)
+{
+ /* The watchdog is always disabled after a reset. It is enabled by setting
+ * the WDGA bit in the WWDG_CR register, then it cannot be disabled again
+ * except by a reset.
+ */
+
+ wdinfo("Entry\n");
+ return -ENOSYS;
+}
+
+/****************************************************************************
+ * Name: stm32_keepalive
+ *
+ * Description:
+ * Reset the watchdog timer to the current timeout value, prevent any
+ * imminent watchdog timeouts. This is sometimes referred as "pinging"
+ * the watchdog timer or "petting the dog".
+ *
+ * The application program must write in the WWDG_CR register at regular
+ * intervals during normal operation to prevent an MCU reset. This
+ * operation must occur only when the counter value is lower than the
+ * window register value. The value to be stored in the WWDG_CR register
+ * must be between 0xff and 0xC0:
+ *
+ * Input Parameters:
+ * lower - A pointer to the publicly visible representation of the
+ * "lower-half" driver state structure.
+ *
+ * Returned Value:
+ * Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int stm32_keepalive(FAR struct watchdog_lowerhalf_s *lower)
+{
+ FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower;
+
+ wdinfo("Entry\n");
+ DEBUGASSERT(priv);
+
+ /* Write to T[6:0] bits to configure the counter value, no need to do
+ * a read-modify-write; writing a 0 to WDGA bit does nothing.
+ */
+
+ stm32_putreg((WWDG_CR_T_RESET | priv->reload), STM32_WWDG_CR);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: stm32_getstatus
+ *
+ * Description:
+ * Get the current watchdog timer status
+ *
+ * Input Parameters:
+ * lower - A pointer to the publicly visible representation of the
+ * "lower-half" driver state structure.
+ * status - The location to return the watchdog status information.
+ *
+ * Returned Value:
+ * Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int stm32_getstatus(FAR struct watchdog_lowerhalf_s *lower,
+ FAR struct watchdog_status_s *status)
+{
+ FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower;
+ uint32_t elapsed;
+ uint16_t reload;
+
+ wdinfo("Entry\n");
+ DEBUGASSERT(priv);
+
+ /* Return the status bit */
+
+ status->flags = WDFLAGS_RESET;
+ if (priv->started)
+ {
+ status->flags |= WDFLAGS_ACTIVE;
+ }
+
+ if (priv->handler)
+ {
+ status->flags |= WDFLAGS_CAPTURE;
+ }
+
+ /* Return the actual timeout is milliseconds */
+
+ status->timeout = priv->timeout;
+
+ /* Get the time remaining until the watchdog expires (in milliseconds) */
+
+ reload = (stm32_getreg(STM32_WWDG_CR) >> WWDG_CR_T_SHIFT) & 0x7f;
+ elapsed = priv->reload - reload;
+ status->timeleft = (priv->timeout * elapsed) / (priv->reload + 1);
+
+ wdinfo("Status :\n");
+ wdinfo(" flags : %08x\n", status->flags);
+ wdinfo(" timeout : %d\n", status->timeout);
+ wdinfo(" timeleft : %d\n", status->flags);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: stm32_settimeout
+ *
+ * Description:
+ * Set a new timeout value (and reset the watchdog timer)
+ *
+ * Input Parameters:
+ * lower - A pointer to the publicly visible representation of the
+ * "lower-half" driver state structure.
+ * timeout - The new timeout value in milliseconds.
+ *
+ * Returned Value:
+ * Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int stm32_settimeout(FAR struct watchdog_lowerhalf_s *lower,
+ uint32_t timeout)
+{
+ FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower;
+ uint32_t fwwdg;
+ uint32_t reload;
+ uint16_t regval;
+ int wdgtb;
+
+ DEBUGASSERT(priv);
+ wdinfo("Entry: timeout=%d\n", timeout);
+
+ /* Can this timeout be represented? */
+
+ if (timeout < 1 || timeout > WWDG_MAXTIMEOUT)
+ {
+ wderr("ERROR: Cannot represent timeout=%d > %d\n",
+ timeout, WWDG_MAXTIMEOUT);
+ return -ERANGE;
+ }
+
+ /* Determine prescaler value.
+ *
+ * Fwwdg = PCLK1/4096/prescaler.
+ *
+ * Where
+ * Fwwwdg is the frequency of the WWDG clock
+ * wdgtb is one of {1, 2, 4, or 8}
+ */
+
+ /* Select the smallest prescaler that will result in a reload field value
+ * that is less than the maximum.
+ */
+
+ for (wdgtb = 0; ; wdgtb++)
+ {
+ /* WDGTB = 0 -> Divider = 1 = 1 << 0
+ * WDGTB = 1 -> Divider = 2 = 1 << 1
+ * WDGTB = 2 -> Divider = 4 = 1 << 2
+ * WDGTB = 3 -> Divider = 8 = 1 << 3
+ */
+
+ /* Get the WWDG counter frequency in Hz. */
+
+ fwwdg = (STM32_PCLK1_FREQUENCY / 4096) >> wdgtb;
+
+ /* The formula to calculate the timeout value is given by:
+ *
+ * timeout = 1000 * (reload + 1) / Fwwdg, OR
+ * reload = timeout * Fwwdg / 1000 - 1
+ *
+ * Where
+ * timeout is the desired timout in milliseconds
+ * reload is the contents of T{5:0]
+ * Fwwdg is the frequency of the WWDG clock
+ */
+
+ reload = timeout * fwwdg / 1000 - 1;
+
+ /* If this reload valid is less than the maximum or we are not ready
+ * at the prescaler value, then break out of the loop to use these
+ * settings.
+ */
+
+#if 0
+ wdinfo("wdgtb=%d fwwdg=%d reload=%d timout=%d\n",
+ wdgtb, fwwdg, reload, 1000 * (reload + 1) / fwwdg);
+#endif
+ if (reload <= WWDG_CR_T_MAX || wdgtb == 3)
+ {
+ /* Note that we explicitly break out of the loop rather than using
+ * the 'for' loop termination logic because we do not want the
+ * value of wdgtb to be incremented.
+ */
+
+ break;
+ }
+ }
+
+ /* Make sure that the final reload value is within range */
+
+ if (reload > WWDG_CR_T_MAX)
+ {
+ reload = WWDG_CR_T_MAX;
+ }
+
+ /* Calculate and save the actual timeout value in milliseconds:
+ *
+ * timeout = 1000 * (reload + 1) / Fwwdg
+ */
+
+ priv->timeout = 1000 * (reload + 1) / fwwdg;
+
+ /* Remember the selected values */
+
+ priv->fwwdg = fwwdg;
+ priv->reload = reload;
+
+ wdinfo("wdgtb=%d fwwdg=%d reload=%d timout=%d\n",
+ wdgtb, fwwdg, reload, priv->timeout);
+
+ /* Set WDGTB[1:0] bits according to calculated value */
+
+ regval = stm32_getreg(STM32_WWDG_CFR);
+ regval &= ~WWDG_CFR_WDGTB_MASK;
+ regval |= (uint16_t)wdgtb << WWDG_CFR_WDGTB_SHIFT;
+ stm32_putreg(regval, STM32_WWDG_CFR);
+
+ /* Reset the 7-bit window value to the maximum value...essentially
+ * disabling the lower limit of the watchdog reset time.
+ */
+
+ stm32_setwindow(priv, 0x7f);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: stm32_capture
+ *
+ * Description:
+ * Don't reset on watchdog timer timeout; instead, call this user provider
+ * timeout handler. NOTE: Providing handler==NULL will restore the reset
+ * behavior.
+ *
+ * Input Parameters:
+ * lower - A pointer to the publicly visible representation of the
+ * "lower-half" driver state structure.
+ * newhandler - The new watchdog expiration function pointer. If this
+ * function pointer is NULL, then the reset-on-expiration
+ * behavior is restored,
+ *
+ * Returned Value:
+ * The previous watchdog expiration function pointer or NULL is there was
+ * no previous function pointer, i.e., if the previous behavior was
+ * reset-on-expiration (NULL is also returned if an error occurs).
+ *
+ ****************************************************************************/
+
+static xcpt_t stm32_capture(FAR struct watchdog_lowerhalf_s *lower,
+ xcpt_t handler)
+{
+ FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower;
+ irqstate_t flags;
+ xcpt_t oldhandler;
+ uint16_t regval;
+
+ DEBUGASSERT(priv);
+ wdinfo("Entry: handler=%p\n", handler);
+
+ /* Get the old handler return value */
+
+ flags = enter_critical_section();
+ oldhandler = priv->handler;
+
+ /* Save the new handler */
+
+ priv->handler = handler;
+
+ /* Are we attaching or detaching the handler? */
+
+ regval = stm32_getreg(STM32_WWDG_CFR);
+ if (handler)
+ {
+ /* Attaching... Enable the EWI interrupt */
+
+ regval |= WWDG_CFR_EWI;
+ stm32_putreg(regval, STM32_WWDG_CFR);
+
+ up_enable_irq(STM32_IRQ_WWDG1);
+ }
+ else
+ {
+ /* Detaching... Disable the EWI interrupt */
+
+ regval &= ~WWDG_CFR_EWI;
+ stm32_putreg(regval, STM32_WWDG_CFR);
+
+ up_disable_irq(STM32_IRQ_WWDG1);
+ }
+
+ leave_critical_section(flags);
+ return oldhandler;
+}
+
+/****************************************************************************
+ * Name: stm32_ioctl
+ *
+ * Description:
+ * Any ioctl commands that are not recognized by the "upper-half" driver
+ * are forwarded to the lower half driver through this method.
+ *
+ * Input Parameters:
+ * lower - A pointer to the publicly visible representation of the
+ * "lower-half" driver state structure.
+ * cmd - The ioctl command value
+ * arg - The optional argument that accompanies the 'cmd'. The
+ * interpretation of this argument depends on the particular
+ * command.
+ *
+ * Returned Value:
+ * Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int stm32_ioctl(FAR struct watchdog_lowerhalf_s *lower, int cmd,
+ unsigned long arg)
+{
+ FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower;
+ int ret = -ENOTTY;
+
+ DEBUGASSERT(priv);
+ wdinfo("Entry: cmd=%d arg=%ld\n", cmd, arg);
+
+ /* WDIOC_MINTIME: Set the minimum ping time. If two keepalive ioctls
+ * are received within this time, a reset event will be generated.
+ * Argument: A 32-bit time value in milliseconds.
+ */
+
+ if (cmd == WDIOC_MINTIME)
+ {
+ uint32_t mintime = (uint32_t)arg;
+
+ /* The minimum time should be strictly less than the total delay
+ * which, in turn, will be less than or equal to WWDG_CR_T_MAX
+ */
+
+ ret = -EINVAL;
+ if (mintime < priv->timeout)
+ {
+ uint32_t window = (priv->timeout - mintime) * priv->fwwdg / 1000 - 1;
+ DEBUGASSERT(window < priv->reload);
+ stm32_setwindow(priv, window | WWDG_CR_T_RESET);
+ ret = OK;
+ }
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_wwdginitialize
+ *
+ * Description:
+ * Initialize the WWDG watchdog timer. The watchdog timer is initialized
+ * and registers as 'devpath'. The initial state of the watchdog timer is
+ * disabled.
+ *
+ * Input Parameters:
+ * devpath - The full path to the watchdog. This should be of the form
+ * /dev/watchdog0
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void stm32_wwdginitialize(FAR const char *devpath)
+{
+ FAR struct stm32_lowerhalf_s *priv = &g_wdgdev;
+
+ wdinfo("Entry: devpath=%s\n", devpath);
+
+ /* NOTE we assume that clocking to the WWDG has already been provided by
+ * the RCC initialization logic.
+ */
+
+ /* Initialize the driver state structure. Here we assume: (1) the state
+ * structure lies in .bss and was zeroed at reset time. (2) This function
+ * is only called once so it is never necessary to re-zero the structure.
+ */
+
+ priv->ops = &g_wdgops;
+
+ /* Attach our EWI interrupt handler (But don't enable it yet) */
+
+ irq_attach(STM32_IRQ_WWDG1, stm32_interrupt, NULL);
+
+ /* Select an arbitrary initial timeout value. But don't start the watchdog
+ * yet. NOTE: If the "Hardware watchdog" feature is enabled through the
+ * device option bits, the watchdog is automatically enabled at power-on.
+ */
+
+ stm32_settimeout((FAR struct watchdog_lowerhalf_s *)priv,
+ CONFIG_STM32H7_WWDG_DEFTIMOUT);
+
+ /* Register the watchdog driver as /dev/watchdog0 */
+
+ watchdog_register(devpath, (FAR struct watchdog_lowerhalf_s *)priv);
+
+ /* When the microcontroller enters debug mode (Cortex-M core halted),
+ * the WWDG counter either continues to work normally or stops, depending
+ * on the WWDG1 STOP configuration bit in DBG module.
+ */
+
+#if defined(CONFIG_STM32H7_JTAG_FULL_ENABLE) || \
+ defined(CONFIG_STM32H7_JTAG_NOJNTRST_ENABLE) || \
+ defined(CONFIG_STM32H7_JTAG_SW_ENABLE)
+ {
+ uint32_t cr = getreg32(STM32_DBGMCU_APB3_FZ1);
+ cr |= DBGMCU_APB3_WWDG1STOP;
+ putreg32(cr, STM32_DBGMCU_APB3_FZ1);
+ }
+#endif
+}
+
+#endif /* CONFIG_WATCHDOG && CONFIG_STM32H7_WWDG */
diff --git a/arch/arm/src/stm32h7/stm32h7x3xx_rcc.c b/arch/arm/src/stm32h7/stm32h7x3xx_rcc.c
index 54f3f8f..b1881e4 100644
--- a/arch/arm/src/stm32h7/stm32h7x3xx_rcc.c
+++ b/arch/arm/src/stm32h7/stm32h7x3xx_rcc.c
@@ -95,7 +95,6 @@
# endif
#endif
-
/* PLL are only enabled if the P,Q or R outputs are enabled. */
#undef USE_PLL1
@@ -143,8 +142,8 @@ static inline void rcc_reset(void)
putreg32(regval, STM32_RCC_CR);
#if defined(CONFIG_STM32H7_AXI_SRAM_CORRUPTION_WAR)
- /* Errata 2.2.9 Enable workaround for Reading from AXI SRAM may lead to data
- * read corruption. See ES0392 Rev 6.
+ /* Errata 2.2.9 Enable workaround for Reading from AXI SRAM may lead to
+ * data read corruption. See ES0392 Rev 6.
*/
putreg32(AXI_TARG_READ_ISS_OVERRIDE, STM32_AXI_TARG7_FN_MOD);
@@ -767,6 +766,7 @@ static void stm32_stdclockconfig(void)
{
}
#endif
+
#if defined(USE_PLL3)
/* Wait until the PLL3 is ready */
@@ -776,15 +776,15 @@ static void stm32_stdclockconfig(void)
#endif
/* Ww must write the lower byte of the PWR_CR3 register is written once
- * after POR and it shall be written before changing VOS level or ck_sys
- * clock frequency. No limitation applies to the upper bytes.
+ * after POR and it shall be written before changing VOS level or
+ * ck_sys clock frequency. No limitation applies to the upper bytes.
*
* Programming data corresponding to an invalid combination of
* LDOEN and BYPASS bits will be ignored: data will not be written,
* the written-once mechanism will lock the register and any further
* write access will be ignored. The default supply configuration will
- * be kept and the ACTVOSRDY bit in PWR control status register 1 (PWR_CSR1)
- * will go on indicating invalid voltage levels.
+ * be kept and the ACTVOSRDY bit in PWR control status register 1
+ * (PWR_CSR1) will go on indicating invalid voltage levels.
*
* N.B. The system shall be power cycled before writing a new value.
*/
@@ -804,6 +804,12 @@ static void stm32_stdclockconfig(void)
{
}
+ /* See Reference manual Section 5.4.1, System supply startup */
+
+ while ((getreg32(STM32_PWR_CSR1) & PWR_CSR1_ACTVOSRDY) == 0)
+ {
+ }
+
/* Over-drive is needed if
* - Voltage output scale 1 mode is selected and SYSCLK frequency is
* over 400 Mhz.
@@ -812,7 +818,6 @@ static void stm32_stdclockconfig(void)
if ((STM32_PWR_VOS_SCALE == PWR_D3CR_VOS_SCALE_1) &&
STM32_SYSCLK_FREQUENCY > 400000000)
{
-
/* Enable System configuration controller clock to Enable ODEN */
regval = getreg32(STM32_RCC_APB4ENR);
@@ -835,7 +840,6 @@ static void stm32_stdclockconfig(void)
regval = FLASH_ACR_WRHIGHFREQ(BOARD_FLASH_PROGDELAY) |
FLASH_ACR_LATENCY(BOARD_FLASH_WAITSTATES);
-
putreg32(regval, STM32_FLASH_ACR);
/* Select the PLL1P as system clock source */