You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2026/03/30 01:48:24 UTC
(nuttx) 01/03: arch/arm/ht32f491x3: add initial support
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit ba6ee9d559f227518ab80cbd5076e007864b36cc
Author: Felipe Moura <mo...@gmail.com>
AuthorDate: Tue Mar 24 21:51:04 2026 -0300
arch/arm/ht32f491x3: add initial support
Add initial HT32F491x3 support with startup, IRQ handling,
serial console, GPIO helpers, custom vectors, and CMake build files.
Signed-off-by: Felipe Moura <mo...@gmail.com>
---
arch/arm/Kconfig | 12 +
arch/arm/include/ht32f491x3/chip.h | 69 +++
arch/arm/include/ht32f491x3/ht32f491x3_irq.h | 130 ++++
arch/arm/include/ht32f491x3/irq.h | 61 ++
arch/arm/src/Makefile | 9 +
arch/arm/src/ht32f491x3/CMakeLists.txt | 37 ++
arch/arm/src/ht32f491x3/Kconfig | 67 +++
arch/arm/src/ht32f491x3/Make.defs | 34 ++
arch/arm/src/ht32f491x3/arm_vectors.c | 108 ++++
arch/arm/src/ht32f491x3/chip.h | 43 ++
arch/arm/src/ht32f491x3/hardware/ht32f491x3_crm.h | 249 ++++++++
.../arm/src/ht32f491x3/hardware/ht32f491x3_flash.h | 50 ++
arch/arm/src/ht32f491x3/hardware/ht32f491x3_gpio.h | 83 +++
.../src/ht32f491x3/hardware/ht32f491x3_memorymap.h | 127 ++++
arch/arm/src/ht32f491x3/hardware/ht32f491x3_pwc.h | 48 ++
arch/arm/src/ht32f491x3/hardware/ht32f491x3_uart.h | 147 +++++
arch/arm/src/ht32f491x3/ht32f491x3_config.h | 53 ++
arch/arm/src/ht32f491x3/ht32f491x3_gpio.c | 78 +++
arch/arm/src/ht32f491x3/ht32f491x3_gpio.h | 63 ++
arch/arm/src/ht32f491x3/ht32f491x3_irq.c | 310 ++++++++++
arch/arm/src/ht32f491x3/ht32f491x3_lowputc.c | 287 +++++++++
arch/arm/src/ht32f491x3/ht32f491x3_lowputc.h | 43 ++
arch/arm/src/ht32f491x3/ht32f491x3_serial.c | 658 +++++++++++++++++++++
arch/arm/src/ht32f491x3/ht32f491x3_serial.h | 46 ++
arch/arm/src/ht32f491x3/ht32f491x3_start.c | 114 ++++
arch/arm/src/ht32f491x3/ht32f491x3_start.h | 39 ++
arch/arm/src/ht32f491x3/ht32f491x3_timerisr.c | 95 +++
27 files changed, 3060 insertions(+)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 52b1e3e88da..de81c0fb81c 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -779,6 +779,14 @@ config ARCH_CHIP_CXD32XX
---help---
Sony CXD32XX (ARM Cortex-M4) architectures
+config ARCH_CHIP_HT32F491X3
+ bool "Holtek HT32F491x3"
+ select ARCH_CORTEXM4
+ select ARCH_HAVE_FPU
+ select LIBC_ARCH_ATOMIC
+ ---help---
+ Holtek HT32F491x3 (ARM Cortex-M4) architectures
+
config ARCH_CHIP_ARM_CUSTOM
bool "Custom ARM chip"
select ARCH_CHIP_CUSTOM
@@ -1207,6 +1215,7 @@ config ARCH_CHIP
default "goldfish" if ARCH_CHIP_GOLDFISH_ARM
default "at32" if ARCH_CHIP_AT32
default "cxd32xx" if ARCH_CHIP_CXD32XX
+ default "ht32f491x3" if ARCH_CHIP_HT32F491X3
default "csk6" if ARCH_CHIP_CSK6
default "mcx-nxxx" if ARCH_CHIP_MCX_NXXX
@@ -1748,6 +1757,9 @@ endif
if ARCH_CHIP_CXD32XX
source "arch/arm/src/cxd32xx/Kconfig"
endif
+if ARCH_CHIP_HT32F491X3
+source "arch/arm/src/ht32f491x3/Kconfig"
+endif
if ARCH_CHIP_MCX_NXXX
source "arch/arm/src/mcx-nxxx/Kconfig"
endif
diff --git a/arch/arm/include/ht32f491x3/chip.h b/arch/arm/include/ht32f491x3/chip.h
new file mode 100644
index 00000000000..bc843a01c33
--- /dev/null
+++ b/arch/arm/include/ht32f491x3/chip.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+ * arch/arm/include/ht32f491x3/chip.h
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_INCLUDE_HT32F491X3_CHIP_H
+#define __ARCH_ARM_INCLUDE_HT32F491X3_CHIP_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define HT32M4_SYSH_PRIORITY_MIN 0xe0
+#define HT32M4_SYSH_PRIORITY_DEFAULT 0x80
+#define HT32M4_SYSH_PRIORITY_MAX 0x00
+#define HT32M4_SYSH_PRIORITY_STEP 0x20
+
+#define NVIC_SYSH_PRIORITY_MIN HT32M4_SYSH_PRIORITY_MIN
+#define NVIC_SYSH_PRIORITY_DEFAULT HT32M4_SYSH_PRIORITY_DEFAULT
+#define NVIC_SYSH_PRIORITY_MAX HT32M4_SYSH_PRIORITY_MAX
+#define NVIC_SYSH_PRIORITY_STEP HT32M4_SYSH_PRIORITY_STEP
+
+#if defined(CONFIG_ARCH_CHIP_HT32F49153)
+# define HT32_FLASH_KB 128
+#elif defined(CONFIG_ARCH_CHIP_HT32F49163)
+# define HT32_FLASH_KB 256
+#else
+# error "Unsupported HT32F491x3 device"
+#endif
+
+#define HT32_SRAM_KB 48
+#define HT32_NUSART 8
+#define HT32_NGPIO 6
+
+#define HT32_HICK_FREQUENCY 8000000
+#define HT32_HICK48_FREQUENCY 48000000
+#define HT32_HEXT_MIN_FREQUENCY 4000000
+#define HT32_HEXT_MAX_FREQUENCY 25000000
+#define HT32_PLL_MAX_FREQUENCY 150000000
+
+#define HT32_SYSCLK_FREQUENCY CONFIG_HT32F491X3_SYSCLK_FREQUENCY
+#define HT32_HCLK_FREQUENCY HT32_SYSCLK_FREQUENCY
+#define HT32_PCLK1_FREQUENCY CONFIG_HT32F491X3_PCLK1_FREQUENCY
+#define HT32_PCLK2_FREQUENCY CONFIG_HT32F491X3_PCLK2_FREQUENCY
+
+#endif /* __ARCH_ARM_INCLUDE_HT32F491X3_CHIP_H */
diff --git a/arch/arm/include/ht32f491x3/ht32f491x3_irq.h b/arch/arm/include/ht32f491x3/ht32f491x3_irq.h
new file mode 100644
index 00000000000..201431f885c
--- /dev/null
+++ b/arch/arm/include/ht32f491x3/ht32f491x3_irq.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+ * arch/arm/include/ht32f491x3/ht32f491x3_irq.h
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/* This file should never be included directly but, rather,
+ * only indirectly through nuttx/irq.h
+ */
+
+#ifndef __ARCH_ARM_INCLUDE_HT32F491X3_HT32F491X3_IRQ_H
+#define __ARCH_ARM_INCLUDE_HT32F491X3_HT32F491X3_IRQ_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/irq.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* External interrupts. These values follow the Holtek CMSIS device header
+ * and startup vector table for the HT32F491x3 family.
+ */
+
+#define HT32_IRQ_WWDT (HT32_IRQ_FIRST + 0)
+#define HT32_IRQ_PVM (HT32_IRQ_FIRST + 1)
+#define HT32_IRQ_PVD HT32_IRQ_PVM
+#define HT32_IRQ_TAMP_STAMP (HT32_IRQ_FIRST + 2)
+#define HT32_IRQ_TAMPER HT32_IRQ_TAMP_STAMP
+#define HT32_IRQ_TIMESTAMP HT32_IRQ_TAMP_STAMP
+#define HT32_IRQ_ERTCWAKEUP (HT32_IRQ_FIRST + 3)
+#define HT32_IRQ_FLASH (HT32_IRQ_FIRST + 4)
+#define HT32_IRQ_CRM (HT32_IRQ_FIRST + 5)
+#define HT32_IRQ_EXINT0 (HT32_IRQ_FIRST + 6)
+#define HT32_IRQ_EXINT1 (HT32_IRQ_FIRST + 7)
+#define HT32_IRQ_EXINT2 (HT32_IRQ_FIRST + 8)
+#define HT32_IRQ_EXINT3 (HT32_IRQ_FIRST + 9)
+#define HT32_IRQ_EXINT4 (HT32_IRQ_FIRST + 10)
+#define HT32_IRQ_DMA1CH1 (HT32_IRQ_FIRST + 11)
+#define HT32_IRQ_DMA1CH2 (HT32_IRQ_FIRST + 12)
+#define HT32_IRQ_DMA1CH3 (HT32_IRQ_FIRST + 13)
+#define HT32_IRQ_DMA1CH4 (HT32_IRQ_FIRST + 14)
+#define HT32_IRQ_DMA1CH5 (HT32_IRQ_FIRST + 15)
+#define HT32_IRQ_DMA1CH6 (HT32_IRQ_FIRST + 16)
+#define HT32_IRQ_DMA1CH7 (HT32_IRQ_FIRST + 17)
+#define HT32_IRQ_ADC1 (HT32_IRQ_FIRST + 18)
+#define HT32_IRQ_ADC HT32_IRQ_ADC1
+#define HT32_IRQ_CAN1TX (HT32_IRQ_FIRST + 19)
+#define HT32_IRQ_CAN1RX0 (HT32_IRQ_FIRST + 20)
+#define HT32_IRQ_CAN1RX1 (HT32_IRQ_FIRST + 21)
+#define HT32_IRQ_CAN1SE (HT32_IRQ_FIRST + 22)
+#define HT32_IRQ_CANSE HT32_IRQ_CAN1SE
+#define HT32_IRQ_EXINT95 (HT32_IRQ_FIRST + 23)
+#define HT32_IRQ_TMR1BRK (HT32_IRQ_FIRST + 24)
+#define HT32_IRQ_TMR9 HT32_IRQ_TMR1BRK
+#define HT32_IRQ_TMR1UP (HT32_IRQ_FIRST + 25)
+#define HT32_IRQ_TMR10 HT32_IRQ_TMR1UP
+#define HT32_IRQ_TMR1TRGCOM (HT32_IRQ_FIRST + 26)
+#define HT32_IRQ_TMR11 HT32_IRQ_TMR1TRGCOM
+#define HT32_IRQ_TMR1CC (HT32_IRQ_FIRST + 27)
+#define HT32_IRQ_TMR2 (HT32_IRQ_FIRST + 28)
+#define HT32_IRQ_TMR3 (HT32_IRQ_FIRST + 29)
+#define HT32_IRQ_TMR4 (HT32_IRQ_FIRST + 30)
+#define HT32_IRQ_I2C1EV (HT32_IRQ_FIRST + 31)
+#define HT32_IRQ_I2C1ERR (HT32_IRQ_FIRST + 32)
+#define HT32_IRQ_I2C2EV (HT32_IRQ_FIRST + 33)
+#define HT32_IRQ_I2C2ERR (HT32_IRQ_FIRST + 34)
+#define HT32_IRQ_SPI1 (HT32_IRQ_FIRST + 35)
+#define HT32_IRQ_SPI2 (HT32_IRQ_FIRST + 36)
+#define HT32_IRQ_USART1 (HT32_IRQ_FIRST + 37)
+#define HT32_IRQ_USART2 (HT32_IRQ_FIRST + 38)
+#define HT32_IRQ_USART3 (HT32_IRQ_FIRST + 39)
+#define HT32_IRQ_EXINT1510 (HT32_IRQ_FIRST + 40)
+#define HT32_IRQ_ERTCALARM (HT32_IRQ_FIRST + 41)
+#define HT32_IRQ_OTGFSWKUP (HT32_IRQ_FIRST + 42)
+#define HT32_IRQ_TMR12 (HT32_IRQ_FIRST + 43)
+#define HT32_IRQ_TMR13 (HT32_IRQ_FIRST + 44)
+#define HT32_IRQ_TMR14 (HT32_IRQ_FIRST + 45)
+#define HT32_IRQ_SPI3 (HT32_IRQ_FIRST + 51)
+#define HT32_IRQ_USART4 (HT32_IRQ_FIRST + 52)
+#define HT32_IRQ_USART5 (HT32_IRQ_FIRST + 53)
+#define HT32_IRQ_TMR6 (HT32_IRQ_FIRST + 54)
+#define HT32_IRQ_DAC HT32_IRQ_TMR6
+#define HT32_IRQ_TMR7 (HT32_IRQ_FIRST + 55)
+#define HT32_IRQ_DMA2CH1 (HT32_IRQ_FIRST + 56)
+#define HT32_IRQ_DMA2CH2 (HT32_IRQ_FIRST + 57)
+#define HT32_IRQ_DMA2CH3 (HT32_IRQ_FIRST + 58)
+#define HT32_IRQ_DMA2CH4 (HT32_IRQ_FIRST + 59)
+#define HT32_IRQ_DMA2CH5 (HT32_IRQ_FIRST + 60)
+#define HT32_IRQ_CAN2TX (HT32_IRQ_FIRST + 63)
+#define HT32_IRQ_CAN2RX0 (HT32_IRQ_FIRST + 64)
+#define HT32_IRQ_CAN2RX1 (HT32_IRQ_FIRST + 65)
+#define HT32_IRQ_CAN2SE (HT32_IRQ_FIRST + 66)
+#define HT32_IRQ_OTGFS1 (HT32_IRQ_FIRST + 67)
+#define HT32_IRQ_OTGFS HT32_IRQ_OTGFS1
+#define HT32_IRQ_DMA2CH6 (HT32_IRQ_FIRST + 68)
+#define HT32_IRQ_DMA2CH7 (HT32_IRQ_FIRST + 69)
+#define HT32_IRQ_USART6 (HT32_IRQ_FIRST + 71)
+#define HT32_IRQ_I2C3EV (HT32_IRQ_FIRST + 72)
+#define HT32_IRQ_I2C3ERR (HT32_IRQ_FIRST + 73)
+#define HT32_IRQ_FPU (HT32_IRQ_FIRST + 81)
+#define HT32_IRQ_USART7 (HT32_IRQ_FIRST + 82)
+#define HT32_IRQ_USART8 (HT32_IRQ_FIRST + 83)
+#define HT32_IRQ_DMAMUX (HT32_IRQ_FIRST + 94)
+#define HT32_IRQ_ACC (HT32_IRQ_FIRST + 103)
+
+#define HT32_IRQ_NEXTINT (104)
+#define NR_IRQS (HT32_IRQ_FIRST + HT32_IRQ_NEXTINT)
+
+#endif /* __ARCH_ARM_INCLUDE_HT32F491X3_HT32F491X3_IRQ_H */
diff --git a/arch/arm/include/ht32f491x3/irq.h b/arch/arm/include/ht32f491x3/irq.h
new file mode 100644
index 00000000000..16d1f314af8
--- /dev/null
+++ b/arch/arm/include/ht32f491x3/irq.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+ * arch/arm/include/ht32f491x3/irq.h
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/* This file should never be included directly but, rather,
+ * only indirectly through nuttx/irq.h
+ */
+
+#ifndef __ARCH_ARM_INCLUDE_HT32F491X3_IRQ_H
+#define __ARCH_ARM_INCLUDE_HT32F491X3_IRQ_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/irq.h>
+#include <arch/ht32f491x3/chip.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define HT32_IRQ_RESERVED (0)
+#define HT32_IRQ_NMI (2)
+#define HT32_IRQ_HARDFAULT (3)
+#define HT32_IRQ_MEMFAULT (4)
+#define HT32_IRQ_BUSFAULT (5)
+#define HT32_IRQ_USAGEFAULT (6)
+#define HT32_IRQ_SVCALL (11)
+#define HT32_IRQ_DBGMONITOR (12)
+#define HT32_IRQ_PENDSV (14)
+#define HT32_IRQ_SYSTICK (15)
+
+#define HT32_IRQ_FIRST (16)
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <arch/ht32f491x3/ht32f491x3_irq.h>
+
+#endif /* __ARCH_ARM_INCLUDE_HT32F491X3_IRQ_H */
diff --git a/arch/arm/src/Makefile b/arch/arm/src/Makefile
index 00581e6a1c1..7c6da2a3eaa 100644
--- a/arch/arm/src/Makefile
+++ b/arch/arm/src/Makefile
@@ -21,7 +21,16 @@
############################################################################
include $(TOPDIR)/tools/Make.defs
+
+# Allow cleanup targets to run even if the configured chip dirlink is gone.
+CLEAN_GOALS = clean distclean
+ifeq ($(strip $(MAKECMDGOALS)),)
+include chip/Make.defs
+else ifeq ($(strip $(filter-out $(CLEAN_GOALS),$(MAKECMDGOALS))),)
+-include chip/Make.defs
+else
include chip/Make.defs
+endif
ifeq ($(CONFIG_ARCH_ARMV7A),y) # ARMv7-A
ARCH_SUBDIR = armv7-a
diff --git a/arch/arm/src/ht32f491x3/CMakeLists.txt b/arch/arm/src/ht32f491x3/CMakeLists.txt
new file mode 100644
index 00000000000..1231e5546bd
--- /dev/null
+++ b/arch/arm/src/ht32f491x3/CMakeLists.txt
@@ -0,0 +1,37 @@
+# ##############################################################################
+# arch/arm/src/ht32f491x3/CMakeLists.txt
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more contributor
+# license agreements. See the NOTICE file distributed with this work for
+# additional information regarding copyright ownership. The ASF licenses this
+# file to you under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+#
+# ##############################################################################
+
+list(
+ APPEND
+ SRCS
+ ht32f491x3_start.c
+ ht32f491x3_irq.c
+ ht32f491x3_timerisr.c
+ ht32f491x3_gpio.c
+ ht32f491x3_lowputc.c
+ ht32f491x3_serial.c)
+
+if(CONFIG_ARCH_HAVE_CUSTOM_VECTORS)
+ list(APPEND SRCS arm_vectors.c)
+endif()
+
+target_sources(arch PRIVATE ${SRCS})
diff --git a/arch/arm/src/ht32f491x3/Kconfig b/arch/arm/src/ht32f491x3/Kconfig
new file mode 100644
index 00000000000..3a32d32146a
--- /dev/null
+++ b/arch/arm/src/ht32f491x3/Kconfig
@@ -0,0 +1,67 @@
+#
+# For a description of the syntax of this configuration file,
+# see the file kconfig-language.txt in the NuttX tools repository.
+#
+
+comment "HT32F491x3 Configuration Options"
+
+choice
+ prompt "HT32F491x3 Chip Selection"
+ default ARCH_CHIP_HT32F49163
+ depends on ARCH_CHIP_HT32F491X3
+
+config ARCH_CHIP_HT32F49153
+ bool "HT32F49153"
+ select ARCH_HAVE_CUSTOM_VECTORS
+ ---help---
+ 128 KiB FLASH, 48 KiB SRAM.
+
+config ARCH_CHIP_HT32F49163
+ bool "HT32F49163"
+ select ARCH_HAVE_CUSTOM_VECTORS
+ ---help---
+ 256 KiB FLASH, 48 KiB SRAM.
+
+endchoice
+
+config HT32F491X3_SYSCLK_FREQUENCY
+ int "System clock frequency"
+ default 8000000
+ range 1 150000000
+ depends on ARCH_CHIP_HT32F491X3
+ ---help---
+ The reset clock tree runs from the 8 MHz HICK oscillator. Adjust
+ this if board-specific CRM/PLL setup changes SYSCLK before the
+ generic timer or serial logic runs.
+
+config HT32F491X3_PCLK1_FREQUENCY
+ int "APB1 clock frequency"
+ default HT32F491X3_SYSCLK_FREQUENCY
+ range 1 150000000
+ depends on ARCH_CHIP_HT32F491X3
+ ---help---
+ APB1 clock used by USART2 and USART3. The default matches the reset
+ configuration where APB1DIV does not divide HCLK.
+
+config HT32F491X3_PCLK2_FREQUENCY
+ int "APB2 clock frequency"
+ default HT32F491X3_SYSCLK_FREQUENCY
+ range 1 150000000
+ depends on ARCH_CHIP_HT32F491X3
+ ---help---
+ APB2 clock used by USART1. The default matches the reset
+ configuration where APB2DIV does not divide HCLK.
+
+menu "Peripheral Support"
+
+config HT32F491X3_USART1_SERIALDRIVER
+ bool "USART1"
+ default y
+ select USART1_SERIALDRIVER
+ select ARCH_HAVE_SERIAL_TERMIOS
+ ---help---
+ Enable the standard lower-half driver for USART1.
+
+comment "In this current version, only USART1 is exposed by the esk32 board support."
+
+endmenu # "Peripheral Support"
diff --git a/arch/arm/src/ht32f491x3/Make.defs b/arch/arm/src/ht32f491x3/Make.defs
new file mode 100644
index 00000000000..e8fee89b83f
--- /dev/null
+++ b/arch/arm/src/ht32f491x3/Make.defs
@@ -0,0 +1,34 @@
+############################################################################
+# arch/arm/src/ht32f491x3/Make.defs
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership. The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+include armv7-m/Make.defs
+
+CHIP_ASRCS +=
+
+CHIP_CSRCS += ht32f491x3_start.c ht32f491x3_irq.c
+CHIP_CSRCS += ht32f491x3_timerisr.c ht32f491x3_gpio.c
+CHIP_CSRCS += ht32f491x3_lowputc.c
+CHIP_CSRCS += ht32f491x3_serial.c
+
+ifeq ($(CONFIG_ARCH_HAVE_CUSTOM_VECTORS),y)
+CHIP_CSRCS += arm_vectors.c
+endif
diff --git a/arch/arm/src/ht32f491x3/arm_vectors.c b/arch/arm/src/ht32f491x3/arm_vectors.c
new file mode 100644
index 00000000000..bfd2bcd5511
--- /dev/null
+++ b/arch/arm/src/ht32f491x3/arm_vectors.c
@@ -0,0 +1,108 @@
+/****************************************************************************
+ * arch/arm/src/ht32f491x3/arm_vectors.c
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: 2012 Michael Smith. All rights reserved.
+ *
+ * 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 <stdint.h>
+
+#include "chip.h"
+#include "arm_internal.h"
+#include "ram_vectors.h"
+#include "nvic.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define IDLE_STACK (_ebss + CONFIG_IDLETHREAD_STACKSIZE)
+
+#define HT32_VECTOR_RESERVED ((const void *)(uintptr_t)UINT32_MAX)
+
+#if defined(CONFIG_ARCH_CHIP_HT32F49153)
+# define HT32_VECTOR_FWID ((const void *)(uintptr_t)0x00049153u)
+#elif defined(CONFIG_ARCH_CHIP_HT32F49163)
+# define HT32_VECTOR_FWID ((const void *)(uintptr_t)0x00049163u)
+#else
+# error "Unsupported HT32F491x3 device"
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+extern void __start(void);
+
+static void start(void)
+{
+ /* Zero lr to mark the end of backtrace */
+
+ asm volatile ("mov lr, #0\n\t"
+ "b __start\n\t");
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+extern void exception_common(void);
+extern void exception_direct(void);
+
+/****************************************************************************
+ * Public data
+ ****************************************************************************/
+
+/* Holtek reserves vector slots 7/9/10/13 and uses slot 8 for a device FWID.
+ * Keep the NuttX exception routing semantics for all real exceptions/IRQs.
+ */
+
+const void * const _vectors[] locate_data(".vectors")
+ aligned_data(VECTAB_ALIGN) =
+{
+ IDLE_STACK,
+ start,
+ [NVIC_IRQ_NMI ... NVIC_IRQ_USAGEFAULT] = &exception_common,
+ [7] = HT32_VECTOR_RESERVED,
+ [8] = HT32_VECTOR_FWID,
+ [9 ... 10] = HT32_VECTOR_RESERVED,
+ [NVIC_IRQ_SVCALL ... NVIC_IRQ_DBGMONITOR] = &exception_common,
+ [13] = HT32_VECTOR_RESERVED,
+ [NVIC_IRQ_PENDSV] = &exception_common,
+ [NVIC_IRQ_SYSTICK ... (15 + ARMV7M_PERIPHERAL_INTERRUPTS)]
+ = &exception_direct
+};
diff --git a/arch/arm/src/ht32f491x3/chip.h b/arch/arm/src/ht32f491x3/chip.h
new file mode 100644
index 00000000000..6e9ff9162a5
--- /dev/null
+++ b/arch/arm/src/ht32f491x3/chip.h
@@ -0,0 +1,43 @@
+/****************************************************************************
+ * arch/arm/src/ht32f491x3/chip.h
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_HT32F491X3_CHIP_H
+#define __ARCH_ARM_SRC_HT32F491X3_CHIP_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <arch/ht32f491x3/chip.h>
+#include <arch/ht32f491x3/irq.h>
+
+#include "hardware/ht32f491x3_memorymap.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define ARMV7M_PERIPHERAL_INTERRUPTS HT32_IRQ_NEXTINT
+
+#endif /* __ARCH_ARM_SRC_HT32F491X3_CHIP_H */
diff --git a/arch/arm/src/ht32f491x3/hardware/ht32f491x3_crm.h b/arch/arm/src/ht32f491x3/hardware/ht32f491x3_crm.h
new file mode 100644
index 00000000000..2d0387e2778
--- /dev/null
+++ b/arch/arm/src/ht32f491x3/hardware/ht32f491x3_crm.h
@@ -0,0 +1,249 @@
+/****************************************************************************
+ * arch/arm/src/ht32f491x3/hardware/ht32f491x3_crm.h
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_HT32F491X3_HARDWARE_HT32F491X3_CRM_H
+#define __ARCH_ARM_SRC_HT32F491X3_HARDWARE_HT32F491X3_CRM_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "chip.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Register Offsets *********************************************************/
+
+#define HT32_CRM_CTRL_OFFSET 0x000
+#define HT32_CRM_PLLCFG_OFFSET 0x004
+#define HT32_CRM_CFG_OFFSET 0x008
+#define HT32_CRM_CLKINT_OFFSET 0x00c
+#define HT32_CRM_AHBRST1_OFFSET 0x010
+#define HT32_CRM_AHBRST2_OFFSET 0x014
+#define HT32_CRM_AHBRST3_OFFSET 0x018
+#define HT32_CRM_APB1RST_OFFSET 0x020
+#define HT32_CRM_APB2RST_OFFSET 0x024
+#define HT32_CRM_AHBEN1_OFFSET 0x030
+#define HT32_CRM_AHBEN2_OFFSET 0x034
+#define HT32_CRM_AHBEN3_OFFSET 0x038
+#define HT32_CRM_APB1EN_OFFSET 0x040
+#define HT32_CRM_APB2EN_OFFSET 0x044
+#define HT32_CRM_APB1LPEN_OFFSET 0x060
+#define HT32_CRM_APB2LPEN_OFFSET 0x064
+#define HT32_CRM_PICLKS_OFFSET 0x068
+#define HT32_CRM_MISC1_OFFSET 0x0a0
+#define HT32_CRM_MISC2_OFFSET 0x0a4
+
+/* Register Addresses *******************************************************/
+
+#define HT32_CRM_CTRL (HT32_CRM_BASE + HT32_CRM_CTRL_OFFSET)
+#define HT32_CRM_PLLCFG (HT32_CRM_BASE + HT32_CRM_PLLCFG_OFFSET)
+#define HT32_CRM_CFG (HT32_CRM_BASE + HT32_CRM_CFG_OFFSET)
+#define HT32_CRM_CLKINT (HT32_CRM_BASE + HT32_CRM_CLKINT_OFFSET)
+#define HT32_CRM_AHBRST1 (HT32_CRM_BASE + HT32_CRM_AHBRST1_OFFSET)
+#define HT32_CRM_AHBRST2 (HT32_CRM_BASE + HT32_CRM_AHBRST2_OFFSET)
+#define HT32_CRM_AHBRST3 (HT32_CRM_BASE + HT32_CRM_AHBRST3_OFFSET)
+#define HT32_CRM_APB1RST (HT32_CRM_BASE + HT32_CRM_APB1RST_OFFSET)
+#define HT32_CRM_APB2RST (HT32_CRM_BASE + HT32_CRM_APB2RST_OFFSET)
+#define HT32_CRM_AHBEN1 (HT32_CRM_BASE + HT32_CRM_AHBEN1_OFFSET)
+#define HT32_CRM_AHBEN2 (HT32_CRM_BASE + HT32_CRM_AHBEN2_OFFSET)
+#define HT32_CRM_AHBEN3 (HT32_CRM_BASE + HT32_CRM_AHBEN3_OFFSET)
+#define HT32_CRM_APB1EN (HT32_CRM_BASE + HT32_CRM_APB1EN_OFFSET)
+#define HT32_CRM_APB2EN (HT32_CRM_BASE + HT32_CRM_APB2EN_OFFSET)
+#define HT32_CRM_APB1LPEN (HT32_CRM_BASE + HT32_CRM_APB1LPEN_OFFSET)
+#define HT32_CRM_APB2LPEN (HT32_CRM_BASE + HT32_CRM_APB2LPEN_OFFSET)
+#define HT32_CRM_PICLKS (HT32_CRM_BASE + HT32_CRM_PICLKS_OFFSET)
+#define HT32_CRM_MISC1 (HT32_CRM_BASE + HT32_CRM_MISC1_OFFSET)
+#define HT32_CRM_MISC2 (HT32_CRM_BASE + HT32_CRM_MISC2_OFFSET)
+
+/* Clock control register ***************************************************/
+
+#define HT32_CRM_CTRL_HICKEN (1 << 0)
+#define HT32_CRM_CTRL_HICKSTBL (1 << 1)
+#define HT32_CRM_CTRL_HEXTEN (1 << 16)
+#define HT32_CRM_CTRL_HEXTSTBL (1 << 17)
+#define HT32_CRM_CTRL_HEXTBYPS (1 << 18)
+#define HT32_CRM_CTRL_PLLEN (1 << 24)
+#define HT32_CRM_CTRL_PLLSTBL (1 << 25)
+
+/* PLL configuration register ***********************************************/
+
+#define HT32_CRM_PLLCFG_PLLMS_SHIFT (0)
+#define HT32_CRM_PLLCFG_PLLMS_MASK (0x0f << HT32_CRM_PLLCFG_PLLMS_SHIFT)
+#define HT32_CRM_PLLCFG_PLLNS_SHIFT (6)
+#define HT32_CRM_PLLCFG_PLLNS_MASK (0x1ff << HT32_CRM_PLLCFG_PLLNS_SHIFT)
+#define HT32_CRM_PLLCFG_PLLFR_SHIFT (16)
+#define HT32_CRM_PLLCFG_PLLFR_MASK (7 << HT32_CRM_PLLCFG_PLLFR_SHIFT)
+#define HT32_CRM_PLLCFG_PLLRCS (1 << 22)
+
+#define HT32_CRM_PLLCFG_SOURCE_HICK 0
+#define HT32_CRM_PLLCFG_SOURCE_HEXT HT32_CRM_PLLCFG_PLLRCS
+
+#define HT32_CRM_PLLCFG_FR_1 (0 << HT32_CRM_PLLCFG_PLLFR_SHIFT)
+#define HT32_CRM_PLLCFG_FR_2 (1 << HT32_CRM_PLLCFG_PLLFR_SHIFT)
+#define HT32_CRM_PLLCFG_FR_4 (2 << HT32_CRM_PLLCFG_PLLFR_SHIFT)
+#define HT32_CRM_PLLCFG_FR_8 (3 << HT32_CRM_PLLCFG_PLLFR_SHIFT)
+#define HT32_CRM_PLLCFG_FR_16 (4 << HT32_CRM_PLLCFG_PLLFR_SHIFT)
+#define HT32_CRM_PLLCFG_FR_32 (5 << HT32_CRM_PLLCFG_PLLFR_SHIFT)
+
+/* Clock configuration register *********************************************/
+
+#define HT32_CRM_CFG_SCLKSEL_SHIFT (0)
+#define HT32_CRM_CFG_SCLKSEL_MASK (3 << HT32_CRM_CFG_SCLKSEL_SHIFT)
+# define HT32_CRM_CFG_SEL_HICK (0 << HT32_CRM_CFG_SCLKSEL_SHIFT)
+# define HT32_CRM_CFG_SEL_HEXT (1 << HT32_CRM_CFG_SCLKSEL_SHIFT)
+# define HT32_CRM_CFG_SEL_PLL (2 << HT32_CRM_CFG_SCLKSEL_SHIFT)
+
+#define HT32_CRM_CFG_SCLKSTS_SHIFT (2)
+#define HT32_CRM_CFG_SCLKSTS_MASK (3 << HT32_CRM_CFG_SCLKSTS_SHIFT)
+# define HT32_CRM_CFG_STS_HICK (0 << HT32_CRM_CFG_SCLKSTS_SHIFT)
+# define HT32_CRM_CFG_STS_HEXT (1 << HT32_CRM_CFG_SCLKSTS_SHIFT)
+# define HT32_CRM_CFG_STS_PLL (2 << HT32_CRM_CFG_SCLKSTS_SHIFT)
+
+#define HT32_CRM_CFG_AHBDIV_SHIFT (4)
+#define HT32_CRM_CFG_AHBDIV_MASK (0x0f << HT32_CRM_CFG_AHBDIV_SHIFT)
+# define HT32_CRM_CFG_AHBDIV_NONE (0 << HT32_CRM_CFG_AHBDIV_SHIFT)
+# define HT32_CRM_CFG_AHBDIV_2 (8 << HT32_CRM_CFG_AHBDIV_SHIFT)
+# define HT32_CRM_CFG_AHBDIV_4 (9 << HT32_CRM_CFG_AHBDIV_SHIFT)
+# define HT32_CRM_CFG_AHBDIV_8 (10 << HT32_CRM_CFG_AHBDIV_SHIFT)
+# define HT32_CRM_CFG_AHBDIV_16 (11 << HT32_CRM_CFG_AHBDIV_SHIFT)
+# define HT32_CRM_CFG_AHBDIV_64 (12 << HT32_CRM_CFG_AHBDIV_SHIFT)
+# define HT32_CRM_CFG_AHBDIV_128 (13 << HT32_CRM_CFG_AHBDIV_SHIFT)
+# define HT32_CRM_CFG_AHBDIV_256 (14 << HT32_CRM_CFG_AHBDIV_SHIFT)
+# define HT32_CRM_CFG_AHBDIV_512 (15 << HT32_CRM_CFG_AHBDIV_SHIFT)
+
+#define HT32_CRM_CFG_APB1DIV_SHIFT (10)
+#define HT32_CRM_CFG_APB1DIV_MASK (7 << HT32_CRM_CFG_APB1DIV_SHIFT)
+# define HT32_CRM_CFG_APB1DIV_1 (0 << HT32_CRM_CFG_APB1DIV_SHIFT)
+# define HT32_CRM_CFG_APB1DIV_2 (4 << HT32_CRM_CFG_APB1DIV_SHIFT)
+# define HT32_CRM_CFG_APB1DIV_4 (5 << HT32_CRM_CFG_APB1DIV_SHIFT)
+# define HT32_CRM_CFG_APB1DIV_8 (6 << HT32_CRM_CFG_APB1DIV_SHIFT)
+# define HT32_CRM_CFG_APB1DIV_16 (7 << HT32_CRM_CFG_APB1DIV_SHIFT)
+# define HT32_CRM_CFG_APB1DIV_NONE HT32_CRM_CFG_APB1DIV_1
+
+#define HT32_CRM_CFG_APB2DIV_SHIFT (13)
+#define HT32_CRM_CFG_APB2DIV_MASK (7 << HT32_CRM_CFG_APB2DIV_SHIFT)
+# define HT32_CRM_CFG_APB2DIV_1 (0 << HT32_CRM_CFG_APB2DIV_SHIFT)
+# define HT32_CRM_CFG_APB2DIV_2 (4 << HT32_CRM_CFG_APB2DIV_SHIFT)
+# define HT32_CRM_CFG_APB2DIV_4 (5 << HT32_CRM_CFG_APB2DIV_SHIFT)
+# define HT32_CRM_CFG_APB2DIV_8 (6 << HT32_CRM_CFG_APB2DIV_SHIFT)
+# define HT32_CRM_CFG_APB2DIV_16 (7 << HT32_CRM_CFG_APB2DIV_SHIFT)
+# define HT32_CRM_CFG_APB2DIV_NONE HT32_CRM_CFG_APB2DIV_1
+
+/* Clock misc1 register *****************************************************/
+
+#define HT32_CRM_MISC1_HICKDIV (1 << 12)
+#define HT32_CRM_MISC1_HICKTOUSB (1 << 13)
+#define HT32_CRM_MISC1_HICKTOSCLK (1 << 14)
+#define HT32_CRM_MISC1_PLLCLKTOADC (1 << 15)
+
+/* Clock misc2 register *****************************************************/
+
+#define HT32_CRM_MISC2_AUTOSTEP_SHIFT (4)
+#define HT32_CRM_MISC2_AUTOSTEP_MASK (3 << HT32_CRM_MISC2_AUTOSTEP_SHIFT)
+#define HT32_CRM_MISC2_AUTOSTEP_ENABLE (3 << HT32_CRM_MISC2_AUTOSTEP_SHIFT)
+#define HT32_CRM_MISC2_HICKDIV_SHIFT (16)
+#define HT32_CRM_MISC2_HICKDIV_MASK (7 << HT32_CRM_MISC2_HICKDIV_SHIFT)
+# define HT32_CRM_MISC2_HICKDIV_1 (0 << HT32_CRM_MISC2_HICKDIV_SHIFT)
+# define HT32_CRM_MISC2_HICKDIV_2 (1 << HT32_CRM_MISC2_HICKDIV_SHIFT)
+# define HT32_CRM_MISC2_HICKDIV_4 (2 << HT32_CRM_MISC2_HICKDIV_SHIFT)
+# define HT32_CRM_MISC2_HICKDIV_8 (3 << HT32_CRM_MISC2_HICKDIV_SHIFT)
+# define HT32_CRM_MISC2_HICKDIV_16 (4 << HT32_CRM_MISC2_HICKDIV_SHIFT)
+
+/* Peripheral independent clocks register ***********************************/
+
+#define HT32_CRM_PICLKS_USART1SEL_SHIFT (0)
+#define HT32_CRM_PICLKS_USART1SEL_MASK (3 << HT32_CRM_PICLKS_USART1SEL_SHIFT)
+#define HT32_CRM_PICLKS_USART2SEL_SHIFT (2)
+#define HT32_CRM_PICLKS_USART2SEL_MASK (3 << HT32_CRM_PICLKS_USART2SEL_SHIFT)
+#define HT32_CRM_PICLKS_USART3SEL_SHIFT (4)
+#define HT32_CRM_PICLKS_USART3SEL_MASK (3 << HT32_CRM_PICLKS_USART3SEL_SHIFT)
+
+#define HT32_CRM_PICLKS_USARTSEL_PCLK 0
+#define HT32_CRM_PICLKS_USARTSEL_SCLK 1
+#define HT32_CRM_PICLKS_USARTSEL_HICK 2
+#define HT32_CRM_PICLKS_USARTSEL_LEXT 3
+
+/* Peripheral reset registers ***********************************************/
+
+#define HT32_CRM_APB1RST_USART2RST (1 << 17)
+#define HT32_CRM_APB1RST_USART3RST (1 << 18)
+
+#define HT32_CRM_APB2RST_USART1RST (1 << 4)
+
+/* Clock enable registers ***************************************************/
+
+#define HT32_CRM_AHBEN1_GPIOAEN (1 << 0)
+#define HT32_CRM_AHBEN1_GPIOBEN (1 << 1)
+#define HT32_CRM_AHBEN1_GPIOCEN (1 << 2)
+#define HT32_CRM_AHBEN1_GPIODEN (1 << 3)
+#define HT32_CRM_AHBEN1_GPIOEEN (1 << 4)
+#define HT32_CRM_AHBEN1_GPIOFEN (1 << 5)
+#define HT32_CRM_AHBEN1_CRCEN (1 << 12)
+#define HT32_CRM_AHBEN1_DMA1EN (1 << 22)
+#define HT32_CRM_AHBEN1_DMA2EN (1 << 24)
+
+#define HT32_CRM_AHBEN2_OTGFS1EN (1 << 7)
+
+#define HT32_CRM_AHBEN3_XMCEN (1 << 0)
+
+#define HT32_CRM_APB1EN_TMR2EN (1 << 0)
+#define HT32_CRM_APB1EN_TMR3EN (1 << 1)
+#define HT32_CRM_APB1EN_TMR4EN (1 << 2)
+#define HT32_CRM_APB1EN_TMR6EN (1 << 4)
+#define HT32_CRM_APB1EN_TMR7EN (1 << 5)
+#define HT32_CRM_APB1EN_TMR12EN (1 << 6)
+#define HT32_CRM_APB1EN_TMR13EN (1 << 7)
+#define HT32_CRM_APB1EN_TMR14EN (1 << 8)
+#define HT32_CRM_APB1EN_WWDTEN (1 << 11)
+#define HT32_CRM_APB1EN_SPI2EN (1 << 14)
+#define HT32_CRM_APB1EN_SPI3EN (1 << 15)
+#define HT32_CRM_APB1EN_USART2EN (1 << 17)
+#define HT32_CRM_APB1EN_USART3EN (1 << 18)
+#define HT32_CRM_APB1EN_USART4EN (1 << 19)
+#define HT32_CRM_APB1EN_USART5EN (1 << 20)
+#define HT32_CRM_APB1EN_I2C1EN (1 << 21)
+#define HT32_CRM_APB1EN_I2C2EN (1 << 22)
+#define HT32_CRM_APB1EN_I2C3EN (1 << 23)
+#define HT32_CRM_APB1EN_CAN1EN (1 << 25)
+#define HT32_CRM_APB1EN_CAN2EN (1 << 26)
+#define HT32_CRM_APB1EN_PWCEN (1 << 28)
+#define HT32_CRM_APB1EN_DACEN (1 << 29)
+#define HT32_CRM_APB1EN_USART7EN (1u << 30)
+#define HT32_CRM_APB1EN_USART8EN (1u << 31)
+
+#define HT32_CRM_APB2EN_TMR1EN (1 << 0)
+#define HT32_CRM_APB2EN_USART1EN (1 << 4)
+#define HT32_CRM_APB2EN_USART6EN (1 << 5)
+#define HT32_CRM_APB2EN_ADC1EN (1 << 8)
+#define HT32_CRM_APB2EN_SPI1EN (1 << 12)
+#define HT32_CRM_APB2EN_SCFGEN (1 << 14)
+#define HT32_CRM_APB2EN_TMR9EN (1 << 16)
+#define HT32_CRM_APB2EN_TMR10EN (1 << 17)
+#define HT32_CRM_APB2EN_TMR11EN (1 << 18)
+#define HT32_CRM_APB2EN_ACCEN (1 << 29)
+
+#endif /* __ARCH_ARM_SRC_HT32F491X3_HARDWARE_HT32F491X3_CRM_H */
diff --git a/arch/arm/src/ht32f491x3/hardware/ht32f491x3_flash.h b/arch/arm/src/ht32f491x3/hardware/ht32f491x3_flash.h
new file mode 100644
index 00000000000..6cea92716b7
--- /dev/null
+++ b/arch/arm/src/ht32f491x3/hardware/ht32f491x3_flash.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+ * arch/arm/src/ht32f491x3/hardware/ht32f491x3_flash.h
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_HT32F491X3_HARDWARE_HT32F491X3_FLASH_H
+#define __ARCH_ARM_SRC_HT32F491X3_HARDWARE_HT32F491X3_FLASH_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "ht32f491x3_memorymap.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define HT32_FLASH_PSR_OFFSET 0x000
+
+#define HT32_FLASH_PSR (HT32_FLASHREG_BASE + HT32_FLASH_PSR_OFFSET)
+
+#define HT32_FLASH_PSR_PROGRAM(wtcyc) (0x150u | (wtcyc))
+
+#define HT32_FLASH_WAIT_CYCLE_0 0x00
+#define HT32_FLASH_WAIT_CYCLE_1 0x01
+#define HT32_FLASH_WAIT_CYCLE_2 0x02
+#define HT32_FLASH_WAIT_CYCLE_3 0x03
+#define HT32_FLASH_WAIT_CYCLE_4 0x04
+
+#endif /* __ARCH_ARM_SRC_HT32F491X3_HARDWARE_HT32F491X3_FLASH_H */
diff --git a/arch/arm/src/ht32f491x3/hardware/ht32f491x3_gpio.h b/arch/arm/src/ht32f491x3/hardware/ht32f491x3_gpio.h
new file mode 100644
index 00000000000..451c4667269
--- /dev/null
+++ b/arch/arm/src/ht32f491x3/hardware/ht32f491x3_gpio.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+ * arch/arm/src/ht32f491x3/hardware/ht32f491x3_gpio.h
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_HT32F491X3_HARDWARE_HT32F491X3_GPIO_H
+#define __ARCH_ARM_SRC_HT32F491X3_HARDWARE_HT32F491X3_GPIO_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <stdint.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* GPIO register offsets ****************************************************/
+
+#define HT32_GPIO_CFGR_OFFSET 0x0000
+#define HT32_GPIO_OMODE_OFFSET 0x0004
+#define HT32_GPIO_ODRVR_OFFSET 0x0008
+#define HT32_GPIO_PULL_OFFSET 0x000c
+#define HT32_GPIO_IDT_OFFSET 0x0010
+#define HT32_GPIO_ODT_OFFSET 0x0014
+#define HT32_GPIO_SCR_OFFSET 0x0018
+#define HT32_GPIO_WPR_OFFSET 0x001c
+#define HT32_GPIO_MUXL_OFFSET 0x0020
+#define HT32_GPIO_MUXH_OFFSET 0x0024
+#define HT32_GPIO_CLR_OFFSET 0x0028
+
+/* GPIO helpers *************************************************************/
+
+#define HT32_GPIO_PIN(n) (1u << (n))
+
+#define HT32_GPIO_MODE_SHIFT(n) ((n) << 1)
+#define HT32_GPIO_MODE_MASK(n) (3u << HT32_GPIO_MODE_SHIFT(n))
+#define HT32_GPIO_MODE_VALUE(n, v) ((uint32_t)(v) << HT32_GPIO_MODE_SHIFT(n))
+
+#define HT32_GPIO_ODRVR_SHIFT(n) ((n) << 1)
+#define HT32_GPIO_ODRVR_MASK(n) (3u << HT32_GPIO_ODRVR_SHIFT(n))
+#define HT32_GPIO_ODRVR_VALUE(n, v) ((uint32_t)(v) << HT32_GPIO_ODRVR_SHIFT(n))
+
+#define HT32_GPIO_PULL_SHIFT(n) ((n) << 1)
+#define HT32_GPIO_PULL_MASK(n) (3u << HT32_GPIO_PULL_SHIFT(n))
+#define HT32_GPIO_PULL_VALUE(n, v) ((uint32_t)(v) << HT32_GPIO_PULL_SHIFT(n))
+
+#define HT32_GPIO_MUX_SHIFT(n) (((n) & 7u) << 2)
+#define HT32_GPIO_MUX_MASK(n) (0x0fu << HT32_GPIO_MUX_SHIFT(n))
+#define HT32_GPIO_MUX_VALUE(n, af) ((uint32_t)(af) << HT32_GPIO_MUX_SHIFT(n))
+#define HT32_GPIO_MUX_OFFSET(n) (((n) < 8u) ? HT32_GPIO_MUXL_OFFSET : \
+ HT32_GPIO_MUXH_OFFSET)
+
+/* Compatibility aliases for board pinmux code that still uses the older
+ * CFGLR/CFGHR naming for alternate-function selection.
+ */
+
+#define HT32_GPIO_CFGLR_OFFSET HT32_GPIO_MUXL_OFFSET
+#define HT32_GPIO_CFGHR_OFFSET HT32_GPIO_MUXH_OFFSET
+#define HT32_GPIO_CFG_SHIFT(n) HT32_GPIO_MUX_SHIFT(n)
+#define HT32_GPIO_CFG_MASK(n) HT32_GPIO_MUX_MASK(n)
+#define HT32_GPIO_CFG_VALUE(n, af) HT32_GPIO_MUX_VALUE(n, af)
+#define HT32_GPIO_CFG_OFFSET(n) HT32_GPIO_MUX_OFFSET(n)
+
+#endif /* __ARCH_ARM_SRC_HT32F491X3_HARDWARE_HT32F491X3_GPIO_H */
diff --git a/arch/arm/src/ht32f491x3/hardware/ht32f491x3_memorymap.h b/arch/arm/src/ht32f491x3/hardware/ht32f491x3_memorymap.h
new file mode 100644
index 00000000000..fbe0c1228f3
--- /dev/null
+++ b/arch/arm/src/ht32f491x3/hardware/ht32f491x3_memorymap.h
@@ -0,0 +1,127 @@
+/****************************************************************************
+ * arch/arm/src/ht32f491x3/hardware/ht32f491x3_memorymap.h
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_HT32F491X3_HARDWARE_HT32F491X3_MEMORYMAP_H
+#define __ARCH_ARM_SRC_HT32F491X3_HARDWARE_HT32F491X3_MEMORYMAP_H
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Address blocks ***********************************************************/
+
+#define HT32_CODE_BASE 0x00000000
+#define HT32_SRAM_BASE 0x20000000
+#define HT32_PERIPH_BASE 0x40000000
+#define HT32_XMC_MEM_BASE 0x60000000
+#define HT32_XMC_BANK1 HT32_XMC_MEM_BASE
+#define HT32_XMC_REG_BASE 0xa0000000
+#define HT32_CORTEX_BASE 0xe0000000
+
+/* Code region **************************************************************/
+
+#define HT32_BOOT_BASE 0x00000000
+#define HT32_FLASH_BASE 0x08000000
+#define HT32_FLASHREG_BASE 0x40023c00
+#define HT32_SYSMEM_BASE 0x1fffa400
+#define HT32_USERDATA_BASE 0x1ffff800
+
+/* SRAM region **************************************************************/
+
+#define HT32_SRAMBB_BASE 0x22000000
+
+/* Peripheral region ********************************************************/
+
+#define HT32_APB1_BASE 0x40000000
+#define HT32_APB2_BASE 0x40010000
+#define HT32_AHB1_BASE 0x40020000
+#define HT32_AHB2_BASE 0x50000000
+
+/* APB1 */
+
+#define HT32_TMR2_BASE 0x40000000
+#define HT32_TMR3_BASE 0x40000400
+#define HT32_TMR4_BASE 0x40000800
+#define HT32_TMR6_BASE 0x40001000
+#define HT32_TMR7_BASE 0x40001400
+#define HT32_TMR12_BASE 0x40001800
+#define HT32_TMR13_BASE 0x40001c00
+#define HT32_TMR14_BASE 0x40002000
+#define HT32_ERTC_BASE 0x40002800
+#define HT32_WWDT_BASE 0x40002c00
+#define HT32_WDT_BASE 0x40003000
+#define HT32_SPI2_BASE 0x40003800
+#define HT32_SPI3_BASE 0x40003c00
+#define HT32_USART2_BASE 0x40004400
+#define HT32_USART3_BASE 0x40004800
+#define HT32_USART4_BASE 0x40004c00
+#define HT32_USART5_BASE 0x40005000
+#define HT32_I2C1_BASE 0x40005400
+#define HT32_I2C2_BASE 0x40005800
+#define HT32_I2C3_BASE 0x40005c00
+#define HT32_CAN1_BASE 0x40006400
+#define HT32_CAN2_BASE 0x40006800
+#define HT32_PWC_BASE 0x40007000
+#define HT32_DAC_BASE 0x40007400
+#define HT32_USART7_BASE 0x40007800
+#define HT32_USART8_BASE 0x40007c00
+
+/* APB2 */
+
+#define HT32_TMR1_BASE 0x40010000
+#define HT32_USART1_BASE 0x40011000
+#define HT32_USART6_BASE 0x40011400
+#define HT32_ADC1_BASE 0x40012000
+#define HT32_ADC_BASE HT32_ADC1_BASE
+#define HT32_ADCCOM_BASE 0x40012300
+#define HT32_SPI1_BASE 0x40013000
+#define HT32_SCFG_BASE 0x40013800
+#define HT32_EXINT_BASE 0x40013c00
+#define HT32_TMR9_BASE 0x40014000
+#define HT32_TMR10_BASE 0x40014400
+#define HT32_TMR11_BASE 0x40014800
+#define HT32_ACC_BASE 0x40017400
+
+/* AHB1 */
+
+#define HT32_GPIOA_BASE 0x40020000
+#define HT32_GPIOB_BASE 0x40020400
+#define HT32_GPIOC_BASE 0x40020800
+#define HT32_GPIOD_BASE 0x40020c00
+#define HT32_GPIOE_BASE 0x40021000
+#define HT32_GPIOF_BASE 0x40021400
+#define HT32_CRC_BASE 0x40023000
+#define HT32_CRM_BASE 0x40023800
+#define HT32_FLASHIF_BASE 0x40023c00
+#define HT32_DMA1_BASE 0x40026000
+#define HT32_DMA2_BASE 0x40026400
+
+/* AHB2 */
+
+#define HT32_OTGFS1_BASE 0x50000000
+#define HT32_OTGFS_BASE HT32_OTGFS1_BASE
+
+/* Cortex-M4 system control space *******************************************/
+
+#define HT32_SCS_BASE 0xe000e000
+
+#endif /* __ARCH_ARM_SRC_HT32F491X3_HARDWARE_HT32F491X3_MEMORYMAP_H */
diff --git a/arch/arm/src/ht32f491x3/hardware/ht32f491x3_pwc.h b/arch/arm/src/ht32f491x3/hardware/ht32f491x3_pwc.h
new file mode 100644
index 00000000000..94f80da4945
--- /dev/null
+++ b/arch/arm/src/ht32f491x3/hardware/ht32f491x3_pwc.h
@@ -0,0 +1,48 @@
+/****************************************************************************
+ * arch/arm/src/ht32f491x3/hardware/ht32f491x3_pwc.h
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_HT32F491X3_HARDWARE_HT32F491X3_PWC_H
+#define __ARCH_ARM_SRC_HT32F491X3_HARDWARE_HT32F491X3_PWC_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "ht32f491x3_memorymap.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define HT32_PWC_LDOOV_OFFSET 0x010
+
+#define HT32_PWC_LDOOV (HT32_PWC_BASE + HT32_PWC_LDOOV_OFFSET)
+
+#define HT32_PWC_LDOOVSEL_SHIFT 0
+#define HT32_PWC_LDOOVSEL_MASK (3 << HT32_PWC_LDOOVSEL_SHIFT)
+#define HT32_PWC_LDO_OUTPUT_1V1 (1 << HT32_PWC_LDOOVSEL_SHIFT)
+#define HT32_PWC_LDO_OUTPUT_1V2 (2 << HT32_PWC_LDOOVSEL_SHIFT)
+#define HT32_PWC_LDO_OUTPUT_1V3 (3 << HT32_PWC_LDOOVSEL_SHIFT)
+
+#endif /* __ARCH_ARM_SRC_HT32F491X3_HARDWARE_HT32F491X3_PWC_H */
diff --git a/arch/arm/src/ht32f491x3/hardware/ht32f491x3_uart.h b/arch/arm/src/ht32f491x3/hardware/ht32f491x3_uart.h
new file mode 100644
index 00000000000..3d059206c2a
--- /dev/null
+++ b/arch/arm/src/ht32f491x3/hardware/ht32f491x3_uart.h
@@ -0,0 +1,147 @@
+/****************************************************************************
+ * arch/arm/src/ht32f491x3/hardware/ht32f491x3_uart.h
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_HT32F491X3_HARDWARE_HT32F491X3_UART_H
+#define __ARCH_ARM_SRC_HT32F491X3_HARDWARE_HT32F491X3_UART_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "chip.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Register Offsets *********************************************************/
+
+#define HT32_USART_STS_OFFSET 0x00
+#define HT32_USART_DT_OFFSET 0x04
+#define HT32_USART_BAUDR_OFFSET 0x08
+#define HT32_USART_CTRL1_OFFSET 0x0c
+#define HT32_USART_CTRL2_OFFSET 0x10
+#define HT32_USART_CTRL3_OFFSET 0x14
+#define HT32_USART_GDIV_OFFSET 0x18
+#define HT32_USART_RTOR_OFFSET 0x1c
+#define HT32_USART_IFC_OFFSET 0x20
+
+/* Register Addresses *******************************************************/
+
+#define HT32_USART1_STS (HT32_USART1_BASE + HT32_USART_STS_OFFSET)
+#define HT32_USART1_DT (HT32_USART1_BASE + HT32_USART_DT_OFFSET)
+#define HT32_USART1_BAUDR (HT32_USART1_BASE + HT32_USART_BAUDR_OFFSET)
+#define HT32_USART1_CTRL1 (HT32_USART1_BASE + HT32_USART_CTRL1_OFFSET)
+#define HT32_USART1_CTRL2 (HT32_USART1_BASE + HT32_USART_CTRL2_OFFSET)
+#define HT32_USART1_CTRL3 (HT32_USART1_BASE + HT32_USART_CTRL3_OFFSET)
+
+#define HT32_USART2_STS (HT32_USART2_BASE + HT32_USART_STS_OFFSET)
+#define HT32_USART2_DT (HT32_USART2_BASE + HT32_USART_DT_OFFSET)
+#define HT32_USART2_BAUDR (HT32_USART2_BASE + HT32_USART_BAUDR_OFFSET)
+#define HT32_USART2_CTRL1 (HT32_USART2_BASE + HT32_USART_CTRL1_OFFSET)
+#define HT32_USART2_CTRL2 (HT32_USART2_BASE + HT32_USART_CTRL2_OFFSET)
+#define HT32_USART2_CTRL3 (HT32_USART2_BASE + HT32_USART_CTRL3_OFFSET)
+
+#define HT32_USART3_STS (HT32_USART3_BASE + HT32_USART_STS_OFFSET)
+#define HT32_USART3_DT (HT32_USART3_BASE + HT32_USART_DT_OFFSET)
+#define HT32_USART3_BAUDR (HT32_USART3_BASE + HT32_USART_BAUDR_OFFSET)
+#define HT32_USART3_CTRL1 (HT32_USART3_BASE + HT32_USART_CTRL1_OFFSET)
+#define HT32_USART3_CTRL2 (HT32_USART3_BASE + HT32_USART_CTRL2_OFFSET)
+#define HT32_USART3_CTRL3 (HT32_USART3_BASE + HT32_USART_CTRL3_OFFSET)
+
+/* Status register **********************************************************/
+
+#define HT32_USART_STS_PERR (1 << 0)
+#define HT32_USART_STS_FERR (1 << 1)
+#define HT32_USART_STS_NERR (1 << 2)
+#define HT32_USART_STS_ROERR (1 << 3)
+#define HT32_USART_STS_IDLEF (1 << 4)
+#define HT32_USART_STS_RDBF (1 << 5)
+#define HT32_USART_STS_TDC (1 << 6)
+#define HT32_USART_STS_TDBE (1 << 7)
+#define HT32_USART_STS_BFF (1 << 8)
+#define HT32_USART_STS_CTSCF (1 << 9)
+#define HT32_USART_STS_LPWUF (1 << 20)
+#define HT32_USART_STS_TXON (1 << 21)
+#define HT32_USART_STS_RXON (1 << 22)
+
+/* Data register ************************************************************/
+
+#define HT32_USART_DT_SHIFT (0)
+#define HT32_USART_DT_MASK (0x1ff << HT32_USART_DT_SHIFT)
+
+/* Baud rate register *******************************************************/
+
+#define HT32_USART_BAUDR_DIV_SHIFT (0)
+#define HT32_USART_BAUDR_DIV_MASK (0xffff << HT32_USART_BAUDR_DIV_SHIFT)
+
+/* Control register 1 *******************************************************/
+
+#define HT32_USART_CTRL1_SBF (1 << 0)
+#define HT32_USART_CTRL1_RM (1 << 1)
+#define HT32_USART_CTRL1_REN (1 << 2)
+#define HT32_USART_CTRL1_TEN (1 << 3)
+#define HT32_USART_CTRL1_IDLEIEN (1 << 4)
+#define HT32_USART_CTRL1_RDBFIEN (1 << 5)
+#define HT32_USART_CTRL1_TDCIEN (1 << 6)
+#define HT32_USART_CTRL1_TDBEIEN (1 << 7)
+#define HT32_USART_CTRL1_PERRIEN (1 << 8)
+#define HT32_USART_CTRL1_PSEL (1 << 9)
+#define HT32_USART_CTRL1_PEN (1 << 10)
+#define HT32_USART_CTRL1_WUM (1 << 11)
+#define HT32_USART_CTRL1_DBN0 (1 << 12)
+#define HT32_USART_CTRL1_UEN (1 << 13)
+#define HT32_USART_CTRL1_DBN1 (1 << 28)
+
+/* Control register 2 *******************************************************/
+
+#define HT32_USART_CTRL2_BFIEN (1 << 6)
+#define HT32_USART_CTRL2_LBCP (1 << 8)
+#define HT32_USART_CTRL2_CLKPHA (1 << 9)
+#define HT32_USART_CTRL2_CLKPOL (1 << 10)
+#define HT32_USART_CTRL2_CLKEN (1 << 11)
+#define HT32_USART_CTRL2_STOPBN_SHIFT (12)
+#define HT32_USART_CTRL2_STOPBN_MASK (3 << HT32_USART_CTRL2_STOPBN_SHIFT)
+#define HT32_USART_CTRL2_STOPBN_10 (0 << HT32_USART_CTRL2_STOPBN_SHIFT)
+#define HT32_USART_CTRL2_STOPBN_05 (1 << HT32_USART_CTRL2_STOPBN_SHIFT)
+#define HT32_USART_CTRL2_STOPBN_20 (2 << HT32_USART_CTRL2_STOPBN_SHIFT)
+#define HT32_USART_CTRL2_STOPBN_15 (3 << HT32_USART_CTRL2_STOPBN_SHIFT)
+
+/* Control register 3 *******************************************************/
+
+#define HT32_USART_CTRL3_ERRIEN (1 << 0)
+#define HT32_USART_CTRL3_DMAREN (1 << 6)
+#define HT32_USART_CTRL3_DMATEN (1 << 7)
+#define HT32_USART_CTRL3_RTSEN (1 << 8)
+#define HT32_USART_CTRL3_CTSEN (1 << 9)
+#define HT32_USART_CTRL3_CTSCFIEN (1 << 10)
+#define HT32_USART_CTRL3_RS485EN (1 << 14)
+#define HT32_USART_CTRL3_DEP (1 << 15)
+
+/* Convenience aliases ******************************************************/
+
+#define HT32_USART_RDR_OFFSET HT32_USART_DT_OFFSET
+#define HT32_USART_TDR_OFFSET HT32_USART_DT_OFFSET
+
+#endif /* __ARCH_ARM_SRC_HT32F491X3_HARDWARE_HT32F491X3_UART_H */
diff --git a/arch/arm/src/ht32f491x3/ht32f491x3_config.h b/arch/arm/src/ht32f491x3/ht32f491x3_config.h
new file mode 100644
index 00000000000..459d4d29bc8
--- /dev/null
+++ b/arch/arm/src/ht32f491x3/ht32f491x3_config.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+ * arch/arm/src/ht32f491x3/ht32f491x3_config.h
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_HT32F491X3_HT32F491X3_CONFIG_H
+#define __ARCH_ARM_SRC_HT32F491X3_HT32F491X3_CONFIG_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#undef HAVE_UART
+#if defined(CONFIG_HT32F491X3_USART1_SERIALDRIVER) || \
+ defined(CONFIG_HT32F491X3_USART2_SERIALDRIVER) || \
+ defined(CONFIG_HT32F491X3_USART3_SERIALDRIVER)
+# define HAVE_UART 1
+#endif
+
+#undef HAVE_CONSOLE
+#if (defined(CONFIG_USART1_SERIAL_CONSOLE) && \
+ defined(CONFIG_HT32F491X3_USART1_SERIALDRIVER)) || \
+ (defined(CONFIG_USART2_SERIAL_CONSOLE) && \
+ defined(CONFIG_HT32F491X3_USART2_SERIALDRIVER)) || \
+ (defined(CONFIG_USART3_SERIAL_CONSOLE) && \
+ defined(CONFIG_HT32F491X3_USART3_SERIALDRIVER))
+# define HAVE_CONSOLE 1
+#endif
+
+#endif /* __ARCH_ARM_SRC_HT32F491X3_HT32F491X3_CONFIG_H */
diff --git a/arch/arm/src/ht32f491x3/ht32f491x3_gpio.c b/arch/arm/src/ht32f491x3/ht32f491x3_gpio.c
new file mode 100644
index 00000000000..92d3def504d
--- /dev/null
+++ b/arch/arm/src/ht32f491x3/ht32f491x3_gpio.c
@@ -0,0 +1,78 @@
+/****************************************************************************
+ * arch/arm/src/ht32f491x3/ht32f491x3_gpio.c
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "arm_internal.h"
+
+#include "ht32f491x3_gpio.h"
+
+#include "hardware/ht32f491x3_gpio.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+void ht32f491x3_gpioconfig(uintptr_t base, unsigned int pin,
+ unsigned int mode, bool opendrain,
+ unsigned int drive, unsigned int pull,
+ unsigned int af)
+{
+ modifyreg32(base + HT32_GPIO_CFGR_OFFSET,
+ HT32_GPIO_MODE_MASK(pin),
+ HT32_GPIO_MODE_VALUE(pin, mode));
+
+ modifyreg32(base + HT32_GPIO_OMODE_OFFSET,
+ HT32_GPIO_PIN(pin),
+ opendrain ? HT32_GPIO_PIN(pin) : 0);
+
+ modifyreg32(base + HT32_GPIO_ODRVR_OFFSET,
+ HT32_GPIO_ODRVR_MASK(pin),
+ HT32_GPIO_ODRVR_VALUE(pin, drive));
+
+ modifyreg32(base + HT32_GPIO_PULL_OFFSET,
+ HT32_GPIO_PULL_MASK(pin),
+ HT32_GPIO_PULL_VALUE(pin, pull));
+
+ modifyreg32(base + HT32_GPIO_MUX_OFFSET(pin),
+ HT32_GPIO_MUX_MASK(pin),
+ mode == HT32_GPIO_MODE_ALTFN ?
+ HT32_GPIO_MUX_VALUE(pin, af) : 0);
+}
+
+void ht32f491x3_gpiowrite(uintptr_t base, unsigned int pin, bool value)
+{
+ putreg32(HT32_GPIO_PIN(pin),
+ base + (value ? HT32_GPIO_SCR_OFFSET : HT32_GPIO_CLR_OFFSET));
+}
+
+bool ht32f491x3_gpioread(uintptr_t base, unsigned int pin)
+{
+ return (getreg32(base + HT32_GPIO_IDT_OFFSET) & HT32_GPIO_PIN(pin)) != 0;
+}
diff --git a/arch/arm/src/ht32f491x3/ht32f491x3_gpio.h b/arch/arm/src/ht32f491x3/ht32f491x3_gpio.h
new file mode 100644
index 00000000000..aae7b3ecf72
--- /dev/null
+++ b/arch/arm/src/ht32f491x3/ht32f491x3_gpio.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+ * arch/arm/src/ht32f491x3/ht32f491x3_gpio.h
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_HT32F491X3_HT32F491X3_GPIO_H
+#define __ARCH_ARM_SRC_HT32F491X3_HT32F491X3_GPIO_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdbool.h>
+#include <stdint.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define HT32_GPIO_MODE_INPUT 0u
+#define HT32_GPIO_MODE_OUTPUT 1u
+#define HT32_GPIO_MODE_ALTFN 2u
+#define HT32_GPIO_MODE_ANALOG 3u
+
+#define HT32_GPIO_DRIVE_LOW 0u
+#define HT32_GPIO_DRIVE_MEDIUM 1u
+#define HT32_GPIO_DRIVE_HIGH 2u
+
+#define HT32_GPIO_PULL_NONE 0u
+#define HT32_GPIO_PULL_UP 1u
+#define HT32_GPIO_PULL_DOWN 2u
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+void ht32f491x3_gpioconfig(uintptr_t base, unsigned int pin,
+ unsigned int mode, bool opendrain,
+ unsigned int drive, unsigned int pull,
+ unsigned int af);
+void ht32f491x3_gpiowrite(uintptr_t base, unsigned int pin, bool value);
+bool ht32f491x3_gpioread(uintptr_t base, unsigned int pin);
+
+#endif /* __ARCH_ARM_SRC_HT32F491X3_HT32F491X3_GPIO_H */
diff --git a/arch/arm/src/ht32f491x3/ht32f491x3_irq.c b/arch/arm/src/ht32f491x3/ht32f491x3_irq.c
new file mode 100644
index 00000000000..49f45c0f104
--- /dev/null
+++ b/arch/arm/src/ht32f491x3/ht32f491x3_irq.c
@@ -0,0 +1,310 @@
+/****************************************************************************
+ * arch/arm/src/ht32f491x3/ht32f491x3_irq.c
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <assert.h>
+#include <debug.h>
+#include <errno.h>
+#include <stdint.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/irq.h>
+#include <arch/irq.h>
+#include <arch/armv7-m/nvicpri.h>
+
+#include "nvic.h"
+#ifdef CONFIG_ARCH_RAMVECTORS
+# include "ram_vectors.h"
+#endif
+#include "arm_internal.h"
+#include "chip.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define DEFPRIORITY32 \
+ (NVIC_SYSH_PRIORITY_DEFAULT << 24 | \
+ NVIC_SYSH_PRIORITY_DEFAULT << 16 | \
+ NVIC_SYSH_PRIORITY_DEFAULT << 8 | \
+ NVIC_SYSH_PRIORITY_DEFAULT)
+
+#define NVIC_ENA_OFFSET (0)
+#define NVIC_CLRENA_OFFSET (NVIC_IRQ0_31_CLEAR - NVIC_IRQ0_31_ENABLE)
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+#ifdef CONFIG_DEBUG_FEATURES
+static int ht32_nmi(int irq, FAR void *context, FAR void *arg)
+{
+ UNUSED(irq);
+ UNUSED(context);
+ UNUSED(arg);
+
+ up_irq_save();
+ _err("PANIC!!! NMI received\n");
+ PANIC();
+ return 0;
+}
+
+static int ht32_pendsv(int irq, FAR void *context, FAR void *arg)
+{
+ UNUSED(irq);
+ UNUSED(context);
+ UNUSED(arg);
+
+ up_irq_save();
+ _err("PANIC!!! PendSV received\n");
+ PANIC();
+ return 0;
+}
+
+static int ht32_dbgmonitor(int irq, FAR void *context, FAR void *arg)
+{
+ UNUSED(irq);
+ UNUSED(context);
+ UNUSED(arg);
+
+ up_irq_save();
+ _err("PANIC!!! Debug Monitor received\n");
+ PANIC();
+ return 0;
+}
+
+static int ht32_reserved(int irq, FAR void *context, FAR void *arg)
+{
+ UNUSED(irq);
+ UNUSED(context);
+ UNUSED(arg);
+
+ up_irq_save();
+ _err("PANIC!!! Reserved interrupt\n");
+ PANIC();
+ return 0;
+}
+#endif
+
+static inline void ht32_prioritize_syscall(int priority)
+{
+ uint32_t regval;
+
+ regval = getreg32(NVIC_SYSH8_11_PRIORITY);
+ regval &= ~NVIC_SYSH_PRIORITY_PR11_MASK;
+ regval |= (priority << NVIC_SYSH_PRIORITY_PR11_SHIFT);
+ putreg32(regval, NVIC_SYSH8_11_PRIORITY);
+}
+
+static int ht32_irqinfo(int irq, uintptr_t *regaddr, uint32_t *bit,
+ uintptr_t offset)
+{
+ int n;
+
+ DEBUGASSERT(irq >= HT32_IRQ_NMI && irq < NR_IRQS);
+
+ if (irq >= HT32_IRQ_FIRST)
+ {
+ n = irq - HT32_IRQ_FIRST;
+ *regaddr = NVIC_IRQ_ENABLE(n) + offset;
+ *bit = (uint32_t)1 << (n & 0x1f);
+ }
+ else
+ {
+ *regaddr = NVIC_SYSHCON;
+ if (irq == HT32_IRQ_MEMFAULT)
+ {
+ *bit = NVIC_SYSHCON_MEMFAULTENA;
+ }
+ else if (irq == HT32_IRQ_BUSFAULT)
+ {
+ *bit = NVIC_SYSHCON_BUSFAULTENA;
+ }
+ else if (irq == HT32_IRQ_USAGEFAULT)
+ {
+ *bit = NVIC_SYSHCON_USGFAULTENA;
+ }
+ else if (irq == HT32_IRQ_SYSTICK)
+ {
+ *regaddr = NVIC_SYSTICK_CTRL;
+ *bit = NVIC_SYSTICK_CTRL_ENABLE;
+ }
+ else
+ {
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+void up_irqinitialize(void)
+{
+ uint32_t regaddr;
+ int num_priority_registers;
+ int i;
+
+ for (i = 0; i < NR_IRQS - HT32_IRQ_FIRST; i += 32)
+ {
+ putreg32(0xffffffff, NVIC_IRQ_CLEAR(i));
+ }
+
+#if defined(__ICCARM__)
+ putreg32((uint32_t)__vector_table, NVIC_VECTAB);
+#else
+ putreg32((uint32_t)_vectors, NVIC_VECTAB);
+#endif
+
+#ifdef CONFIG_ARCH_RAMVECTORS
+ arm_ramvec_initialize();
+#endif
+
+ putreg32(DEFPRIORITY32, NVIC_SYSH4_7_PRIORITY);
+ putreg32(DEFPRIORITY32, NVIC_SYSH8_11_PRIORITY);
+ putreg32(DEFPRIORITY32, NVIC_SYSH12_15_PRIORITY);
+
+ num_priority_registers = (getreg32(NVIC_ICTR) + 1) * 8;
+ regaddr = NVIC_IRQ0_3_PRIORITY;
+
+ while (num_priority_registers-- > 0)
+ {
+ putreg32(DEFPRIORITY32, regaddr);
+ regaddr += 4;
+ }
+
+ irq_attach(HT32_IRQ_SVCALL, arm_svcall, NULL);
+ irq_attach(HT32_IRQ_HARDFAULT, arm_hardfault, NULL);
+ ht32_prioritize_syscall(NVIC_SYSH_SVCALL_PRIORITY);
+
+#ifdef CONFIG_ARM_MPU
+ irq_attach(HT32_IRQ_MEMFAULT, arm_memfault, NULL);
+ up_enable_irq(HT32_IRQ_MEMFAULT);
+#endif
+
+#ifdef CONFIG_DEBUG_FEATURES
+ irq_attach(HT32_IRQ_NMI, ht32_nmi, NULL);
+#ifndef CONFIG_ARM_MPU
+ irq_attach(HT32_IRQ_MEMFAULT, arm_memfault, NULL);
+#endif
+ irq_attach(HT32_IRQ_BUSFAULT, arm_busfault, NULL);
+ irq_attach(HT32_IRQ_USAGEFAULT, arm_usagefault, NULL);
+ irq_attach(HT32_IRQ_PENDSV, ht32_pendsv, NULL);
+ irq_attach(HT32_IRQ_DBGMONITOR, ht32_dbgmonitor, NULL);
+ irq_attach(HT32_IRQ_RESERVED, ht32_reserved, NULL);
+#endif
+
+#ifndef CONFIG_SUPPRESS_INTERRUPTS
+ arm_color_intstack();
+ up_irq_enable();
+#endif
+}
+
+void up_disable_irq(int irq)
+{
+ uintptr_t regaddr;
+ uint32_t regval;
+ uint32_t bit;
+
+ if (ht32_irqinfo(irq, ®addr, &bit, NVIC_CLRENA_OFFSET) < 0)
+ {
+ return;
+ }
+
+ if (irq >= HT32_IRQ_FIRST)
+ {
+ putreg32(bit, regaddr);
+ }
+ else
+ {
+ regval = getreg32(regaddr);
+ regval &= ~bit;
+ putreg32(regval, regaddr);
+ }
+}
+
+void up_enable_irq(int irq)
+{
+ uintptr_t regaddr;
+ uint32_t regval;
+ uint32_t bit;
+
+ if (ht32_irqinfo(irq, ®addr, &bit, NVIC_ENA_OFFSET) < 0)
+ {
+ return;
+ }
+
+ if (irq >= HT32_IRQ_FIRST)
+ {
+ putreg32(bit, regaddr);
+ }
+ else
+ {
+ regval = getreg32(regaddr);
+ regval |= bit;
+ putreg32(regval, regaddr);
+ }
+}
+
+void arm_ack_irq(int irq)
+{
+ UNUSED(irq);
+}
+
+#ifdef CONFIG_ARCH_IRQPRIO
+int up_prioritize_irq(int irq, int priority)
+{
+ uint32_t regaddr;
+ uint32_t regval;
+ int shift;
+
+ DEBUGASSERT(irq >= HT32_IRQ_MEMFAULT && irq < NR_IRQS &&
+ (unsigned)priority <= NVIC_SYSH_PRIORITY_MIN);
+
+ if (irq < HT32_IRQ_FIRST)
+ {
+ regaddr = NVIC_SYSH_PRIORITY(irq);
+ irq -= 4;
+ }
+ else
+ {
+ irq -= HT32_IRQ_FIRST;
+ regaddr = NVIC_IRQ_PRIORITY(irq);
+ }
+
+ regval = getreg32(regaddr);
+ shift = ((irq & 3) << 3);
+ regval &= ~(0xff << shift);
+ regval |= ((uint32_t)priority << shift);
+ putreg32(regval, regaddr);
+
+ return 0;
+}
+#endif
diff --git a/arch/arm/src/ht32f491x3/ht32f491x3_lowputc.c b/arch/arm/src/ht32f491x3/ht32f491x3_lowputc.c
new file mode 100644
index 00000000000..c22c40ae9d2
--- /dev/null
+++ b/arch/arm/src/ht32f491x3/ht32f491x3_lowputc.c
@@ -0,0 +1,287 @@
+/****************************************************************************
+ * arch/arm/src/ht32f491x3/ht32f491x3_lowputc.c
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <nuttx/compiler.h>
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <arch/board/board.h>
+
+#include "arm_internal.h"
+#include "chip.h"
+
+#include "ht32f491x3_config.h"
+#include "ht32f491x3_gpio.h"
+#include "ht32f491x3_lowputc.h"
+#include "ht32f491x3_serial.h"
+
+#include "hardware/ht32f491x3_crm.h"
+#include "hardware/ht32f491x3_gpio.h"
+#include "hardware/ht32f491x3_uart.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifdef HAVE_CONSOLE
+# if defined(CONFIG_USART1_SERIAL_CONSOLE) && \
+ defined(CONFIG_HT32F491X3_USART1_SERIALDRIVER)
+# define HT32_CONSOLE_BASE HT32_USART1_BASE
+# define HT32_CONSOLE_APBREG HT32_CRM_APB2EN
+# define HT32_CONSOLE_APBEN HT32_CRM_APB2EN_USART1EN
+# define HT32_CONSOLE_CLOCK HT32_PCLK2_FREQUENCY
+# define HT32_CONSOLE_BAUD CONFIG_USART1_BAUD
+# define HT32_CONSOLE_BITS CONFIG_USART1_BITS
+# define HT32_CONSOLE_PARITY CONFIG_USART1_PARITY
+# define HT32_CONSOLE_2STOP CONFIG_USART1_2STOP
+# elif defined(CONFIG_USART2_SERIAL_CONSOLE) && \
+ defined(CONFIG_HT32F491X3_USART2_SERIALDRIVER)
+# define HT32_CONSOLE_BASE HT32_USART2_BASE
+# define HT32_CONSOLE_APBREG HT32_CRM_APB1EN
+# define HT32_CONSOLE_APBEN HT32_CRM_APB1EN_USART2EN
+# define HT32_CONSOLE_CLOCK HT32_PCLK1_FREQUENCY
+# define HT32_CONSOLE_BAUD CONFIG_USART2_BAUD
+# define HT32_CONSOLE_BITS CONFIG_USART2_BITS
+# define HT32_CONSOLE_PARITY CONFIG_USART2_PARITY
+# define HT32_CONSOLE_2STOP CONFIG_USART2_2STOP
+# elif defined(CONFIG_USART3_SERIAL_CONSOLE) && \
+ defined(CONFIG_HT32F491X3_USART3_SERIALDRIVER)
+# define HT32_CONSOLE_BASE HT32_USART3_BASE
+# define HT32_CONSOLE_APBREG HT32_CRM_APB1EN
+# define HT32_CONSOLE_APBEN HT32_CRM_APB1EN_USART3EN
+# define HT32_CONSOLE_CLOCK HT32_PCLK1_FREQUENCY
+# define HT32_CONSOLE_BAUD CONFIG_USART3_BAUD
+# define HT32_CONSOLE_BITS CONFIG_USART3_BITS
+# define HT32_CONSOLE_PARITY CONFIG_USART3_PARITY
+# define HT32_CONSOLE_2STOP CONFIG_USART3_2STOP
+# endif
+
+# define HT32_USART_CTRL1_CLRBITS \
+ (HT32_USART_CTRL1_SBF | HT32_USART_CTRL1_RM | HT32_USART_CTRL1_REN | \
+ HT32_USART_CTRL1_TEN | HT32_USART_CTRL1_IDLEIEN | \
+ HT32_USART_CTRL1_RDBFIEN | HT32_USART_CTRL1_TDCIEN | \
+ HT32_USART_CTRL1_TDBEIEN | HT32_USART_CTRL1_PERRIEN | \
+ HT32_USART_CTRL1_PSEL | HT32_USART_CTRL1_PEN | \
+ HT32_USART_CTRL1_WUM | HT32_USART_CTRL1_DBN0 | \
+ HT32_USART_CTRL1_UEN | HT32_USART_CTRL1_DBN1)
+
+# define HT32_USART_CTRL2_CLRBITS \
+ (HT32_USART_CTRL2_BFIEN | HT32_USART_CTRL2_LBCP | \
+ HT32_USART_CTRL2_CLKPHA | HT32_USART_CTRL2_CLKPOL | \
+ HT32_USART_CTRL2_CLKEN | HT32_USART_CTRL2_STOPBN_MASK)
+
+# define HT32_USART_CTRL3_CLRBITS \
+ (HT32_USART_CTRL3_ERRIEN | HT32_USART_CTRL3_DMAREN | \
+ HT32_USART_CTRL3_DMATEN | HT32_USART_CTRL3_RTSEN | \
+ HT32_USART_CTRL3_CTSEN | HT32_USART_CTRL3_CTSCFIEN | \
+ HT32_USART_CTRL3_RS485EN | HT32_USART_CTRL3_DEP)
+#endif
+
+static uint32_t ht32f491x3_bauddiv(uint32_t clock, uint32_t baud)
+{
+ uint32_t div;
+
+ div = (clock * 10u) / baud;
+ return ((div % 10u) < 5u) ? (div / 10u) : (div / 10u + 1u);
+}
+
+void ht32f491x3_usart_config(uintptr_t uartbase)
+{
+ if (uartbase == HT32_USART1_BASE)
+ {
+ modifyreg32(HT32_CRM_PICLKS,
+ HT32_CRM_PICLKS_USART1SEL_MASK,
+ HT32_CRM_PICLKS_USARTSEL_PCLK <<
+ HT32_CRM_PICLKS_USART1SEL_SHIFT);
+ modifyreg32(HT32_CRM_APB2RST, 0, HT32_CRM_APB2RST_USART1RST);
+ modifyreg32(HT32_CRM_APB2RST, HT32_CRM_APB2RST_USART1RST, 0);
+ }
+ else if (uartbase == HT32_USART2_BASE)
+ {
+ modifyreg32(HT32_CRM_PICLKS,
+ HT32_CRM_PICLKS_USART2SEL_MASK,
+ HT32_CRM_PICLKS_USARTSEL_PCLK <<
+ HT32_CRM_PICLKS_USART2SEL_SHIFT);
+ modifyreg32(HT32_CRM_APB1RST, 0, HT32_CRM_APB1RST_USART2RST);
+ modifyreg32(HT32_CRM_APB1RST, HT32_CRM_APB1RST_USART2RST, 0);
+ }
+ else if (uartbase == HT32_USART3_BASE)
+ {
+ modifyreg32(HT32_CRM_PICLKS,
+ HT32_CRM_PICLKS_USART3SEL_MASK,
+ HT32_CRM_PICLKS_USARTSEL_PCLK <<
+ HT32_CRM_PICLKS_USART3SEL_SHIFT);
+ modifyreg32(HT32_CRM_APB1RST, 0, HT32_CRM_APB1RST_USART3RST);
+ modifyreg32(HT32_CRM_APB1RST, HT32_CRM_APB1RST_USART3RST, 0);
+ }
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/* Configure the board-specific pinmux for the selected USART. The physical
+ * mapping comes from BOARD_USARTx_* macros in <arch/board/board.h>.
+ */
+
+void ht32f491x3_usart_pins(uintptr_t uartbase)
+{
+#ifdef BOARD_USART1_GPIO_CLKEN
+ if (uartbase == HT32_USART1_BASE)
+ {
+ modifyreg32(HT32_CRM_AHBEN1, 0, BOARD_USART1_GPIO_CLKEN);
+ ht32f491x3_gpioconfig(BOARD_USART1_TX_GPIO_BASE,
+ BOARD_USART1_TX_PIN, HT32_GPIO_MODE_ALTFN,
+ false, HT32_GPIO_DRIVE_MEDIUM,
+ HT32_GPIO_PULL_NONE,
+ BOARD_USART1_TX_AF);
+ ht32f491x3_gpioconfig(BOARD_USART1_RX_GPIO_BASE,
+ BOARD_USART1_RX_PIN, HT32_GPIO_MODE_ALTFN,
+ false, HT32_GPIO_DRIVE_MEDIUM,
+ HT32_GPIO_PULL_UP,
+ BOARD_USART1_RX_AF);
+ return;
+ }
+#endif
+
+#ifdef BOARD_USART2_GPIO_CLKEN
+ if (uartbase == HT32_USART2_BASE)
+ {
+ modifyreg32(HT32_CRM_AHBEN1, 0, BOARD_USART2_GPIO_CLKEN);
+ ht32f491x3_gpioconfig(BOARD_USART2_TX_GPIO_BASE,
+ BOARD_USART2_TX_PIN, HT32_GPIO_MODE_ALTFN,
+ false, HT32_GPIO_DRIVE_MEDIUM,
+ HT32_GPIO_PULL_NONE,
+ BOARD_USART2_TX_AF);
+ ht32f491x3_gpioconfig(BOARD_USART2_RX_GPIO_BASE,
+ BOARD_USART2_RX_PIN, HT32_GPIO_MODE_ALTFN,
+ false, HT32_GPIO_DRIVE_MEDIUM,
+ HT32_GPIO_PULL_UP,
+ BOARD_USART2_RX_AF);
+ return;
+ }
+#endif
+
+#ifdef BOARD_USART3_GPIO_CLKEN
+ if (uartbase == HT32_USART3_BASE)
+ {
+ modifyreg32(HT32_CRM_AHBEN1, 0, BOARD_USART3_GPIO_CLKEN);
+ ht32f491x3_gpioconfig(BOARD_USART3_TX_GPIO_BASE,
+ BOARD_USART3_TX_PIN, HT32_GPIO_MODE_ALTFN,
+ false, HT32_GPIO_DRIVE_MEDIUM,
+ HT32_GPIO_PULL_NONE,
+ BOARD_USART3_TX_AF);
+ ht32f491x3_gpioconfig(BOARD_USART3_RX_GPIO_BASE,
+ BOARD_USART3_RX_PIN, HT32_GPIO_MODE_ALTFN,
+ false, HT32_GPIO_DRIVE_MEDIUM,
+ HT32_GPIO_PULL_UP,
+ BOARD_USART3_RX_AF);
+ }
+#endif
+}
+
+void arm_lowputc(char ch)
+{
+#ifdef HAVE_CONSOLE
+ while ((getreg32(HT32_CONSOLE_BASE + HT32_USART_STS_OFFSET) &
+ HT32_USART_STS_TDBE) == 0)
+ {
+ }
+
+ putreg32((uint32_t)ch & HT32_USART_DT_MASK,
+ HT32_CONSOLE_BASE + HT32_USART_DT_OFFSET);
+#endif
+}
+
+void ht32f491x3_lowsetup(void)
+{
+#if defined(HAVE_CONSOLE)
+ uint32_t regval;
+
+ modifyreg32(HT32_CONSOLE_APBREG, 0, HT32_CONSOLE_APBEN);
+ ht32f491x3_usart_config(HT32_CONSOLE_BASE);
+ ht32f491x3_usart_pins(HT32_CONSOLE_BASE);
+
+#ifndef CONFIG_SUPPRESS_UART_CONFIG
+ regval = getreg32(HT32_CONSOLE_BASE + HT32_USART_CTRL1_OFFSET);
+ regval &= ~HT32_USART_CTRL1_UEN;
+ putreg32(regval, HT32_CONSOLE_BASE + HT32_USART_CTRL1_OFFSET);
+
+ regval = getreg32(HT32_CONSOLE_BASE + HT32_USART_CTRL2_OFFSET);
+ regval &= ~HT32_USART_CTRL2_CLRBITS;
+ if (HT32_CONSOLE_2STOP != 0)
+ {
+ regval |= HT32_USART_CTRL2_STOPBN_20;
+ }
+ else
+ {
+ regval |= HT32_USART_CTRL2_STOPBN_10;
+ }
+
+ putreg32(regval, HT32_CONSOLE_BASE + HT32_USART_CTRL2_OFFSET);
+
+ regval = getreg32(HT32_CONSOLE_BASE + HT32_USART_CTRL1_OFFSET);
+ regval &= ~HT32_USART_CTRL1_CLRBITS;
+
+ if (HT32_CONSOLE_PARITY == 1)
+ {
+ regval |= HT32_USART_CTRL1_PEN;
+ }
+ else if (HT32_CONSOLE_PARITY == 2)
+ {
+ regval |= HT32_USART_CTRL1_PEN | HT32_USART_CTRL1_PSEL;
+ }
+
+ if (HT32_CONSOLE_BITS == 9 ||
+ (HT32_CONSOLE_BITS == 8 && HT32_CONSOLE_PARITY != 0))
+ {
+ regval |= HT32_USART_CTRL1_DBN0;
+ }
+ else if (HT32_CONSOLE_BITS == 7)
+ {
+ regval |= HT32_USART_CTRL1_DBN1;
+ }
+
+ putreg32(regval, HT32_CONSOLE_BASE + HT32_USART_CTRL1_OFFSET);
+
+ regval = getreg32(HT32_CONSOLE_BASE + HT32_USART_CTRL3_OFFSET);
+ regval &= ~HT32_USART_CTRL3_CLRBITS;
+ putreg32(regval, HT32_CONSOLE_BASE + HT32_USART_CTRL3_OFFSET);
+
+ putreg32(ht32f491x3_bauddiv(HT32_CONSOLE_CLOCK, HT32_CONSOLE_BAUD),
+ HT32_CONSOLE_BASE + HT32_USART_BAUDR_OFFSET);
+#endif
+
+ regval = getreg32(HT32_CONSOLE_BASE + HT32_USART_CTRL1_OFFSET);
+ regval |= HT32_USART_CTRL1_UEN |
+ HT32_USART_CTRL1_TEN |
+ HT32_USART_CTRL1_REN;
+ putreg32(regval, HT32_CONSOLE_BASE + HT32_USART_CTRL1_OFFSET);
+#endif
+}
diff --git a/arch/arm/src/ht32f491x3/ht32f491x3_lowputc.h b/arch/arm/src/ht32f491x3/ht32f491x3_lowputc.h
new file mode 100644
index 00000000000..c900b58dd41
--- /dev/null
+++ b/arch/arm/src/ht32f491x3/ht32f491x3_lowputc.h
@@ -0,0 +1,43 @@
+/****************************************************************************
+ * arch/arm/src/ht32f491x3/ht32f491x3_lowputc.h
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_HT32F491X3_HT32F491X3_LOWPUTC_H
+#define __ARCH_ARM_SRC_HT32F491X3_HT32F491X3_LOWPUTC_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+void ht32f491x3_lowsetup(void);
+void ht32f491x3_usart_config(uintptr_t uartbase);
+#endif
+
+#endif /* __ARCH_ARM_SRC_HT32F491X3_HT32F491X3_LOWPUTC_H */
diff --git a/arch/arm/src/ht32f491x3/ht32f491x3_serial.c b/arch/arm/src/ht32f491x3/ht32f491x3_serial.c
new file mode 100644
index 00000000000..06ff5013159
--- /dev/null
+++ b/arch/arm/src/ht32f491x3/ht32f491x3_serial.c
@@ -0,0 +1,658 @@
+/****************************************************************************
+ * arch/arm/src/ht32f491x3/ht32f491x3_serial.c
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+
+#include <stdbool.h>
+#include <errno.h>
+#include <stdint.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/irq.h>
+#include <nuttx/serial/serial.h>
+#include <nuttx/spinlock.h>
+
+#include "chip.h"
+#include "arm_internal.h"
+
+#include "ht32f491x3_config.h"
+#include "ht32f491x3_lowputc.h"
+#include "ht32f491x3_serial.h"
+
+#include "hardware/ht32f491x3_crm.h"
+#include "hardware/ht32f491x3_uart.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#if defined(CONFIG_USART1_SERIAL_CONSOLE) && \
+ defined(CONFIG_HT32F491X3_USART1_SERIALDRIVER)
+# define CONSOLE_USART 1
+#elif defined(CONFIG_USART2_SERIAL_CONSOLE) && \
+ defined(CONFIG_HT32F491X3_USART2_SERIALDRIVER)
+# define CONSOLE_USART 2
+#elif defined(CONFIG_USART3_SERIAL_CONSOLE) && \
+ defined(CONFIG_HT32F491X3_USART3_SERIALDRIVER)
+# define CONSOLE_USART 3
+#else
+# define CONSOLE_USART 0
+#endif
+
+#define HT32_USART_CTRL1_USED_INTS \
+ (HT32_USART_CTRL1_IDLEIEN | HT32_USART_CTRL1_RDBFIEN | \
+ HT32_USART_CTRL1_TDCIEN | HT32_USART_CTRL1_TDBEIEN | \
+ HT32_USART_CTRL1_PERRIEN)
+
+#define HT32_USART_CTRL3_USED_INTS HT32_USART_CTRL3_ERRIEN
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct up_dev_s
+{
+ uintptr_t uartbase;
+ uintptr_t apbreg;
+ uint32_t apbmask;
+ uint32_t apbclock;
+ uint32_t baud;
+ uint32_t ie;
+ int irq;
+ uint8_t parity;
+ uint8_t bits;
+ bool stopbits2;
+ spinlock_t lock;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int up_setup(FAR struct uart_dev_s *dev);
+static void up_shutdown(FAR struct uart_dev_s *dev);
+static int up_attach(FAR struct uart_dev_s *dev);
+static void up_detach(FAR struct uart_dev_s *dev);
+static int ht32_interrupt(int irq, FAR void *context, FAR void *arg);
+static int up_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
+static int up_receive(FAR struct uart_dev_s *dev,
+ FAR unsigned int *status);
+static void up_rxint(FAR struct uart_dev_s *dev, bool enable);
+static bool up_rxavailable(FAR struct uart_dev_s *dev);
+static void up_send(FAR struct uart_dev_s *dev, int ch);
+static void up_txint(FAR struct uart_dev_s *dev, bool enable);
+static bool up_txready(FAR struct uart_dev_s *dev);
+static bool up_txempty(FAR struct uart_dev_s *dev);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct uart_ops_s g_uart_ops =
+{
+ .setup = up_setup,
+ .shutdown = up_shutdown,
+ .attach = up_attach,
+ .detach = up_detach,
+ .ioctl = up_ioctl,
+ .receive = up_receive,
+ .rxint = up_rxint,
+ .rxavailable = up_rxavailable,
+ .send = up_send,
+ .txint = up_txint,
+ .txready = up_txready,
+ .txempty = up_txempty,
+};
+
+#if defined(USE_SERIALDRIVER) && defined(HAVE_UART)
+
+#ifdef CONFIG_HT32F491X3_USART1_SERIALDRIVER
+static char g_usart1rxbuffer[CONFIG_USART1_RXBUFSIZE];
+static char g_usart1txbuffer[CONFIG_USART1_TXBUFSIZE];
+
+static struct up_dev_s g_usart1priv =
+{
+ .uartbase = HT32_USART1_BASE,
+ .apbreg = HT32_CRM_APB2EN,
+ .apbmask = HT32_CRM_APB2EN_USART1EN,
+ .apbclock = HT32_PCLK2_FREQUENCY,
+ .baud = CONFIG_USART1_BAUD,
+ .irq = HT32_IRQ_USART1,
+ .parity = CONFIG_USART1_PARITY,
+ .bits = CONFIG_USART1_BITS,
+ .stopbits2 = CONFIG_USART1_2STOP,
+ .lock = SP_UNLOCKED,
+};
+
+static uart_dev_t g_usart1port =
+{
+#if CONSOLE_USART == 1
+ .isconsole = true,
+#endif
+ .recv =
+ {
+ .size = CONFIG_USART1_RXBUFSIZE,
+ .buffer = g_usart1rxbuffer,
+ },
+ .xmit =
+ {
+ .size = CONFIG_USART1_TXBUFSIZE,
+ .buffer = g_usart1txbuffer,
+ },
+ .ops = &g_uart_ops,
+ .priv = &g_usart1priv,
+};
+#endif
+
+#ifdef CONFIG_HT32F491X3_USART2_SERIALDRIVER
+static char g_usart2rxbuffer[CONFIG_USART2_RXBUFSIZE];
+static char g_usart2txbuffer[CONFIG_USART2_TXBUFSIZE];
+
+static struct up_dev_s g_usart2priv =
+{
+ .uartbase = HT32_USART2_BASE,
+ .apbreg = HT32_CRM_APB1EN,
+ .apbmask = HT32_CRM_APB1EN_USART2EN,
+ .apbclock = HT32_PCLK1_FREQUENCY,
+ .baud = CONFIG_USART2_BAUD,
+ .irq = HT32_IRQ_USART2,
+ .parity = CONFIG_USART2_PARITY,
+ .bits = CONFIG_USART2_BITS,
+ .stopbits2 = CONFIG_USART2_2STOP,
+ .lock = SP_UNLOCKED,
+};
+
+static uart_dev_t g_usart2port =
+{
+#if CONSOLE_USART == 2
+ .isconsole = true,
+#endif
+ .recv =
+ {
+ .size = CONFIG_USART2_RXBUFSIZE,
+ .buffer = g_usart2rxbuffer,
+ },
+ .xmit =
+ {
+ .size = CONFIG_USART2_TXBUFSIZE,
+ .buffer = g_usart2txbuffer,
+ },
+ .ops = &g_uart_ops,
+ .priv = &g_usart2priv,
+};
+#endif
+
+#ifdef CONFIG_HT32F491X3_USART3_SERIALDRIVER
+static char g_usart3rxbuffer[CONFIG_USART3_RXBUFSIZE];
+static char g_usart3txbuffer[CONFIG_USART3_TXBUFSIZE];
+
+static struct up_dev_s g_usart3priv =
+{
+ .uartbase = HT32_USART3_BASE,
+ .apbreg = HT32_CRM_APB1EN,
+ .apbmask = HT32_CRM_APB1EN_USART3EN,
+ .apbclock = HT32_PCLK1_FREQUENCY,
+ .baud = CONFIG_USART3_BAUD,
+ .irq = HT32_IRQ_USART3,
+ .parity = CONFIG_USART3_PARITY,
+ .bits = CONFIG_USART3_BITS,
+ .stopbits2 = CONFIG_USART3_2STOP,
+ .lock = SP_UNLOCKED,
+};
+
+static uart_dev_t g_usart3port =
+{
+#if CONSOLE_USART == 3
+ .isconsole = true,
+#endif
+ .recv =
+ {
+ .size = CONFIG_USART3_RXBUFSIZE,
+ .buffer = g_usart3rxbuffer,
+ },
+ .xmit =
+ {
+ .size = CONFIG_USART3_TXBUFSIZE,
+ .buffer = g_usart3txbuffer,
+ },
+ .ops = &g_uart_ops,
+ .priv = &g_usart3priv,
+};
+#endif
+
+static uart_dev_t *const g_uart_devs[] =
+{
+#ifdef CONFIG_HT32F491X3_USART1_SERIALDRIVER
+ &g_usart1port,
+#else
+ NULL,
+#endif
+#ifdef CONFIG_HT32F491X3_USART2_SERIALDRIVER
+ &g_usart2port,
+#else
+ NULL,
+#endif
+#ifdef CONFIG_HT32F491X3_USART3_SERIALDRIVER
+ &g_usart3port,
+#else
+ NULL,
+#endif
+};
+
+#define HT32_NUART_PORTS (sizeof(g_uart_devs) / sizeof(g_uart_devs[0]))
+
+#if CONSOLE_USART == 1
+# define CONSOLE_DEVPTR (&g_usart1port)
+#elif CONSOLE_USART == 2
+# define CONSOLE_DEVPTR (&g_usart2port)
+#elif CONSOLE_USART == 3
+# define CONSOLE_DEVPTR (&g_usart3port)
+#else
+# define CONSOLE_DEVPTR ((FAR uart_dev_t *)0)
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static inline uint32_t up_serialin(FAR struct up_dev_s *priv, int offset)
+{
+ return getreg32(priv->uartbase + offset);
+}
+
+static inline void up_serialout(FAR struct up_dev_s *priv, int offset,
+ uint32_t value)
+{
+ putreg32(value, priv->uartbase + offset);
+}
+
+static uint32_t ht32f491x3_bauddiv(uint32_t clock, uint32_t baud)
+{
+ uint32_t div;
+
+ div = (clock * 10u) / baud;
+ return ((div % 10u) < 5u) ? (div / 10u) : (div / 10u + 1u);
+}
+
+static void up_setusartint_nolock(FAR struct up_dev_s *priv, uint32_t ie)
+{
+ uint32_t regval;
+
+ priv->ie = ie;
+
+ regval = up_serialin(priv, HT32_USART_CTRL1_OFFSET);
+ regval &= ~HT32_USART_CTRL1_USED_INTS;
+ regval |= ie & HT32_USART_CTRL1_USED_INTS;
+ up_serialout(priv, HT32_USART_CTRL1_OFFSET, regval);
+
+ regval = up_serialin(priv, HT32_USART_CTRL3_OFFSET);
+ regval &= ~HT32_USART_CTRL3_USED_INTS;
+ regval |= ie & HT32_USART_CTRL3_USED_INTS;
+ up_serialout(priv, HT32_USART_CTRL3_OFFSET, regval);
+}
+
+static void up_restoreusartint(FAR struct up_dev_s *priv, uint32_t ie)
+{
+ irqstate_t flags;
+
+ flags = spin_lock_irqsave(&priv->lock);
+ up_setusartint_nolock(priv, ie);
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static void up_disableusartint(FAR struct up_dev_s *priv, FAR uint32_t *ie)
+{
+ irqstate_t flags;
+
+ flags = spin_lock_irqsave(&priv->lock);
+
+ if (ie != NULL)
+ {
+ uint32_t regval;
+
+ regval = up_serialin(priv, HT32_USART_CTRL1_OFFSET);
+ *ie = regval & HT32_USART_CTRL1_USED_INTS;
+ regval = up_serialin(priv, HT32_USART_CTRL3_OFFSET);
+ *ie |= regval & HT32_USART_CTRL3_USED_INTS;
+ }
+
+ up_setusartint_nolock(priv, 0);
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+#ifndef CONFIG_SUPPRESS_UART_CONFIG
+static void up_set_format(FAR struct uart_dev_s *dev)
+{
+ FAR struct up_dev_s *priv = (FAR struct up_dev_s *)dev->priv;
+ uint32_t regval;
+
+ regval = up_serialin(priv, HT32_USART_CTRL1_OFFSET);
+ regval &= ~(HT32_USART_CTRL1_PEN | HT32_USART_CTRL1_PSEL |
+ HT32_USART_CTRL1_DBN0 | HT32_USART_CTRL1_DBN1);
+
+ if (priv->parity == 1)
+ {
+ regval |= HT32_USART_CTRL1_PEN;
+ }
+ else if (priv->parity == 2)
+ {
+ regval |= HT32_USART_CTRL1_PEN | HT32_USART_CTRL1_PSEL;
+ }
+
+ if (priv->bits == 9 || (priv->bits == 8 && priv->parity != 0))
+ {
+ regval |= HT32_USART_CTRL1_DBN0;
+ }
+ else if (priv->bits == 7)
+ {
+ regval |= HT32_USART_CTRL1_DBN1;
+ }
+
+ up_serialout(priv, HT32_USART_CTRL1_OFFSET, regval);
+
+ regval = up_serialin(priv, HT32_USART_CTRL2_OFFSET);
+ regval &= ~HT32_USART_CTRL2_STOPBN_MASK;
+ regval |= priv->stopbits2 ? HT32_USART_CTRL2_STOPBN_20
+ : HT32_USART_CTRL2_STOPBN_10;
+ up_serialout(priv, HT32_USART_CTRL2_OFFSET, regval);
+
+ regval = up_serialin(priv, HT32_USART_CTRL3_OFFSET);
+ regval &= ~(HT32_USART_CTRL3_RTSEN | HT32_USART_CTRL3_CTSEN |
+ HT32_USART_CTRL3_RS485EN | HT32_USART_CTRL3_DEP);
+ up_serialout(priv, HT32_USART_CTRL3_OFFSET, regval);
+
+ up_serialout(priv, HT32_USART_BAUDR_OFFSET,
+ ht32f491x3_bauddiv(priv->apbclock, priv->baud));
+}
+#endif
+
+static int up_setup(FAR struct uart_dev_s *dev)
+{
+ FAR struct up_dev_s *priv = (FAR struct up_dev_s *)dev->priv;
+ uint32_t regval;
+
+ modifyreg32(priv->apbreg, 0, priv->apbmask);
+ ht32f491x3_usart_config(priv->uartbase);
+ ht32f491x3_usart_pins(priv->uartbase);
+
+ regval = up_serialin(priv, HT32_USART_CTRL1_OFFSET);
+ regval &= ~HT32_USART_CTRL1_UEN;
+ up_serialout(priv, HT32_USART_CTRL1_OFFSET, regval);
+
+#ifndef CONFIG_SUPPRESS_UART_CONFIG
+ up_set_format(dev);
+#endif
+
+ regval = up_serialin(priv, HT32_USART_CTRL1_OFFSET);
+ regval |= HT32_USART_CTRL1_UEN |
+ HT32_USART_CTRL1_TEN |
+ HT32_USART_CTRL1_REN;
+ up_serialout(priv, HT32_USART_CTRL1_OFFSET, regval);
+
+ return 0;
+}
+
+static void up_shutdown(FAR struct uart_dev_s *dev)
+{
+ FAR struct up_dev_s *priv = (FAR struct up_dev_s *)dev->priv;
+ uint32_t regval;
+
+ up_disableusartint(priv, NULL);
+
+ regval = up_serialin(priv, HT32_USART_CTRL1_OFFSET);
+ regval &= ~(HT32_USART_CTRL1_UEN |
+ HT32_USART_CTRL1_TEN |
+ HT32_USART_CTRL1_REN);
+ up_serialout(priv, HT32_USART_CTRL1_OFFSET, regval);
+}
+
+static int up_attach(FAR struct uart_dev_s *dev)
+{
+ FAR struct up_dev_s *priv = (FAR struct up_dev_s *)dev->priv;
+ int ret;
+
+ ret = irq_attach(priv->irq, ht32_interrupt, dev);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ up_enable_irq(priv->irq);
+ return 0;
+}
+
+static void up_detach(FAR struct uart_dev_s *dev)
+{
+ FAR struct up_dev_s *priv = (FAR struct up_dev_s *)dev->priv;
+
+ up_disable_irq(priv->irq);
+ irq_detach(priv->irq);
+}
+
+static int ht32_interrupt(int irq, FAR void *context, FAR void *arg)
+{
+ FAR struct uart_dev_s *dev = (FAR struct uart_dev_s *)arg;
+ FAR struct up_dev_s *priv = (FAR struct up_dev_s *)dev->priv;
+ uint32_t status;
+
+ UNUSED(irq);
+ UNUSED(context);
+
+ status = up_serialin(priv, HT32_USART_STS_OFFSET);
+
+ if ((status & HT32_USART_STS_RDBF) != 0)
+ {
+ uart_recvchars(dev);
+ }
+
+ if ((status & HT32_USART_STS_TDBE) != 0 &&
+ (priv->ie & HT32_USART_CTRL1_TDBEIEN) != 0)
+ {
+ uart_xmitchars(dev);
+ }
+
+ return 0;
+}
+
+static int up_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
+{
+ UNUSED(filep);
+ UNUSED(cmd);
+ UNUSED(arg);
+ return -ENOTTY;
+}
+
+static int up_receive(FAR struct uart_dev_s *dev, FAR unsigned int *status)
+{
+ FAR struct up_dev_s *priv = (FAR struct up_dev_s *)dev->priv;
+ uint32_t regval;
+
+ regval = up_serialin(priv, HT32_USART_STS_OFFSET);
+ if (status != NULL)
+ {
+ *status = regval;
+ }
+
+ regval = up_serialin(priv, HT32_USART_RDR_OFFSET);
+ return (int)(regval & (HT32_USART_DT_MASK >> HT32_USART_DT_SHIFT));
+}
+
+static void up_rxint(FAR struct uart_dev_s *dev, bool enable)
+{
+ FAR struct up_dev_s *priv = (FAR struct up_dev_s *)dev->priv;
+ irqstate_t flags;
+ uint32_t ie;
+
+ flags = spin_lock_irqsave(&priv->lock);
+ ie = priv->ie;
+
+ if (enable)
+ {
+ ie |= HT32_USART_CTRL1_RDBFIEN | HT32_USART_CTRL3_ERRIEN;
+ }
+ else
+ {
+ ie &= ~(HT32_USART_CTRL1_RDBFIEN | HT32_USART_CTRL3_ERRIEN);
+ }
+
+ up_setusartint_nolock(priv, ie);
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static bool up_rxavailable(FAR struct uart_dev_s *dev)
+{
+ FAR struct up_dev_s *priv = (FAR struct up_dev_s *)dev->priv;
+
+ return (up_serialin(priv, HT32_USART_STS_OFFSET) &
+ HT32_USART_STS_RDBF) != 0;
+}
+
+static void up_send(FAR struct uart_dev_s *dev, int ch)
+{
+ FAR struct up_dev_s *priv = (FAR struct up_dev_s *)dev->priv;
+
+ up_serialout(priv, HT32_USART_TDR_OFFSET,
+ (uint32_t)ch & (HT32_USART_DT_MASK >> HT32_USART_DT_SHIFT));
+}
+
+static void up_txint(FAR struct uart_dev_s *dev, bool enable)
+{
+ FAR struct up_dev_s *priv = (FAR struct up_dev_s *)dev->priv;
+ irqstate_t flags;
+ uint32_t ie;
+
+ flags = spin_lock_irqsave(&priv->lock);
+ ie = priv->ie;
+
+ if (enable)
+ {
+ ie |= HT32_USART_CTRL1_TDBEIEN;
+ }
+ else
+ {
+ ie &= ~HT32_USART_CTRL1_TDBEIEN;
+ }
+
+ up_setusartint_nolock(priv, ie);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ if (enable)
+ {
+ uart_xmitchars(dev);
+ }
+}
+
+static bool up_txready(FAR struct uart_dev_s *dev)
+{
+ FAR struct up_dev_s *priv = (FAR struct up_dev_s *)dev->priv;
+
+ return (up_serialin(priv, HT32_USART_STS_OFFSET) &
+ HT32_USART_STS_TDBE) != 0;
+}
+
+static bool up_txempty(FAR struct uart_dev_s *dev)
+{
+ FAR struct up_dev_s *priv = (FAR struct up_dev_s *)dev->priv;
+
+ return (up_serialin(priv, HT32_USART_STS_OFFSET) &
+ HT32_USART_STS_TDC) != 0;
+}
+
+void arm_earlyserialinit(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < HT32_NUART_PORTS; i++)
+ {
+ if (g_uart_devs[i] != NULL)
+ {
+ up_disableusartint((FAR struct up_dev_s *)g_uart_devs[i]->priv,
+ NULL);
+ }
+ }
+
+#if CONSOLE_USART > 0
+ up_setup(CONSOLE_DEVPTR);
+#endif
+}
+
+void arm_serialinit(void)
+{
+ char devname[] = "/dev/ttySx";
+ unsigned int i;
+ unsigned int minor = 0;
+
+#if CONSOLE_USART > 0
+ uart_register("/dev/console", CONSOLE_DEVPTR);
+ uart_register("/dev/ttyS0", CONSOLE_DEVPTR);
+ minor = 1;
+#endif
+
+ for (i = 0; i < HT32_NUART_PORTS; i++)
+ {
+ if (g_uart_devs[i] == NULL || g_uart_devs[i]->isconsole)
+ {
+ continue;
+ }
+
+ devname[9] = '0' + minor++;
+ uart_register(devname, g_uart_devs[i]);
+ }
+}
+
+#else
+
+void arm_earlyserialinit(void)
+{
+}
+
+void arm_serialinit(void)
+{
+}
+
+#endif /* USE_SERIALDRIVER && HAVE_UART */
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+void up_putc(int ch)
+{
+#ifdef HAVE_CONSOLE
+# if defined(USE_SERIALDRIVER) && defined(HAVE_UART) && CONSOLE_USART > 0
+ FAR struct up_dev_s *priv = (FAR struct up_dev_s *)CONSOLE_DEVPTR->priv;
+ uint32_t ie;
+
+ up_disableusartint(priv, &ie);
+ arm_lowputc(ch);
+ up_restoreusartint(priv, ie);
+# else
+ arm_lowputc(ch);
+# endif
+#endif
+}
diff --git a/arch/arm/src/ht32f491x3/ht32f491x3_serial.h b/arch/arm/src/ht32f491x3/ht32f491x3_serial.h
new file mode 100644
index 00000000000..0f242735249
--- /dev/null
+++ b/arch/arm/src/ht32f491x3/ht32f491x3_serial.h
@@ -0,0 +1,46 @@
+/****************************************************************************
+ * arch/arm/src/ht32f491x3/ht32f491x3_serial.h
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_HT32F491X3_HT32F491X3_SERIAL_H
+#define __ARCH_ARM_SRC_HT32F491X3_HT32F491X3_SERIAL_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+void arm_earlyserialinit(void);
+void arm_serialinit(void);
+void ht32f491x3_usart_pins(uintptr_t uartbase);
+
+#endif
+
+#endif /* __ARCH_ARM_SRC_HT32F491X3_HT32F491X3_SERIAL_H */
diff --git a/arch/arm/src/ht32f491x3/ht32f491x3_start.c b/arch/arm/src/ht32f491x3/ht32f491x3_start.c
new file mode 100644
index 00000000000..c688976e243
--- /dev/null
+++ b/arch/arm/src/ht32f491x3/ht32f491x3_start.c
@@ -0,0 +1,114 @@
+/****************************************************************************
+ * arch/arm/src/ht32f491x3/ht32f491x3_start.c
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+
+#include <nuttx/init.h>
+#include <arch/irq.h>
+
+#include "arm_internal.h"
+
+#include "ht32f491x3_lowputc.h"
+#include "ht32f491x3_serial.h"
+#include "ht32f491x3_start.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifdef CONFIG_DEBUG_FEATURES
+# define showprogress(c) arm_lowputc(c)
+#else
+# define showprogress(c)
+#endif
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+const uintptr_t g_idle_topstack = (uintptr_t)_END_BSS +
+ CONFIG_IDLETHREAD_STACKSIZE;
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+void weak_function ht32f491x3_clockconfig(void)
+{
+}
+
+void __start(void) __attribute__((section(".entry")));
+void __start(void)
+{
+ const uint32_t *src;
+ uint32_t *dest;
+
+ up_irq_disable();
+
+ /* Let the board tune CRM before the early console computes its divisors.
+ */
+
+ ht32f491x3_clockconfig();
+ ht32f491x3_lowsetup();
+ showprogress('A');
+
+ for (dest = (uint32_t *)_START_BSS; dest < (uint32_t *)_END_BSS; )
+ {
+ *dest++ = 0;
+ }
+
+ showprogress('B');
+
+ src = (const uint32_t *)_DATA_INIT;
+ dest = (uint32_t *)_START_DATA;
+
+ while (dest < (uint32_t *)_END_DATA)
+ {
+ *dest++ = *src++;
+ }
+
+ showprogress('C');
+
+ arm_fpuconfig();
+ showprogress('D');
+
+#ifdef USE_EARLYSERIALINIT
+ arm_earlyserialinit();
+#endif
+ showprogress('E');
+
+ ht32f491x3_boardinitialize();
+ showprogress('F');
+
+ showprogress('\r');
+ showprogress('\n');
+
+ nx_start();
+
+ for (; ; );
+}
diff --git a/arch/arm/src/ht32f491x3/ht32f491x3_start.h b/arch/arm/src/ht32f491x3/ht32f491x3_start.h
new file mode 100644
index 00000000000..68b12352454
--- /dev/null
+++ b/arch/arm/src/ht32f491x3/ht32f491x3_start.h
@@ -0,0 +1,39 @@
+/****************************************************************************
+ * arch/arm/src/ht32f491x3/ht32f491x3_start.h
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_HT32F491X3_HT32F491X3_START_H
+#define __ARCH_ARM_SRC_HT32F491X3_HT32F491X3_START_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+void ht32f491x3_clockconfig(void);
+void ht32f491x3_boardinitialize(void);
+
+#endif /* __ARCH_ARM_SRC_HT32F491X3_HT32F491X3_START_H */
diff --git a/arch/arm/src/ht32f491x3/ht32f491x3_timerisr.c b/arch/arm/src/ht32f491x3/ht32f491x3_timerisr.c
new file mode 100644
index 00000000000..17b05d2eedf
--- /dev/null
+++ b/arch/arm/src/ht32f491x3/ht32f491x3_timerisr.c
@@ -0,0 +1,95 @@
+/****************************************************************************
+ * arch/arm/src/ht32f491x3/ht32f491x3_timerisr.c
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <time.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/timers/arch_timer.h>
+
+#include "nvic.h"
+#include "clock/clock.h"
+#include "arm_internal.h"
+#include "systick.h"
+
+#include "chip.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define HT32_SYSTICK_RELOAD ((HT32_HCLK_FREQUENCY / CLK_TCK) - 1)
+
+#if HT32_SYSTICK_RELOAD > 0x00ffffff
+# error HT32_SYSTICK_RELOAD exceeds the SysTick reload field
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+#if !defined(CONFIG_ARMV7M_SYSTICK) && !defined(CONFIG_TIMER_ARCH)
+static int ht32f491x3_timerisr(int irq, FAR void *context, FAR void *arg)
+{
+ UNUSED(irq);
+ UNUSED(context);
+ UNUSED(arg);
+
+ nxsched_process_timer();
+ return 0;
+}
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+void up_timer_initialize(void)
+{
+ uint32_t regval;
+
+ regval = getreg32(NVIC_SYSH12_15_PRIORITY);
+ regval &= ~NVIC_SYSH_PRIORITY_PR15_MASK;
+ regval |= (NVIC_SYSH_PRIORITY_DEFAULT << NVIC_SYSH_PRIORITY_PR15_SHIFT);
+ putreg32(regval, NVIC_SYSH12_15_PRIORITY);
+
+#if defined(CONFIG_ARMV7M_SYSTICK) && defined(CONFIG_TIMER_ARCH)
+ up_timer_set_lowerhalf(systick_initialize(true, HT32_HCLK_FREQUENCY, -1));
+#else
+ putreg32(HT32_SYSTICK_RELOAD, NVIC_SYSTICK_RELOAD);
+
+ irq_attach(HT32_IRQ_SYSTICK, ht32f491x3_timerisr, NULL);
+
+ putreg32(NVIC_SYSTICK_CTRL_CLKSOURCE |
+ NVIC_SYSTICK_CTRL_TICKINT |
+ NVIC_SYSTICK_CTRL_ENABLE,
+ NVIC_SYSTICK_CTRL);
+
+ up_enable_irq(HT32_IRQ_SYSTICK);
+#endif
+}