diff --git a/demos/AT32/RT-AT-START-F405/.cproject b/demos/AT32/RT-AT-START-F405/.cproject
new file mode 100644
index 0000000000..eb00a4aec8
--- /dev/null
+++ b/demos/AT32/RT-AT-START-F405/.cproject
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/demos/AT32/RT-AT-START-F405/.project b/demos/AT32/RT-AT-START-F405/.project
new file mode 100644
index 0000000000..1f4a7141bb
--- /dev/null
+++ b/demos/AT32/RT-AT-START-F405/.project
@@ -0,0 +1,78 @@
+
+
+ RT-AT-START-F405
+
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.genmakebuilder
+ clean,full,incremental,
+
+
+ ?name?
+
+
+
+ org.eclipse.cdt.make.core.append_environment
+ true
+
+
+ org.eclipse.cdt.make.core.autoBuildTarget
+ all
+
+
+ org.eclipse.cdt.make.core.buildArguments
+
+
+
+ org.eclipse.cdt.make.core.buildCommand
+ mingw32-make
+
+
+ org.eclipse.cdt.make.core.cleanBuildTarget
+ clean
+
+
+ org.eclipse.cdt.make.core.contents
+ org.eclipse.cdt.make.core.activeConfigSettings
+
+
+ org.eclipse.cdt.make.core.enableAutoBuild
+ false
+
+
+ org.eclipse.cdt.make.core.enableCleanBuild
+ true
+
+
+ org.eclipse.cdt.make.core.enableFullBuild
+ true
+
+
+ org.eclipse.cdt.make.core.fullBuildTarget
+ all
+
+
+ org.eclipse.cdt.make.core.stopOnError
+ true
+
+
+ org.eclipse.cdt.make.core.useDefaultBuildCmd
+ false
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
+ full,incremental,
+
+
+
+
+
+ org.eclipse.cdt.core.cnature
+ org.eclipse.cdt.managedbuilder.core.managedBuildNature
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
+
+
diff --git a/demos/AT32/RT-AT-START-F405/Makefile b/demos/AT32/RT-AT-START-F405/Makefile
new file mode 100644
index 0000000000..4bec71adea
--- /dev/null
+++ b/demos/AT32/RT-AT-START-F405/Makefile
@@ -0,0 +1,197 @@
+##############################################################################
+# Build global options
+# NOTE: Can be overridden externally.
+#
+
+# Compiler options here.
+ifeq ($(USE_OPT),)
+ USE_OPT = -O2 -ggdb -fomit-frame-pointer -falign-functions=16
+endif
+
+# C specific options here (added to USE_OPT).
+ifeq ($(USE_COPT),)
+ USE_COPT =
+endif
+
+# C++ specific options here (added to USE_OPT).
+ifeq ($(USE_CPPOPT),)
+ USE_CPPOPT = -fno-rtti
+endif
+
+# Enable this if you want the linker to remove unused code and data.
+ifeq ($(USE_LINK_GC),)
+ USE_LINK_GC = yes
+endif
+
+# Linker extra options here.
+ifeq ($(USE_LDOPT),)
+ USE_LDOPT =
+endif
+
+# Enable this if you want link time optimizations (LTO).
+ifeq ($(USE_LTO),)
+ USE_LTO = yes
+endif
+
+# Enable this if you want to see the full log while compiling.
+ifeq ($(USE_VERBOSE_COMPILE),)
+ USE_VERBOSE_COMPILE = no
+endif
+
+# If enabled, this option makes the build process faster by not compiling
+# modules not used in the current configuration.
+ifeq ($(USE_SMART_BUILD),)
+ USE_SMART_BUILD = yes
+endif
+
+# Enable this if you want to use bitbang I2C.
+ifeq ($(USE_HAL_I2C_FALLBACK),)
+ USE_HAL_I2C_FALLBACK = no
+endif
+
+#
+# Build global options
+##############################################################################
+
+##############################################################################
+# Architecture or project specific options
+#
+
+# Stack size to be allocated to the Cortex-M process stack. This stack is
+# the stack used by the main() thread.
+ifeq ($(USE_PROCESS_STACKSIZE),)
+ USE_PROCESS_STACKSIZE = 0x400
+endif
+
+# Stack size to the allocated to the Cortex-M main/exceptions stack. This
+# stack is used for processing interrupts and exceptions.
+ifeq ($(USE_EXCEPTIONS_STACKSIZE),)
+ USE_EXCEPTIONS_STACKSIZE = 0x400
+endif
+
+# Enables the use of FPU (no, softfp, hard).
+ifeq ($(USE_FPU),)
+ USE_FPU = no
+endif
+
+# FPU-related options.
+ifeq ($(USE_FPU_OPT),)
+ USE_FPU_OPT = -mfloat-abi=$(USE_FPU) -mfpu=fpv4-sp-d16
+endif
+
+#
+# Architecture or project specific options
+##############################################################################
+
+##############################################################################
+# Project, target, sources and paths
+#
+
+# Define project name here
+PROJECT = ch
+
+# Target settings.
+MCU = cortex-m4
+
+# Imported source files and paths.
+CHIBIOS := ../../../../ChibiOS
+CHIBIOS_CONTRIB := ../../..
+CONFDIR := ./cfg
+BUILDDIR := ./build
+DEPDIR := ./.dep
+
+# Licensing files.
+include $(CHIBIOS)/os/license/license.mk
+# Startup files.
+include $(CHIBIOS_CONTRIB)/os/common/startup/ARMCMx/compilers/GCC/mk/startup_at32f405xx.mk
+# HAL-OSAL files (optional).
+include $(CHIBIOS)/os/hal/hal.mk
+include $(CHIBIOS_CONTRIB)/os/hal/ports/AT32/AT32F405xx/platform.mk
+include $(CHIBIOS_CONTRIB)/os/hal/boards/AT_START_F405/board.mk
+include $(CHIBIOS)/os/hal/osal/rt-nil/osal.mk
+# RTOS files (optional).
+include $(CHIBIOS)/os/rt/rt.mk
+include $(CHIBIOS)/os/common/ports/ARMv7-M/compilers/GCC/mk/port.mk
+# Auto-build files in ./source recursively.
+include $(CHIBIOS)/tools/mk/autobuild.mk
+# Other files (optional).
+include $(CHIBIOS)/os/test/test.mk
+include $(CHIBIOS)/test/rt/rt_test.mk
+include $(CHIBIOS)/test/oslib/oslib_test.mk
+include $(CHIBIOS)/os/hal/lib/streams/streams.mk
+include $(CHIBIOS)/os/various/shell/shell.mk
+
+# Define linker script file here.
+LDSCRIPT= $(STARTUPLD_CONTRIB)/AT32F405xC.ld
+
+# C sources that can be compiled in ARM or THUMB mode depending on the global
+# setting.
+CSRC = $(ALLCSRC) \
+ $(TESTSRC) \
+ main.c
+
+# C++ sources that can be compiled in ARM or THUMB mode depending on the global
+# setting.
+CPPSRC = $(ALLCPPSRC)
+
+# List ASM source files here.
+ASMSRC = $(ALLASMSRC)
+
+# List ASM with preprocessor source files here.
+ASMXSRC = $(ALLXASMSRC)
+
+# Inclusion directories.
+INCDIR = $(CONFDIR) $(ALLINC) $(TESTINC)
+
+# Define C warning options here.
+CWARN = -Wall -Wextra -Wundef -Wstrict-prototypes
+
+# Define C++ warning options here.
+CPPWARN = -Wall -Wextra -Wundef
+
+#
+# Project, target, sources and paths
+##############################################################################
+
+##############################################################################
+# Start of user section
+#
+
+# List all user C define here, like -D_DEBUG=1
+UDEFS =
+
+# Define ASM defines here
+UADEFS =
+
+# List all user directories here
+UINCDIR =
+
+# List the user directory to look for the libraries here
+ULIBDIR =
+
+# List all user libraries here
+ULIBS =
+
+#
+# End of user section
+##############################################################################
+
+##############################################################################
+# Common rules
+#
+
+RULESPATH = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/mk
+include $(RULESPATH)/arm-none-eabi.mk
+include $(RULESPATH)/rules.mk
+
+#
+# Common rules
+##############################################################################
+
+##############################################################################
+# Custom rules
+#
+
+#
+# Custom rules
+##############################################################################
diff --git a/demos/AT32/RT-AT-START-F405/cfg/chconf.h b/demos/AT32/RT-AT-START-F405/cfg/chconf.h
new file mode 100644
index 0000000000..46b3f78b68
--- /dev/null
+++ b/demos/AT32/RT-AT-START-F405/cfg/chconf.h
@@ -0,0 +1,842 @@
+/*
+ ChibiOS - Copyright (C) 2006..2020 Giovanni Di Sirio
+ ChibiOS - Copyright (C) 2023..2024 HorrorTroll
+ ChibiOS - Copyright (C) 2023..2024 Zhaqian
+
+ Licensed 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.
+*/
+
+/**
+ * @file rt/templates/chconf.h
+ * @brief Configuration file template.
+ * @details A copy of this file must be placed in each project directory, it
+ * contains the application specific kernel settings.
+ *
+ * @addtogroup config
+ * @details Kernel related settings and hooks.
+ * @{
+ */
+
+#ifndef CHCONF_H
+#define CHCONF_H
+
+#define _CHIBIOS_RT_CONF_
+#define _CHIBIOS_RT_CONF_VER_7_0_
+
+/*===========================================================================*/
+/**
+ * @name System settings
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Handling of instances.
+ * @note If enabled then threads assigned to various instances can
+ * interact each other using the same synchronization objects.
+ * If disabled then each OS instance is a separate world, no
+ * direct interactions are handled by the OS.
+ */
+#if !defined(CH_CFG_SMP_MODE)
+#define CH_CFG_SMP_MODE FALSE
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name System timers settings
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief System time counter resolution.
+ * @note Allowed values are 16, 32 or 64 bits.
+ */
+#if !defined(CH_CFG_ST_RESOLUTION)
+#define CH_CFG_ST_RESOLUTION 32
+#endif
+
+/**
+ * @brief System tick frequency.
+ * @details Frequency of the system timer that drives the system ticks. This
+ * setting also defines the system tick time unit.
+ */
+#if !defined(CH_CFG_ST_FREQUENCY)
+#define CH_CFG_ST_FREQUENCY 10000
+#endif
+
+/**
+ * @brief Time intervals data size.
+ * @note Allowed values are 16, 32 or 64 bits.
+ */
+#if !defined(CH_CFG_INTERVALS_SIZE)
+#define CH_CFG_INTERVALS_SIZE 32
+#endif
+
+/**
+ * @brief Time types data size.
+ * @note Allowed values are 16 or 32 bits.
+ */
+#if !defined(CH_CFG_TIME_TYPES_SIZE)
+#define CH_CFG_TIME_TYPES_SIZE 32
+#endif
+
+/**
+ * @brief Time delta constant for the tick-less mode.
+ * @note If this value is zero then the system uses the classic
+ * periodic tick. This value represents the minimum number
+ * of ticks that is safe to specify in a timeout directive.
+ * The value one is not valid, timeouts are rounded up to
+ * this value.
+ */
+#if !defined(CH_CFG_ST_TIMEDELTA)
+#define CH_CFG_ST_TIMEDELTA 2
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Kernel parameters and options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Round robin interval.
+ * @details This constant is the number of system ticks allowed for the
+ * threads before preemption occurs. Setting this value to zero
+ * disables the preemption for threads with equal priority and the
+ * round robin becomes cooperative. Note that higher priority
+ * threads can still preempt, the kernel is always preemptive.
+ * @note Disabling the round robin preemption makes the kernel more compact
+ * and generally faster.
+ * @note The round robin preemption is not supported in tickless mode and
+ * must be set to zero in that case.
+ */
+#if !defined(CH_CFG_TIME_QUANTUM)
+#define CH_CFG_TIME_QUANTUM 0
+#endif
+
+/**
+ * @brief Idle thread automatic spawn suppression.
+ * @details When this option is activated the function @p chSysInit()
+ * does not spawn the idle thread. The application @p main()
+ * function becomes the idle thread and must implement an
+ * infinite loop.
+ */
+#if !defined(CH_CFG_NO_IDLE_THREAD)
+#define CH_CFG_NO_IDLE_THREAD FALSE
+#endif
+
+/**
+ * @brief Kernel hardening level.
+ * @details This option is the level of functional-safety checks enabled
+ * in the kerkel. The meaning is:
+ * - 0: No checks, maximum performance.
+ * - 1: Reasonable checks.
+ * - 2: All checks.
+ * .
+ */
+#if !defined(CH_CFG_HARDENING_LEVEL)
+#define CH_CFG_HARDENING_LEVEL 0
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Performance options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief OS optimization.
+ * @details If enabled then time efficient rather than space efficient code
+ * is used when two possible implementations exist.
+ *
+ * @note This is not related to the compiler optimization options.
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_OPTIMIZE_SPEED)
+#define CH_CFG_OPTIMIZE_SPEED TRUE
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Subsystem options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Time Measurement APIs.
+ * @details If enabled then the time measurement APIs are included in
+ * the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_TM)
+#define CH_CFG_USE_TM TRUE
+#endif
+
+/**
+ * @brief Time Stamps APIs.
+ * @details If enabled then the time stamps APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_TIMESTAMP)
+#define CH_CFG_USE_TIMESTAMP TRUE
+#endif
+
+/**
+ * @brief Threads registry APIs.
+ * @details If enabled then the registry APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_REGISTRY)
+#define CH_CFG_USE_REGISTRY TRUE
+#endif
+
+/**
+ * @brief Threads synchronization APIs.
+ * @details If enabled then the @p chThdWait() function is included in
+ * the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_WAITEXIT)
+#define CH_CFG_USE_WAITEXIT TRUE
+#endif
+
+/**
+ * @brief Semaphores APIs.
+ * @details If enabled then the Semaphores APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_SEMAPHORES)
+#define CH_CFG_USE_SEMAPHORES TRUE
+#endif
+
+/**
+ * @brief Semaphores queuing mode.
+ * @details If enabled then the threads are enqueued on semaphores by
+ * priority rather than in FIFO order.
+ *
+ * @note The default is @p FALSE. Enable this if you have special
+ * requirements.
+ * @note Requires @p CH_CFG_USE_SEMAPHORES.
+ */
+#if !defined(CH_CFG_USE_SEMAPHORES_PRIORITY)
+#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE
+#endif
+
+/**
+ * @brief Mutexes APIs.
+ * @details If enabled then the mutexes APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_MUTEXES)
+#define CH_CFG_USE_MUTEXES TRUE
+#endif
+
+/**
+ * @brief Enables recursive behavior on mutexes.
+ * @note Recursive mutexes are heavier and have an increased
+ * memory footprint.
+ *
+ * @note The default is @p FALSE.
+ * @note Requires @p CH_CFG_USE_MUTEXES.
+ */
+#if !defined(CH_CFG_USE_MUTEXES_RECURSIVE)
+#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE
+#endif
+
+/**
+ * @brief Conditional Variables APIs.
+ * @details If enabled then the conditional variables APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_MUTEXES.
+ */
+#if !defined(CH_CFG_USE_CONDVARS)
+#define CH_CFG_USE_CONDVARS TRUE
+#endif
+
+/**
+ * @brief Conditional Variables APIs with timeout.
+ * @details If enabled then the conditional variables APIs with timeout
+ * specification are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_CONDVARS.
+ */
+#if !defined(CH_CFG_USE_CONDVARS_TIMEOUT)
+#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE
+#endif
+
+/**
+ * @brief Events Flags APIs.
+ * @details If enabled then the event flags APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_EVENTS)
+#define CH_CFG_USE_EVENTS TRUE
+#endif
+
+/**
+ * @brief Events Flags APIs with timeout.
+ * @details If enabled then the events APIs with timeout specification
+ * are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_EVENTS.
+ */
+#if !defined(CH_CFG_USE_EVENTS_TIMEOUT)
+#define CH_CFG_USE_EVENTS_TIMEOUT TRUE
+#endif
+
+/**
+ * @brief Synchronous Messages APIs.
+ * @details If enabled then the synchronous messages APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_MESSAGES)
+#define CH_CFG_USE_MESSAGES TRUE
+#endif
+
+/**
+ * @brief Synchronous Messages queuing mode.
+ * @details If enabled then messages are served by priority rather than in
+ * FIFO order.
+ *
+ * @note The default is @p FALSE. Enable this if you have special
+ * requirements.
+ * @note Requires @p CH_CFG_USE_MESSAGES.
+ */
+#if !defined(CH_CFG_USE_MESSAGES_PRIORITY)
+#define CH_CFG_USE_MESSAGES_PRIORITY FALSE
+#endif
+
+/**
+ * @brief Dynamic Threads APIs.
+ * @details If enabled then the dynamic threads creation APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_WAITEXIT.
+ * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS.
+ */
+#if !defined(CH_CFG_USE_DYNAMIC)
+#define CH_CFG_USE_DYNAMIC TRUE
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name OSLIB options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Mailboxes APIs.
+ * @details If enabled then the asynchronous messages (mailboxes) APIs are
+ * included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_SEMAPHORES.
+ */
+#if !defined(CH_CFG_USE_MAILBOXES)
+#define CH_CFG_USE_MAILBOXES TRUE
+#endif
+
+/**
+ * @brief Memory checks APIs.
+ * @details If enabled then the memory checks APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_MEMCHECKS)
+#define CH_CFG_USE_MEMCHECKS TRUE
+#endif
+
+/**
+ * @brief Core Memory Manager APIs.
+ * @details If enabled then the core memory manager APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_MEMCORE)
+#define CH_CFG_USE_MEMCORE TRUE
+#endif
+
+/**
+ * @brief Managed RAM size.
+ * @details Size of the RAM area to be managed by the OS. If set to zero
+ * then the whole available RAM is used. The core memory is made
+ * available to the heap allocator and/or can be used directly through
+ * the simplified core memory allocator.
+ *
+ * @note In order to let the OS manage the whole RAM the linker script must
+ * provide the @p __heap_base__ and @p __heap_end__ symbols.
+ * @note Requires @p CH_CFG_USE_MEMCORE.
+ */
+#if !defined(CH_CFG_MEMCORE_SIZE)
+#define CH_CFG_MEMCORE_SIZE 0
+#endif
+
+/**
+ * @brief Heap Allocator APIs.
+ * @details If enabled then the memory heap allocator APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or
+ * @p CH_CFG_USE_SEMAPHORES.
+ * @note Mutexes are recommended.
+ */
+#if !defined(CH_CFG_USE_HEAP)
+#define CH_CFG_USE_HEAP TRUE
+#endif
+
+/**
+ * @brief Memory Pools Allocator APIs.
+ * @details If enabled then the memory pools allocator APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_MEMPOOLS)
+#define CH_CFG_USE_MEMPOOLS TRUE
+#endif
+
+/**
+ * @brief Objects FIFOs APIs.
+ * @details If enabled then the objects FIFOs APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_OBJ_FIFOS)
+#define CH_CFG_USE_OBJ_FIFOS TRUE
+#endif
+
+/**
+ * @brief Pipes APIs.
+ * @details If enabled then the pipes APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_PIPES)
+#define CH_CFG_USE_PIPES TRUE
+#endif
+
+/**
+ * @brief Objects Caches APIs.
+ * @details If enabled then the objects caches APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_OBJ_CACHES)
+#define CH_CFG_USE_OBJ_CACHES TRUE
+#endif
+
+/**
+ * @brief Delegate threads APIs.
+ * @details If enabled then the delegate threads APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_DELEGATES)
+#define CH_CFG_USE_DELEGATES TRUE
+#endif
+
+/**
+ * @brief Jobs Queues APIs.
+ * @details If enabled then the jobs queues APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_JOBS)
+#define CH_CFG_USE_JOBS TRUE
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Objects factory options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Objects Factory APIs.
+ * @details If enabled then the objects factory APIs are included in the
+ * kernel.
+ *
+ * @note The default is @p FALSE.
+ */
+#if !defined(CH_CFG_USE_FACTORY)
+#define CH_CFG_USE_FACTORY TRUE
+#endif
+
+/**
+ * @brief Maximum length for object names.
+ * @details If the specified length is zero then the name is stored by
+ * pointer but this could have unintended side effects.
+ */
+#if !defined(CH_CFG_FACTORY_MAX_NAMES_LENGTH)
+#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8
+#endif
+
+/**
+ * @brief Enables the registry of generic objects.
+ */
+#if !defined(CH_CFG_FACTORY_OBJECTS_REGISTRY)
+#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE
+#endif
+
+/**
+ * @brief Enables factory for generic buffers.
+ */
+#if !defined(CH_CFG_FACTORY_GENERIC_BUFFERS)
+#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE
+#endif
+
+/**
+ * @brief Enables factory for semaphores.
+ */
+#if !defined(CH_CFG_FACTORY_SEMAPHORES)
+#define CH_CFG_FACTORY_SEMAPHORES TRUE
+#endif
+
+/**
+ * @brief Enables factory for mailboxes.
+ */
+#if !defined(CH_CFG_FACTORY_MAILBOXES)
+#define CH_CFG_FACTORY_MAILBOXES TRUE
+#endif
+
+/**
+ * @brief Enables factory for objects FIFOs.
+ */
+#if !defined(CH_CFG_FACTORY_OBJ_FIFOS)
+#define CH_CFG_FACTORY_OBJ_FIFOS TRUE
+#endif
+
+/**
+ * @brief Enables factory for Pipes.
+ */
+#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__)
+#define CH_CFG_FACTORY_PIPES TRUE
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Debug options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Debug option, kernel statistics.
+ *
+ * @note The default is @p FALSE.
+ */
+#if !defined(CH_DBG_STATISTICS)
+#define CH_DBG_STATISTICS FALSE
+#endif
+
+/**
+ * @brief Debug option, system state check.
+ * @details If enabled the correct call protocol for system APIs is checked
+ * at runtime.
+ *
+ * @note The default is @p FALSE.
+ */
+#if !defined(CH_DBG_SYSTEM_STATE_CHECK)
+#define CH_DBG_SYSTEM_STATE_CHECK TRUE
+#endif
+
+/**
+ * @brief Debug option, parameters checks.
+ * @details If enabled then the checks on the API functions input
+ * parameters are activated.
+ *
+ * @note The default is @p FALSE.
+ */
+#if !defined(CH_DBG_ENABLE_CHECKS)
+#define CH_DBG_ENABLE_CHECKS TRUE
+#endif
+
+/**
+ * @brief Debug option, consistency checks.
+ * @details If enabled then all the assertions in the kernel code are
+ * activated. This includes consistency checks inside the kernel,
+ * runtime anomalies and port-defined checks.
+ *
+ * @note The default is @p FALSE.
+ */
+#if !defined(CH_DBG_ENABLE_ASSERTS)
+#define CH_DBG_ENABLE_ASSERTS TRUE
+#endif
+
+/**
+ * @brief Debug option, trace buffer.
+ * @details If enabled then the trace buffer is activated.
+ *
+ * @note The default is @p CH_DBG_TRACE_MASK_DISABLED.
+ */
+#if !defined(CH_DBG_TRACE_MASK)
+#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_ALL
+#endif
+
+/**
+ * @brief Trace buffer entries.
+ * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is
+ * different from @p CH_DBG_TRACE_MASK_DISABLED.
+ */
+#if !defined(CH_DBG_TRACE_BUFFER_SIZE)
+#define CH_DBG_TRACE_BUFFER_SIZE 128
+#endif
+
+/**
+ * @brief Debug option, stack checks.
+ * @details If enabled then a runtime stack check is performed.
+ *
+ * @note The default is @p FALSE.
+ * @note The stack check is performed in a architecture/port dependent way.
+ * It may not be implemented or some ports.
+ * @note The default failure mode is to halt the system with the global
+ * @p panic_msg variable set to @p NULL.
+ */
+#if !defined(CH_DBG_ENABLE_STACK_CHECK)
+#define CH_DBG_ENABLE_STACK_CHECK TRUE
+#endif
+
+/**
+ * @brief Debug option, stacks initialization.
+ * @details If enabled then the threads working area is filled with a byte
+ * value when a thread is created. This can be useful for the
+ * runtime measurement of the used stack.
+ *
+ * @note The default is @p FALSE.
+ */
+#if !defined(CH_DBG_FILL_THREADS)
+#define CH_DBG_FILL_THREADS TRUE
+#endif
+
+/**
+ * @brief Debug option, threads profiling.
+ * @details If enabled then a field is added to the @p thread_t structure that
+ * counts the system ticks occurred while executing the thread.
+ *
+ * @note The default is @p FALSE.
+ * @note This debug option is not currently compatible with the
+ * tickless mode.
+ */
+#if !defined(CH_DBG_THREADS_PROFILING)
+#define CH_DBG_THREADS_PROFILING FALSE
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Kernel hooks
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief System structure extension.
+ * @details User fields added to the end of the @p ch_system_t structure.
+ */
+#define CH_CFG_SYSTEM_EXTRA_FIELDS \
+ /* Add system custom fields here.*/
+
+/**
+ * @brief System initialization hook.
+ * @details User initialization code added to the @p chSysInit() function
+ * just before interrupts are enabled globally.
+ */
+#define CH_CFG_SYSTEM_INIT_HOOK() { \
+ /* Add system initialization code here.*/ \
+}
+
+/**
+ * @brief OS instance structure extension.
+ * @details User fields added to the end of the @p os_instance_t structure.
+ */
+#define CH_CFG_OS_INSTANCE_EXTRA_FIELDS \
+ /* Add OS instance custom fields here.*/
+
+/**
+ * @brief OS instance initialization hook.
+ *
+ * @param[in] oip pointer to the @p os_instance_t structure
+ */
+#define CH_CFG_OS_INSTANCE_INIT_HOOK(oip) { \
+ /* Add OS instance initialization code here.*/ \
+}
+
+/**
+ * @brief Threads descriptor structure extension.
+ * @details User fields added to the end of the @p thread_t structure.
+ */
+#define CH_CFG_THREAD_EXTRA_FIELDS \
+ /* Add threads custom fields here.*/
+
+/**
+ * @brief Threads initialization hook.
+ * @details User initialization code added to the @p _thread_init() function.
+ *
+ * @note It is invoked from within @p _thread_init() and implicitly from all
+ * the threads creation APIs.
+ *
+ * @param[in] tp pointer to the @p thread_t structure
+ */
+#define CH_CFG_THREAD_INIT_HOOK(tp) { \
+ /* Add threads initialization code here.*/ \
+}
+
+/**
+ * @brief Threads finalization hook.
+ * @details User finalization code added to the @p chThdExit() API.
+ *
+ * @param[in] tp pointer to the @p thread_t structure
+ */
+#define CH_CFG_THREAD_EXIT_HOOK(tp) { \
+ /* Add threads finalization code here.*/ \
+}
+
+/**
+ * @brief Context switch hook.
+ * @details This hook is invoked just before switching between threads.
+ *
+ * @param[in] ntp thread being switched in
+ * @param[in] otp thread being switched out
+ */
+#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \
+ /* Context switch code here.*/ \
+}
+
+/**
+ * @brief ISR enter hook.
+ */
+#define CH_CFG_IRQ_PROLOGUE_HOOK() { \
+ /* IRQ prologue code here.*/ \
+}
+
+/**
+ * @brief ISR exit hook.
+ */
+#define CH_CFG_IRQ_EPILOGUE_HOOK() { \
+ /* IRQ epilogue code here.*/ \
+}
+
+/**
+ * @brief Idle thread enter hook.
+ * @note This hook is invoked within a critical zone, no OS functions
+ * should be invoked from here.
+ * @note This macro can be used to activate a power saving mode.
+ */
+#define CH_CFG_IDLE_ENTER_HOOK() { \
+ /* Idle-enter code here.*/ \
+}
+
+/**
+ * @brief Idle thread leave hook.
+ * @note This hook is invoked within a critical zone, no OS functions
+ * should be invoked from here.
+ * @note This macro can be used to deactivate a power saving mode.
+ */
+#define CH_CFG_IDLE_LEAVE_HOOK() { \
+ /* Idle-leave code here.*/ \
+}
+
+/**
+ * @brief Idle Loop hook.
+ * @details This hook is continuously invoked by the idle thread loop.
+ */
+#define CH_CFG_IDLE_LOOP_HOOK() { \
+ /* Idle loop code here.*/ \
+}
+
+/**
+ * @brief System tick event hook.
+ * @details This hook is invoked in the system tick handler immediately
+ * after processing the virtual timers queue.
+ */
+#define CH_CFG_SYSTEM_TICK_HOOK() { \
+ /* System tick event code here.*/ \
+}
+
+/**
+ * @brief System halt hook.
+ * @details This hook is invoked in case to a system halting error before
+ * the system is halted.
+ */
+#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \
+ /* System halt code here.*/ \
+}
+
+/**
+ * @brief Trace hook.
+ * @details This hook is invoked each time a new record is written in the
+ * trace buffer.
+ */
+#define CH_CFG_TRACE_HOOK(tep) { \
+ /* Trace code here.*/ \
+}
+
+/**
+ * @brief Runtime Faults Collection Unit hook.
+ * @details This hook is invoked each time new faults are collected and stored.
+ */
+#define CH_CFG_RUNTIME_FAULTS_HOOK(mask) { \
+ /* Faults handling code here.*/ \
+}
+
+/** @} */
+
+/*===========================================================================*/
+/* Port-specific settings (override port settings defaulted in chcore.h). */
+/*===========================================================================*/
+
+#endif /* CHCONF_H */
+
+/** @} */
diff --git a/demos/AT32/RT-AT-START-F405/cfg/config.h b/demos/AT32/RT-AT-START-F405/cfg/config.h
new file mode 100644
index 0000000000..4fbd7cc3df
--- /dev/null
+++ b/demos/AT32/RT-AT-START-F405/cfg/config.h
@@ -0,0 +1,30 @@
+/*
+ ChibiOS - Copyright (C) 2006..2020 Giovanni Di Sirio
+ ChibiOS - Copyright (C) 2023..2024 HorrorTroll
+ ChibiOS - Copyright (C) 2023..2024 Zhaqian
+
+ Licensed 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.
+*/
+
+/*
+ * I2C fallback driver system settings.
+ */
+#define SW_I2C_USE_I2C1 FALSE
+#define SW_I2C_USE_I2C2 FALSE
+#define SW_I2C_USE_I2C3 FALSE
+#define SW_I2C_USE_I2C4 FALSE
+
+/*
+ * Other settings.
+ */
+#define BOARD_OTG_VBUSIG
diff --git a/demos/AT32/RT-AT-START-F405/cfg/halconf.h b/demos/AT32/RT-AT-START-F405/cfg/halconf.h
new file mode 100644
index 0000000000..59fb7c11f3
--- /dev/null
+++ b/demos/AT32/RT-AT-START-F405/cfg/halconf.h
@@ -0,0 +1,556 @@
+/*
+ ChibiOS - Copyright (C) 2006..2020 Giovanni Di Sirio
+ ChibiOS - Copyright (C) 2023..2024 HorrorTroll
+ ChibiOS - Copyright (C) 2023..2024 Zhaqian
+ ChibiOS - Copyright (C) 2023..2024 Maxjta
+
+ Licensed 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.
+*/
+
+/**
+ * @file templates/halconf.h
+ * @brief HAL configuration header.
+ * @details HAL configuration file, this file allows to enable or disable the
+ * various device drivers from your application. You may also use
+ * this file in order to override the device drivers default settings.
+ *
+ * @addtogroup HAL_CONF
+ * @{
+ */
+
+#ifndef HALCONF_H
+#define HALCONF_H
+
+#define _CHIBIOS_HAL_CONF_
+#define _CHIBIOS_HAL_CONF_VER_8_4_
+
+#include "mcuconf.h"
+
+/**
+ * @brief Enables the PAL subsystem.
+ */
+#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__)
+#define HAL_USE_PAL TRUE
+#endif
+
+/**
+ * @brief Enables the ADC subsystem.
+ */
+#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__)
+#define HAL_USE_ADC TRUE
+#endif
+
+/**
+ * @brief Enables the CAN subsystem.
+ */
+#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__)
+#define HAL_USE_CAN FALSE
+#endif
+
+/**
+ * @brief Enables the cryptographic subsystem.
+ */
+#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__)
+#define HAL_USE_CRY FALSE
+#endif
+
+/**
+ * @brief Enables the DAC subsystem.
+ */
+#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__)
+#define HAL_USE_DAC FALSE
+#endif
+
+/**
+ * @brief Enables the EFlash subsystem.
+ */
+#if !defined(HAL_USE_EFL) || defined(__DOXYGEN__)
+#define HAL_USE_EFL FALSE
+#endif
+
+/**
+ * @brief Enables the GPT subsystem.
+ */
+#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__)
+#define HAL_USE_GPT FALSE
+#endif
+
+/**
+ * @brief Enables the I2C subsystem.
+ */
+#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__)
+#define HAL_USE_I2C TRUE
+#endif
+
+/**
+ * @brief Enables the I2S subsystem.
+ */
+#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__)
+#define HAL_USE_I2S FALSE
+#endif
+
+/**
+ * @brief Enables the ICU subsystem.
+ */
+#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__)
+#define HAL_USE_ICU FALSE
+#endif
+
+/**
+ * @brief Enables the MAC subsystem.
+ */
+#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__)
+#define HAL_USE_MAC FALSE
+#endif
+
+/**
+ * @brief Enables the MMC_SPI subsystem.
+ */
+#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__)
+#define HAL_USE_MMC_SPI FALSE
+#endif
+
+/**
+ * @brief Enables the PWM subsystem.
+ */
+#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__)
+#define HAL_USE_PWM FALSE
+#endif
+
+/**
+ * @brief Enables the RTC subsystem.
+ */
+#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__)
+#define HAL_USE_RTC FALSE
+#endif
+
+/**
+ * @brief Enables the SDC subsystem.
+ */
+#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__)
+#define HAL_USE_SDC FALSE
+#endif
+
+/**
+ * @brief Enables the SERIAL subsystem.
+ */
+#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__)
+#define HAL_USE_SERIAL TRUE
+#endif
+
+/**
+ * @brief Enables the SERIAL over USB subsystem.
+ */
+#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__)
+#define HAL_USE_SERIAL_USB FALSE
+#endif
+
+/**
+ * @brief Enables the SIO subsystem.
+ */
+#if !defined(HAL_USE_SIO) || defined(__DOXYGEN__)
+#define HAL_USE_SIO FALSE
+#endif
+
+/**
+ * @brief Enables the SPI subsystem.
+ */
+#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__)
+#define HAL_USE_SPI TRUE
+#endif
+
+/**
+ * @brief Enables the TRNG subsystem.
+ */
+#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__)
+#define HAL_USE_TRNG FALSE
+#endif
+
+/**
+ * @brief Enables the UART subsystem.
+ */
+#if !defined(HAL_USE_UART) || defined(__DOXYGEN__)
+#define HAL_USE_UART FALSE
+#endif
+
+/**
+ * @brief Enables the USB subsystem.
+ */
+#if !defined(HAL_USE_USB) || defined(__DOXYGEN__)
+#define HAL_USE_USB TRUE
+#endif
+
+/**
+ * @brief Enables the WDG subsystem.
+ */
+#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__)
+#define HAL_USE_WDG FALSE
+#endif
+
+/**
+ * @brief Enables the WSPI subsystem.
+ */
+#if !defined(HAL_USE_WSPI) || defined(__DOXYGEN__)
+#define HAL_USE_WSPI FALSE
+#endif
+
+/*===========================================================================*/
+/* PAL driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__)
+#define PAL_USE_CALLBACKS FALSE
+#endif
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__)
+#define PAL_USE_WAIT FALSE
+#endif
+
+/*===========================================================================*/
+/* ADC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__)
+#define ADC_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define ADC_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* CAN driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Sleep mode related APIs inclusion switch.
+ */
+#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__)
+#define CAN_USE_SLEEP_MODE TRUE
+#endif
+
+/**
+ * @brief Enforces the driver to use direct callbacks rather than OSAL events.
+ */
+#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__)
+#define CAN_ENFORCE_USE_CALLBACKS FALSE
+#endif
+
+/*===========================================================================*/
+/* CRY driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables the SW fall-back of the cryptographic driver.
+ * @details When enabled, this option, activates a fall-back software
+ * implementation for algorithms not supported by the underlying
+ * hardware.
+ * @note Fall-back implementations may not be present for all algorithms.
+ */
+#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__)
+#define HAL_CRY_USE_FALLBACK FALSE
+#endif
+
+/**
+ * @brief Makes the driver forcibly use the fall-back implementations.
+ */
+#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__)
+#define HAL_CRY_ENFORCE_FALLBACK FALSE
+#endif
+
+/*===========================================================================*/
+/* DAC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__)
+#define DAC_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define DAC_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* I2C driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables the mutual exclusion APIs on the I2C bus.
+ */
+#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define I2C_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* MAC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables the zero-copy API.
+ */
+#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__)
+#define MAC_USE_ZERO_COPY FALSE
+#endif
+
+/**
+ * @brief Enables an event sources for incoming packets.
+ */
+#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__)
+#define MAC_USE_EVENTS TRUE
+#endif
+
+/*===========================================================================*/
+/* MMC_SPI driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Timeout before assuming a failure while waiting for card idle.
+ * @note Time is in milliseconds.
+ */
+#if !defined(MMC_IDLE_TIMEOUT_MS) || defined(__DOXYGEN__)
+#define MMC_IDLE_TIMEOUT_MS 1000
+#endif
+
+/**
+ * @brief Mutual exclusion on the SPI bus.
+ */
+#if !defined(MMC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define MMC_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* SDC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Number of initialization attempts before rejecting the card.
+ * @note Attempts are performed at 10mS intervals.
+ */
+#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__)
+#define SDC_INIT_RETRY 100
+#endif
+
+/**
+ * @brief Include support for MMC cards.
+ * @note MMC support is not yet implemented so this option must be kept
+ * at @p FALSE.
+ */
+#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__)
+#define SDC_MMC_SUPPORT FALSE
+#endif
+
+/**
+ * @brief Delays insertions.
+ * @details If enabled this options inserts delays into the MMC waiting
+ * routines releasing some extra CPU time for the threads with
+ * lower priority, this may slow down the driver a bit however.
+ */
+#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__)
+#define SDC_NICE_WAITING TRUE
+#endif
+
+/**
+ * @brief OCR initialization constant for V20 cards.
+ */
+#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__)
+#define SDC_INIT_OCR_V20 0x50FF8000U
+#endif
+
+/**
+ * @brief OCR initialization constant for non-V20 cards.
+ */
+#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__)
+#define SDC_INIT_OCR 0x80100000U
+#endif
+
+/*===========================================================================*/
+/* SERIAL driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Default bit rate.
+ * @details Configuration parameter, this is the baud rate selected for the
+ * default configuration.
+ */
+#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__)
+#define SERIAL_DEFAULT_BITRATE 38400
+#endif
+
+/**
+ * @brief Serial buffers size.
+ * @details Configuration parameter, you can change the depth of the queue
+ * buffers depending on the requirements of your application.
+ * @note The default is 16 bytes for both the transmission and receive
+ * buffers.
+ */
+#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)
+#define SERIAL_BUFFERS_SIZE 16
+#endif
+
+/*===========================================================================*/
+/* SIO driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Default bit rate.
+ * @details Configuration parameter, this is the baud rate selected for the
+ * default configuration.
+ */
+#if !defined(SIO_DEFAULT_BITRATE) || defined(__DOXYGEN__)
+#define SIO_DEFAULT_BITRATE 38400
+#endif
+
+/**
+ * @brief Support for thread synchronization API.
+ */
+#if !defined(SIO_USE_SYNCHRONIZATION) || defined(__DOXYGEN__)
+#define SIO_USE_SYNCHRONIZATION TRUE
+#endif
+
+/*===========================================================================*/
+/* SERIAL_USB driver related setting. */
+/*===========================================================================*/
+
+/**
+ * @brief Serial over USB buffers size.
+ * @details Configuration parameter, the buffer size must be a multiple of
+ * the USB data endpoint maximum packet size.
+ * @note The default is 256 bytes for both the transmission and receive
+ * buffers.
+ */
+#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__)
+#define SERIAL_USB_BUFFERS_SIZE 256
+#endif
+
+/**
+ * @brief Serial over USB number of buffers.
+ * @note The default is 2 buffers.
+ */
+#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__)
+#define SERIAL_USB_BUFFERS_NUMBER 2
+#endif
+
+/*===========================================================================*/
+/* SPI driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__)
+#define SPI_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Inserts an assertion on function errors before returning.
+ */
+#if !defined(SPI_USE_ASSERT_ON_ERROR) || defined(__DOXYGEN__)
+#define SPI_USE_ASSERT_ON_ERROR TRUE
+#endif
+
+/**
+ * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define SPI_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/**
+ * @brief Handling method for SPI CS line.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__)
+#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD
+#endif
+
+/*===========================================================================*/
+/* UART driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__)
+#define UART_USE_WAIT FALSE
+#endif
+
+/**
+ * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define UART_USE_MUTUAL_EXCLUSION FALSE
+#endif
+
+/*===========================================================================*/
+/* USB driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__)
+#define USB_USE_WAIT FALSE
+#endif
+
+/*===========================================================================*/
+/* WSPI driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__)
+#define WSPI_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define WSPI_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+#endif /* HALCONF_H */
+
+/** @} */
diff --git a/demos/AT32/RT-AT-START-F405/cfg/mcuconf.h b/demos/AT32/RT-AT-START-F405/cfg/mcuconf.h
new file mode 100644
index 0000000000..a7eb2a1ad1
--- /dev/null
+++ b/demos/AT32/RT-AT-START-F405/cfg/mcuconf.h
@@ -0,0 +1,292 @@
+/*
+ ChibiOS - Copyright (C) 2006..2020 Giovanni Di Sirio
+ ChibiOS - Copyright (C) 2023..2024 HorrorTroll
+ ChibiOS - Copyright (C) 2023..2024 Zhaqian
+ ChibiOS - Copyright (C) 2023..2024 Maxjta
+
+ Licensed 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 MCUCONF_H
+#define MCUCONF_H
+
+/*
+ * AT32F405 drivers configuration.
+ * The following settings override the default settings present in
+ * the various device driver implementation headers.
+ * Note that the settings for each driver only have effect if the whole
+ * driver is enabled in halconf.h.
+ *
+ * IRQ priorities:
+ * 15...0 Lowest...Highest.
+ *
+ * DMA priorities:
+ * 0...3 Lowest...Highest.
+ */
+
+#define AT32F405xx_MCUCONF
+
+/*
+ * General settings.
+ */
+#define AT32_NO_INIT FALSE
+
+/*
+ * HAL driver system settings.
+ */
+#define AT32_HICK_ENABLED TRUE
+#define AT32_LICK_ENABLED TRUE
+#define AT32_HEXT_ENABLED TRUE
+#define AT32_LEXT_ENABLED FALSE
+#define AT32_SCLKSEL AT32_SCLKSEL_PLL
+#define AT32_PLLRCS AT32_PLLRCS_HEXT
+#define AT32_PLLHEXTDIV AT32_PLLHEXTDIV_DIV1
+#define AT32_PLLCFGEN AT32_PLLCFGEN_SOLID
+#define AT32_PLL_FP_VALUE 4
+#define AT32_PLL_FU_VALUE 18
+#define AT32_PLL_MS_VALUE 1
+#define AT32_PLL_NS_VALUE 72
+#define AT32_AHBDIV AT32_AHBDIV_DIV1
+#define AT32_APB1DIV AT32_APB1DIV_DIV2
+#define AT32_APB2DIV AT32_APB2DIV_DIV2
+#define AT32_ADCDIV AT32_ADCDIV_DIV4
+#define AT32_USB_CLOCK_REQUIRED TRUE
+#define AT32_CLKOUT_SEL AT32_CLKOUT_SEL_HICK
+#define AT32_CLKOUTDIV AT32_CLKOUTDIV_DIV1
+#define AT32_ERTCSEL AT32_ERTCSEL_LICK
+#define AT32_PVM_ENABLE FALSE
+#define AT32_PVMSEL AT32_PVMSEL_LEV1
+
+/*
+ * IRQ system settings.
+ */
+#define AT32_IRQ_EXINT0_PRIORITY 6
+#define AT32_IRQ_EXINT1_PRIORITY 6
+#define AT32_IRQ_EXINT2_PRIORITY 6
+#define AT32_IRQ_EXINT3_PRIORITY 6
+#define AT32_IRQ_EXINT4_PRIORITY 6
+#define AT32_IRQ_EXINT5_9_PRIORITY 6
+#define AT32_IRQ_EXINT10_15_PRIORITY 6
+#define AT32_IRQ_EXINT16_PRIORITY 6
+#define AT32_IRQ_EXINT17_PRIORITY 15
+#define AT32_IRQ_EXINT18_PRIORITY 6
+#define AT32_IRQ_EXINT19_PRIORITY 6
+#define AT32_IRQ_EXINT20_PRIORITY 6
+#define AT32_IRQ_EXINT21_PRIORITY 15
+#define AT32_IRQ_EXINT22_PRIORITY 15
+
+#define AT32_IRQ_TMR1_BRK_TMR9_PRIORITY 7
+#define AT32_IRQ_TMR1_OVF_TMR10_PRIORITY 7
+#define AT32_IRQ_TMR1_HALL_TMR11_PRIORITY 7
+#define AT32_IRQ_TMR1_CH_PRIORITY 7
+#define AT32_IRQ_TMR2_PRIORITY 7
+#define AT32_IRQ_TMR3_PRIORITY 7
+#define AT32_IRQ_TMR4_PRIORITY 7
+#define AT32_IRQ_TMR5_PRIORITY 7
+#define AT32_IRQ_TMR6_PRIORITY 7
+#define AT32_IRQ_TMR7_PRIORITY 7
+#define AT32_IRQ_TMR13_PRIORITY 7
+#define AT32_IRQ_TMR14_PRIORITY 7
+
+#define AT32_IRQ_USART1_PRIORITY 12
+#define AT32_IRQ_USART2_PRIORITY 12
+#define AT32_IRQ_USART3_PRIORITY 12
+#define AT32_IRQ_UART4_PRIORITY 12
+#define AT32_IRQ_UART5_PRIORITY 12
+#define AT32_IRQ_USART6_PRIORITY 12
+#define AT32_IRQ_UART7_PRIORITY 12
+#define AT32_IRQ_UART8_PRIORITY 12
+
+/*
+ * ADC driver system settings.
+ */
+#define AT32_ADC_USE_ADC1 TRUE
+#define AT32_ADC_ADC1_DMA_PRIORITY 2
+#define AT32_ADC_ADC1_IRQ_PRIORITY 6
+
+/*
+ * CAN driver system settings.
+ */
+#define AT32_CAN_USE_CAN1 FALSE
+#define AT32_CAN_CAN1_IRQ_PRIORITY 11
+
+/*
+ * DMA driver system settings.
+ */
+#define AT32_DMA_USE_DMAMUX TRUE
+
+/*
+ * GPT driver system settings.
+ */
+#define AT32_GPT_USE_TMR1 FALSE
+#define AT32_GPT_USE_TMR2 FALSE
+#define AT32_GPT_USE_TMR3 FALSE
+#define AT32_GPT_USE_TMR4 FALSE
+#define AT32_GPT_USE_TMR5 FALSE
+#define AT32_GPT_USE_TMR9 FALSE
+#define AT32_GPT_USE_TMR10 FALSE
+#define AT32_GPT_USE_TMR11 FALSE
+#define AT32_GPT_USE_TMR13 FALSE
+#define AT32_GPT_USE_TMR14 FALSE
+
+/*
+ * I2C driver system settings.
+ */
+#define AT32_I2C_USE_I2C1 TRUE
+#define AT32_I2C_USE_I2C2 FALSE
+#define AT32_I2C_USE_DMA FALSE
+#define AT32_I2C_BUSY_TIMEOUT 50
+#define AT32_I2C_I2C1_IRQ_PRIORITY 5
+#define AT32_I2C_I2C2_IRQ_PRIORITY 5
+#define AT32_I2C_I2C1_DMA_PRIORITY 3
+#define AT32_I2C_I2C2_DMA_PRIORITY 3
+#define AT32_I2C_I2C1_RX_DMA_STREAM AT32_DMA_STREAM_ID_ANY
+#define AT32_I2C_I2C1_TX_DMA_STREAM AT32_DMA_STREAM_ID_ANY
+#define AT32_I2C_I2C2_RX_DMA_STREAM AT32_DMA_STREAM_ID_ANY
+#define AT32_I2C_I2C2_TX_DMA_STREAM AT32_DMA_STREAM_ID_ANY
+#define AT32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure")
+
+/*
+ * ICU driver system settings.
+ */
+#define AT32_ICU_USE_TMR1 FALSE
+#define AT32_ICU_USE_TMR2 FALSE
+#define AT32_ICU_USE_TMR3 FALSE
+#define AT32_ICU_USE_TMR4 FALSE
+#define AT32_ICU_USE_TMR5 FALSE
+#define AT32_ICU_USE_TMR9 FALSE
+#define AT32_ICU_USE_TMR10 FALSE
+#define AT32_ICU_USE_TMR11 FALSE
+#define AT32_ICU_USE_TMR13 FALSE
+#define AT32_ICU_USE_TMR14 FALSE
+
+/*
+ * PWM driver system settings.
+ */
+#define AT32_PWM_USE_TMR1 FALSE
+#define AT32_PWM_USE_TMR2 FALSE
+#define AT32_PWM_USE_TMR3 FALSE
+#define AT32_PWM_USE_TMR4 FALSE
+#define AT32_PWM_USE_TMR5 FALSE
+#define AT32_PWM_USE_TMR9 FALSE
+#define AT32_PWM_USE_TMR10 FALSE
+#define AT32_PWM_USE_TMR11 FALSE
+#define AT32_PWM_USE_TMR13 FALSE
+#define AT32_PWM_USE_TMR14 FALSE
+
+/*
+ * RTC driver system settings.
+ */
+#define AT32_ERTC_DIVA_VALUE 32
+#define AT32_ERTC_DIVB_VALUE 1024
+#define AT32_ERTC_CTRL_INIT 0
+#define AT32_ERTC_TAMP_INIT 0
+
+/*
+ * SDC driver system settings.
+ */
+#define AT32_SDC_SDIO_DMA_PRIORITY 3
+#define AT32_SDC_SDIO_IRQ_PRIORITY 9
+#define AT32_SDC_WRITE_TIMEOUT_MS 1000
+#define AT32_SDC_READ_TIMEOUT_MS 1000
+#define AT32_SDC_CLOCK_ACTIVATION_DELAY 10
+#define AT32_SDC_SDIO_UNALIGNED_SUPPORT TRUE
+
+/*
+ * SERIAL driver system settings.
+ */
+#define AT32_SERIAL_USE_USART1 TRUE
+#define AT32_SERIAL_USE_USART2 FALSE
+#define AT32_SERIAL_USE_USART3 FALSE
+#define AT32_SERIAL_USE_UART4 FALSE
+#define AT32_SERIAL_USE_UART5 FALSE
+
+/*
+ * SPI driver system settings.
+ */
+#define AT32_SPI_USE_SPI1 TRUE
+#define AT32_SPI_USE_SPI2 FALSE
+#define AT32_SPI_SPI1_RX_DMA_STREAM AT32_DMA_STREAM_ID_ANY
+#define AT32_SPI_SPI1_TX_DMA_STREAM AT32_DMA_STREAM_ID_ANY
+#define AT32_SPI_SPI2_RX_DMA_STREAM AT32_DMA_STREAM_ID_ANY
+#define AT32_SPI_SPI2_TX_DMA_STREAM AT32_DMA_STREAM_ID_ANY
+
+#define AT32_SPI_SPI1_DMA_PRIORITY 1
+#define AT32_SPI_SPI2_DMA_PRIORITY 1
+#define AT32_SPI_SPI1_IRQ_PRIORITY 10
+#define AT32_SPI_SPI2_IRQ_PRIORITY 10
+#define AT32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure")
+
+/*
+ * ST driver system settings.
+ */
+#define AT32_ST_IRQ_PRIORITY 8
+#define AT32_ST_USE_TIMER 2
+
+/*
+ * UART driver system settings.
+ */
+#define AT32_UART_USE_USART1 FALSE
+#define AT32_UART_USE_USART2 FALSE
+#define AT32_UART_USE_USART3 FALSE
+#define AT32_UART_USE_UART4 FALSE
+#define AT32_UART_USE_UART5 FALSE
+
+#define AT32_UART_USART1_RX_DMA_STREAM AT32_DMA_STREAM_ID_ANY
+#define AT32_UART_USART1_TX_DMA_STREAM AT32_DMA_STREAM_ID_ANY
+#define AT32_UART_USART2_RX_DMA_STREAM AT32_DMA_STREAM_ID_ANY
+#define AT32_UART_USART2_TX_DMA_STREAM AT32_DMA_STREAM_ID_ANY
+#define AT32_UART_USART3_RX_DMA_STREAM AT32_DMA_STREAM_ID_ANY
+#define AT32_UART_USART3_TX_DMA_STREAM AT32_DMA_STREAM_ID_ANY
+#define AT32_UART_UART4_RX_DMA_STREAM AT32_DMA_STREAM_ID_ANY
+#define AT32_UART_UART4_TX_DMA_STREAM AT32_DMA_STREAM_ID_ANY
+#define AT32_UART_UART5_RX_DMA_STREAM AT32_DMA_STREAM_ID_ANY
+#define AT32_UART_UART5_TX_DMA_STREAM AT32_DMA_STREAM_ID_ANY
+
+#define AT32_UART_USART1_DMA_PRIORITY 0
+#define AT32_UART_USART2_DMA_PRIORITY 0
+#define AT32_UART_USART3_DMA_PRIORITY 0
+#define AT32_UART_USART4_DMA_PRIORITY 0
+#define AT32_UART_USART5_DMA_PRIORITY 0
+#define AT32_UART_USART6_DMA_PRIORITY 0
+#define AT32_UART_UART7_DMA_PRIORITY 0
+#define AT32_UART_UART8_DMA_PRIORITY 0
+#define AT32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure")
+
+/*
+ * USB driver system settings.
+ */
+#define AT32_USB_USE_OTG1 TRUE
+#define AT32_USB_OTG1_IRQ_PRIORITY 14
+#define AT32_USB_OTG1_RX_FIFO_SIZE 512
+
+#define AT32_USB_USE_OTG2 TRUE
+#define AT32_USB_OTG2_IRQ_PRIORITY 14
+#define AT32_USB_OTG2_RX_FIFO_SIZE 1024
+#define AT32_USE_USB_OTG2_HS TRUE
+#define AT32_OTG2_SUPPORTS_HS TRUE
+
+
+/*
+ * WDG driver system settings.
+ */
+#define AT32_WDG_USE_WDT FALSE
+
+/*
+ * DMA driver Version.
+ */
+#define AT32_USE_DMA_V1 FALSE
+
+#include "config.h"
+
+#endif /* MCUCONF_H */
diff --git a/demos/AT32/RT-AT-START-F405/main.c b/demos/AT32/RT-AT-START-F405/main.c
new file mode 100644
index 0000000000..65e1853b01
--- /dev/null
+++ b/demos/AT32/RT-AT-START-F405/main.c
@@ -0,0 +1,86 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+ ChibiOS - Copyright (C) 2023..2024 HorrorTroll
+ ChibiOS - Copyright (C) 2023..2024 Zhaqian
+ ChibiOS - Copyright (C) 2023..2024 Maxjta
+
+ Licensed 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 "ch.h"
+#include "hal.h"
+#include "rt_test_root.h"
+#include "oslib_test_root.h"
+
+/*
+ * This is a periodic thread that does absolutely nothing except flashing
+ * a LED.
+ */
+static THD_WORKING_AREA(waThread1, 128);
+static THD_FUNCTION(Thread1, arg) {
+
+ (void)arg;
+ chRegSetThreadName("blinker");
+ while (true) {
+ palSetLine(LINE_LED_RED);
+ chThdSleepMilliseconds(250);
+ palSetLine(LINE_LED_YELLOW);
+ chThdSleepMilliseconds(250);
+ palSetLine(LINE_LED_GREEN);
+ chThdSleepMilliseconds(250);
+ palClearLine(LINE_LED_RED);
+ chThdSleepMilliseconds(250);
+ palClearLine(LINE_LED_YELLOW);
+ chThdSleepMilliseconds(250);
+ palClearLine(LINE_LED_GREEN);
+ chThdSleepMilliseconds(250);
+ }
+}
+
+/*
+ * Application entry point.
+ */
+int main(void) {
+
+ /*
+ * System initializations.
+ * - HAL initialization, this also initializes the configured device drivers
+ * and performs the board-specific initializations.
+ * - Kernel initialization, the main() function becomes a thread and the
+ * RTOS is active.
+ */
+ halInit();
+ chSysInit();
+
+ /*
+ * Activates the serial driver 1 using the driver default configuration.
+ */
+ sdStart(&SD1, NULL);
+
+ /*
+ * Creates the example thread.
+ */
+ chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);
+
+ /*
+ * Normal main() thread activity, in this demo it does nothing except
+ * sleeping in a loop and check the button state.
+ */
+ while (true) {
+ if (palReadLine(LINE_BUTTON)) {
+ test_execute((BaseSequentialStream *)&SD1, &rt_test_suite);
+ test_execute((BaseSequentialStream *)&SD1, &oslib_test_suite);
+ }
+ chThdSleepMilliseconds(500);
+ }
+}
diff --git a/os/common/ext/CMSIS/ArteryTek/AT32F402_405xx/at32f402_405xx.h b/os/common/ext/CMSIS/ArteryTek/AT32F402_405xx/at32f402_405xx.h
new file mode 100644
index 0000000000..f359d99744
--- /dev/null
+++ b/os/common/ext/CMSIS/ArteryTek/AT32F402_405xx/at32f402_405xx.h
@@ -0,0 +1,2649 @@
+/**
+ **************************************************************************
+ * @file at32f402_405.h
+ * @brief at32f402_405 header file
+ **************************************************************************
+ * Copyright notice & Disclaimer
+ *
+ * The software Board Support Package (BSP) that is made available to
+ * download from Artery official website is the copyrighted work of Artery.
+ * Artery authorizes customers to use, copy, and distribute the BSP
+ * software and its related documentation for the purpose of design and
+ * development in conjunction with Artery microcontrollers. Use of the
+ * software is governed by this copyright notice and the following disclaimer.
+ *
+ * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
+ * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
+ * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
+ * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
+ * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
+ *
+ **************************************************************************
+ */
+
+#ifndef __AT32F402_405_H
+#define __AT32F402_405_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined (__CC_ARM)
+ #pragma anon_unions
+#endif
+
+/** @addtogroup CMSIS
+ * @{
+ */
+
+/** @addtogroup AT32F402_405
+ * @{
+ */
+
+/** @addtogroup Library_configuration_section
+ * @{
+ */
+
+/**
+ * tip: to avoid modifying this file each time you need to switch between these
+ * devices, you can define the device in your toolchain compiler preprocessor.
+ */
+
+#if !defined (AT32F405KBU7_4) && !defined (AT32F405KCU7_4) && !defined (AT32F405CBT7) && \
+ !defined (AT32F405CCT7) && !defined (AT32F405CBU7) && !defined (AT32F405CCU7) && \
+ !defined (AT32F405RBT7_7) && !defined (AT32F405RCT7_7) && !defined (AT32F405RBT7) && \
+ !defined (AT32F405RCT7) && !defined (AT32F402KBU7_4) && !defined (AT32F402KCU7_4)&& \
+ !defined (AT32F402CBT7) && !defined (AT32F402CCT7) && !defined (AT32F402CBU7) && \
+ !defined (AT32F402CCU7) && !defined (AT32F402RBT7_7) && !defined (AT32F402RCT7_7)&& \
+ !defined (AT32F402RBT7) && !defined (AT32F402RCT7)
+
+ #error "Please select first the target device used in your application (in at32f402_405.h file)"
+#endif
+
+#if defined (AT32F405KBU7_4) || defined (AT32F405KCU7_4) || defined (AT32F405CBT7) || \
+ defined (AT32F405CCT7) || defined (AT32F405CBU7) || defined (AT32F405CCU7) || \
+ defined (AT32F405RBT7_7) || defined (AT32F405RCT7_7) || defined (AT32F405RBT7) || \
+ defined (AT32F405RCT7)
+
+ #define AT32F405xx
+#endif
+
+#if defined (AT32F402KBU7_4) || defined (AT32F402KCU7_4) || defined (AT32F402CBT7) || \
+ defined (AT32F402CCT7) || defined (AT32F402CBU7) || defined (AT32F402CCU7) || \
+ defined (AT32F402RBT7_7) || defined (AT32F402RCT7_7) || defined (AT32F402RBT7) || \
+ defined (AT32F402RCT7)
+
+ #define AT32F402xx
+#endif
+
+/**
+ * define with package
+ */
+#if defined (AT32F405KBU7_4) || defined (AT32F405KCU7_4)
+
+ #define AT32F405Kx
+#endif
+#if defined (AT32F405CBT7) || defined (AT32F405CCT7) || defined (AT32F405CBU7) || \
+ defined (AT32F405CCU7)
+
+ #define AT32F405Rx
+#endif
+
+#if defined (AT32F405RBT7_7) || defined (AT32F405RCT7_7) || defined (AT32F405RBT7) || \
+ defined (AT32F405RCT7)
+
+ #define AT32F405Rx
+#endif
+
+#if defined (AT32F402KBU7_4) || defined (AT32F402KCU7_4)
+
+ #define AT32F402Kx
+#endif
+#if defined (AT32F402CBT7) || defined (AT32F402CCT7) || defined (AT32F402CBU7) || \
+ defined (AT32F402CCU7)
+
+ #define AT32F402Rx
+#endif
+
+#if defined (AT32F402RBT7_7) || defined (AT32F402RCT7_7) || defined (AT32F402RBT7) || \
+ defined (AT32F402RCT7)
+
+ #define AT32F402Rx
+#endif
+
+
+/**
+ * define with memory density
+ */
+#if defined (AT32F405KBU7_4) || defined (AT32F405CBT7) || defined (AT32F405CBU7) || \
+ defined (AT32F405RBT7_7) || defined (AT32F405RBT7)
+
+ #define AT32F405xB
+#endif
+
+#if defined (AT32F405KCU7_4) || defined (AT32F405CCT7) || defined (AT32F405CCU7) || \
+ defined (AT32F405RCT7_7) || defined (AT32F405RCT7)
+
+ #define AT32F405xC
+#endif
+
+#if defined (AT32F402KBU7_4) || defined (AT32F402CBT7) || defined (AT32F402CBU7) || \
+ defined (AT32F402RBT7_7) || defined (AT32F402RBT7)
+
+ #define AT32F402xB
+#endif
+
+#if defined (AT32F402KCU7_4) || defined (AT32F402CCT7) || defined (AT32F402CCU7) || \
+ defined (AT32F402RCT7_7) || defined (AT32F402RCT7)
+
+ #define AT32F402xC
+#endif
+
+#ifndef USE_STDPERIPH_DRIVER
+/**
+ * @brief comment the line below if you will not use the peripherals drivers.
+ * in this case, these drivers will not be included and the application code will
+ * be based on direct access to peripherals registers
+ */
+ #ifdef _RTE_
+ #include "RTE_Components.h"
+ #ifdef RTE_DEVICE_STDPERIPH_FRAMEWORK
+ #define USE_STDPERIPH_DRIVER
+ #endif
+ #endif
+#endif
+
+/**
+ * @brief at32f402_405 standard peripheral library version number
+ */
+#define __AT32F402_405_LIBRARY_VERSION_MAJOR (0x02) /*!< [31:24] major version */
+#define __AT32F402_405_LIBRARY_VERSION_MIDDLE (0x00) /*!< [23:16] middle version */
+#define __AT32F402_405_LIBRARY_VERSION_MINOR (0x00) /*!< [15:8] minor version */
+#define __AT32F402_405_LIBRARY_VERSION_RC (0x00) /*!< [7:0] release candidate */
+#define __AT32F402_405_LIBRARY_VERSION ((__AT32F402_405_LIBRARY_VERSION_MAJOR << 24) | \
+ (__AT32F402_405_LIBRARY_VERSION_MIDDLE << 16) | \
+ (__AT32F402_405_LIBRARY_VERSION_MINOR << 8) | \
+ (__AT32F402_405_LIBRARY_VERSION_RC))
+
+/**
+ * @}
+ */
+
+/** @addtogroup configuration_section_for_cmsis
+ * @{
+ */
+
+/**
+ * @brief configuration of the cortex-m4 processor and core peripherals
+ */
+#define __CM4_REV 0x0001U /*!< core revision r0p1 */
+#define __MPU_PRESENT 1 /*!< mpu present */
+#define __NVIC_PRIO_BITS 4 /*!< at32 uses 4 bits for the priority levels */
+#define __Vendor_SysTickConfig 0 /*!< set to 1 if different systick config is used */
+#define __FPU_PRESENT 1U /*!< fpu present */
+
+/**
+ * @brief at32f402_405 interrupt number definition, according to the selected device
+ * in @ref library_configuration_section
+ */
+typedef enum IRQn
+{
+ /****** cortex-m4 processor exceptions numbers ***************************************************/
+ Reset_IRQn = -15, /*!< 1 reset vector, invoked on power up and warm reset */
+ NonMaskableInt_IRQn = -14, /*!< 2 non maskable interrupt */
+ HardFault_IRQn = -13, /*!< 3 hard fault, all classes of fault */
+ MemoryManagement_IRQn = -12, /*!< 4 cortex-m4 memory management interrupt */
+ BusFault_IRQn = -11, /*!< 5 cortex-m4 bus fault interrupt */
+ UsageFault_IRQn = -10, /*!< 6 cortex-m4 usage fault interrupt */
+ SVCall_IRQn = -5, /*!< 11 cortex-m4 sv call interrupt */
+ DebugMonitor_IRQn = -4, /*!< 12 cortex-m4 debug monitor interrupt */
+ PendSV_IRQn = -2, /*!< 14 cortex-m4 pend sv interrupt */
+ SysTick_IRQn = -1, /*!< 15 cortex-m4 system tick interrupt */
+
+ /****** at32 specific interrupt numbers *********************************************************/
+ WWDT_IRQn = 0, /*!< window watchdog timer interrupt */
+ PVM_IRQn = 1, /*!< pvm through exint line detection interrupt */
+ TAMP_STAMP_IRQn = 2, /*!< tamper and timestamp interrupts through the exint line */
+ ERTC_WKUP_IRQn = 3, /*!< ertc wakeup through the exint line */
+ FLASH_IRQn = 4, /*!< flash global interrupt */
+ CRM_IRQn = 5, /*!< crm global interrupt */
+ EXINT0_IRQn = 6, /*!< exint line0 interrupt */
+ EXINT1_IRQn = 7, /*!< exint line1 interrupt */
+ EXINT2_IRQn = 8, /*!< exint line2 interrupt */
+ EXINT3_IRQn = 9, /*!< exint line3 interrupt */
+ EXINT4_IRQn = 10, /*!< exint line4 interrupt */
+ DMA1_Channel1_IRQn = 11, /*!< dma1 channel 1 global interrupt */
+ DMA1_Channel2_IRQn = 12, /*!< dma1 channel 2 global interrupt */
+ DMA1_Channel3_IRQn = 13, /*!< dma1 channel 3 global interrupt */
+ DMA1_Channel4_IRQn = 14, /*!< dma1 channel 4 global interrupt */
+ DMA1_Channel5_IRQn = 15, /*!< dma1 channel 5 global interrupt */
+ DMA1_Channel6_IRQn = 16, /*!< dma1 channel 6 global interrupt */
+ DMA1_Channel7_IRQn = 17, /*!< dma1 channel 7 global interrupt */
+
+ ADC1_IRQn = 18, /*!< adc1 global interrupt */
+ CAN1_TX_IRQn = 19, /*!< can1 tx interrupts */
+ CAN1_RX0_IRQn = 20, /*!< can1 rx0 interrupts */
+ CAN1_RX1_IRQn = 21, /*!< can1 rx1 interrupt */
+ CAN1_SE_IRQn = 22, /*!< can1 se interrupt */
+ EXINT9_5_IRQn = 23, /*!< external line[9:5] interrupts */
+ TMR1_BRK_TMR9_IRQn = 24, /*!< tmr1 brake interrupt */
+ TMR1_OVF_TMR10_IRQn = 25, /*!< tmr1 overflow interrupt */
+ TMR1_TRG_HALL_TMR11_IRQn = 26, /*!< tmr1 trigger and hall interrupt */
+ TMR1_CH_IRQn = 27, /*!< tmr1 channel interrupt */
+ TMR2_GLOBAL_IRQn = 28, /*!< tmr2 global interrupt */
+ TMR3_GLOBAL_IRQn = 29, /*!< tmr3 global interrupt */
+ TMR4_GLOBAL_IRQn = 30, /*!< tmr4 global interrupt */
+ I2C1_EVT_IRQn = 31, /*!< i2c1 event interrupt */
+ I2C1_ERR_IRQn = 32, /*!< i2c1 error interrupt */
+ I2C2_EVT_IRQn = 33, /*!< i2c2 event interrupt */
+ I2C2_ERR_IRQn = 34, /*!< i2c2 error interrupt */
+ SPI1_IRQn = 35, /*!< spi1 global interrupt */
+ SPI2_IRQn = 36, /*!< spi2 global interrupt */
+ USART1_IRQn = 37, /*!< usart1 global interrupt */
+ USART2_IRQn = 38, /*!< usart2 global interrupt */
+ USART3_IRQn = 39, /*!< usart3 global interrupt */
+ EXINT15_10_IRQn = 40, /*!< external line[15:10] interrupts */
+ ERTCAlarm_IRQn = 41, /*!< ertc alarm through exint line interrupt */
+ OTGFS1_WKUP_IRQn = 42, /*!< otgfs1 wakeup from suspend through exint line interrupt */
+ TMR13_GLOBAL_IRQn = 44, /*!< tmr13 global interrupt */
+ TMR14_GLOBAL_IRQn = 45, /*!< tmr14 global interrupt */
+ SPI3_IRQn = 51, /*!< spi3 global interrupt */
+ USART4_IRQn = 52, /*!< usart4 global interrupt */
+ USART5_IRQn = 53, /*!< usart5 global interrupt */
+ TMR6_GLOBAL_IRQn = 54, /*!< tmr6 global interrupt */
+ TMR7_GLOBAL_IRQn = 55, /*!< tmr7 global interrupt */
+ DMA2_Channel1_IRQn = 56, /*!< dma2 channel 1 global interrupt */
+ DMA2_Channel2_IRQn = 57, /*!< dma2 channel 2 global interrupt */
+ DMA2_Channel3_IRQn = 58, /*!< dma2 channel 3 global interrupt */
+ DMA2_Channel4_IRQn = 59, /*!< dma2 channel 4 global interrupt */
+ DMA2_Channel5_IRQn = 60, /*!< dma2 channel 5 global interrupt */
+ OTGFS1_IRQn = 67, /*!< otgfs1 interrupt */
+ DMA2_Channel6_IRQn = 68, /*!< dma2 channel 6 global interrupt */
+ DMA2_Channel7_IRQn = 69, /*!< dma2 channel 7 global interrupt */
+ USART6_IRQn = 71, /*!< usart6 interrupt */
+ I2C3_EVT_IRQn = 72, /*!< i2c3 event interrupt */
+ I2C3_ERR_IRQn = 73, /*!< i2c3 error interrupt */
+ OTGHS_EP1_OUT_IRQn = 74, /*!< otghs wakeup from suspend through exint line interrupt */
+ OTGHS_EP1_IN_IRQn = 75, /*!< otghs interrupt */
+ OTGHS_WKUP_IRQn = 76, /*!< otghs wakeup from suspend through exint line interrupt */
+ OTGHS_IRQn = 77, /*!< otghs interrupt */
+ FPU_IRQn = 81, /*!< fpu interrupt */
+ UART7_IRQn = 82, /*!< uart7 interrupt */
+ UART8_IRQn = 83, /*!< uart8 interrupt */
+ I2SF5_IRQn = 85, /*!< i2sf5 global interrupt */
+ QSPI1_IRQn = 92, /*!< qspi1 global interrupt */
+ DMAMUX_IRQn = 94, /*!< dmamux global interrupt */
+ ACC_IRQn = 103, /*!< acc interrupt */
+
+} IRQn_Type;
+
+/**
+ * @}
+ */
+
+#include "core_cm4.h"
+#include
+
+/** @addtogroup Exported_types
+ * @{
+ */
+
+typedef int32_t INT32;
+typedef int16_t INT16;
+typedef int8_t INT8;
+typedef uint32_t UINT32;
+typedef uint16_t UINT16;
+typedef uint8_t UINT8;
+
+typedef int32_t s32;
+typedef int16_t s16;
+typedef int8_t s8;
+
+typedef const int32_t sc32; /*!< read only */
+typedef const int16_t sc16; /*!< read only */
+typedef const int8_t sc8; /*!< read only */
+
+typedef __IO int32_t vs32;
+typedef __IO int16_t vs16;
+typedef __IO int8_t vs8;
+
+typedef __I int32_t vsc32; /*!< read only */
+typedef __I int16_t vsc16; /*!< read only */
+typedef __I int8_t vsc8; /*!< read only */
+
+typedef uint32_t u32;
+typedef uint16_t u16;
+typedef uint8_t u8;
+
+typedef const uint32_t uc32; /*!< read only */
+typedef const uint16_t uc16; /*!< read only */
+typedef const uint8_t uc8; /*!< read only */
+
+typedef __IO uint32_t vu32;
+typedef __IO uint16_t vu16;
+typedef __IO uint8_t vu8;
+
+typedef __I uint32_t vuc32; /*!< read only */
+typedef __I uint16_t vuc16; /*!< read only */
+typedef __I uint8_t vuc8; /*!< read only */
+
+typedef enum {RESET = 0, SET = !RESET} flag_status;
+typedef enum {ERROR = 0, SUCCESS = !ERROR} error_status;
+
+/**
+ * @}
+ */
+
+/** @addtogroup Exported_macro
+ * @{
+ */
+
+#define REG8(addr) *(volatile uint8_t *)(addr)
+#define REG16(addr) *(volatile uint16_t *)(addr)
+#define REG32(addr) *(volatile uint32_t *)(addr)
+
+#define MAKE_VALUE(reg_offset, bit_num) (((reg_offset) << 16) | (bit_num & 0x1f))
+
+#define PERIPH_REG(periph_base, value) REG32((periph_base + (value >> 16)))
+#define PERIPH_REG_BIT(value) (0x1u << (value & 0x1f))
+
+/**
+ * @}
+ */
+
+
+
+
+
+/** @addtogroup Peripheral_registers_structures
+ * @{
+ */
+
+/* ================================================================================ */
+/* ================ ACC ================ */
+/* ================================================================================ */
+
+
+/**
+ * @brief HSI Auto Clock Calibration (ACC)
+ */
+
+typedef struct
+{ /*!< ACC Structure */
+ __IO uint32_t STS; /*!< status register */
+ __IO uint32_t CTRL1; /*!< control register 1 */
+ __IO uint32_t CTRL2; /*!< control register 2 */
+ __IO uint32_t CC1; /*!< compare value 1 */
+ __IO uint32_t CC2; /*!< compare value 2 */
+ __IO uint32_t CC3; /*!< compare value 3 */
+} ACC_TypeDef;
+
+
+/* ================================================================================ */
+/* ================ ADC ================ */
+/* ================================================================================ */
+
+
+/**
+ * @brief Analog to digital converter (ADC)
+ */
+
+typedef struct
+{ /*!< ADC Structure */
+ __IO uint32_t STS; /*!< status register */
+ __IO uint32_t CTRL1; /*!< control register 1 */
+ __IO uint32_t CTRL2; /*!< control register 2 */
+ __IO uint32_t SPT1; /*!< sample time register 1 */
+ __IO uint32_t SPT2; /*!< sample time register 2 */
+ __IO uint32_t PCDTO1; /*!< Preempted channel 1 data offset register */
+ __IO uint32_t PCDTO2; /*!< Preempted channel 2 data offset register */
+ __IO uint32_t PCDTO3; /*!< Preempted channel 3 data offset register */
+ __IO uint32_t PCDTO4; /*!< Preempted channel 4 data offset register */
+ __IO uint32_t VMHB; /*!< Voltage monitoring high boundary register */
+ __IO uint32_t VMLB; /*!< Voltage monitoring low boundary register */
+ __IO uint32_t OSQ1; /*!< Ordinary sequence register 1 */
+ __IO uint32_t OSQ2; /*!< Ordinary sequence register 2 */
+ __IO uint32_t OSQ3; /*!< Ordinary sequence register 3 */
+ __IO uint32_t PSQ; /*!< Preempted sequence register */
+ __IO uint32_t PDT1; /*!< Preempted data register 1 */
+ __IO uint32_t PDT2; /*!< Preempted data register 2 */
+ __IO uint32_t PDT3; /*!< Preempted data register 3 */
+ __IO uint32_t PDT4; /*!< Preempted data register 4 */
+ __IO uint32_t ODT; /*!< Ordinary data register */
+ __IO uint32_t RESERVED0[12];
+ __IO uint32_t OVSP; /*!< oversampling register */
+} ADC_TypeDef;
+
+
+/* ================================================================================ */
+/* ================ ADCCOM ================ */
+/* ================================================================================ */
+
+
+/**
+ * @brief ADC common area (ADCCOM)
+ */
+
+typedef struct
+{ /*!< ADCCOM Structure */
+ __IO uint32_t RESERVED0;
+ __IO uint32_t CCTRL; /*!< Common control register */
+} ADCCOM_TypeDef;
+
+
+/* ================================================================================ */
+/* ================ CAN ================ */
+/* ================================================================================ */
+
+
+/**
+ * @brief Controller Area Network (CAN)
+ */
+/**
+ * @brief Controller Area Network TX Mailbox Registers
+ */
+
+typedef struct
+{
+ __IO uint32_t TMI; /*!< Transmit mailbox identifier register */
+ __IO uint32_t TMC; /*!< Transmit mailbox data length and time stamp register */
+ __IO uint32_t TMDTL; /*!< Transmit mailbox low byte data register */
+ __IO uint32_t TMDTH; /*!< Transmit mailbox high byte data register */
+} CAN_TxMailBox_TypeDef;
+
+/**
+ * @brief Controller Area Network FIFO Mailbox Registers
+ */
+
+typedef struct
+{
+ __IO uint32_t RFI; /*!< Receive FIFO register */
+ __IO uint32_t RFC; /*!< Receive FIFO data length and time stamp register */
+ __IO uint32_t RFDTL; /*!< Receive FIFO low byte data register */
+ __IO uint32_t RFDTH; /*!< Receive FIFO high byte data register */
+} CAN_FIFOMailBox_TypeDef;
+
+/**
+ * @brief Controller Area Network Filter Registers
+ */
+
+typedef struct
+{
+ __IO uint32_t FFB1; /*!< Filter bank filtrate bit register 1 */
+ __IO uint32_t FFB2; /*!< Filter bank filtrate bit register 2 */
+} CAN_FilterRegister_TypeDef;
+
+/**
+ * @brief Controller Area Network
+ */
+
+typedef struct
+{ /*!< CAN Structure */
+ __IO uint32_t MCTRL; /*!< Main control register */
+ __IO uint32_t MSTS; /*!< Main status register */
+ __IO uint32_t TSTS; /*!< Transmit status register */
+ __IO uint32_t RF0; /*!< Receive FIFO 0 register */
+ __IO uint32_t RF1; /*!< Receive FIFO 1 register */
+ __IO uint32_t INTEN; /*!< Interrupt enable register */
+ __IO uint32_t ESTS; /*!< Error status register */
+ __IO uint32_t BTMG; /*!< Bit timing register */
+ __IO uint32_t RESERVED0[88];
+ CAN_TxMailBox_TypeDef sTxMailBox[3]; /*!< Transmit mailbox registers */
+ CAN_FIFOMailBox_TypeDef sFIFOMailBox[2]; /*!< Receive FIFO registers */
+ __IO uint32_t RESERVED1[12];
+ __IO uint32_t FCTRL; /*!< Filter control register */
+ __IO uint32_t FMCFG; /*!< Filter mode config register */
+ __IO uint32_t RESERVED2;
+ __IO uint32_t FBWCFG; /*!< Filter bit width config register */
+ __IO uint32_t RESERVED3;
+ __IO uint32_t FRF; /*!< Filter related FIFO register */
+ __IO uint32_t RESERVED4;
+ __IO uint32_t FACFG; /*!< Filter activate configuration register */
+ __IO uint32_t RESERVED5[8];
+ CAN_FilterRegister_TypeDef sFilterRegister[14]; /*!< Filter registers */
+} CAN_TypeDef;
+
+
+/* ================================================================================ */
+/* ================ CRC ================ */
+/* ================================================================================ */
+
+
+/**
+ * @brief CRC calculation unit (CRC)
+ */
+
+typedef struct
+{ /*!< CRC Structure */
+ __IO uint32_t DT; /*!< Data register */
+ __IO uint32_t CDT; /*!< Common data register */
+ __IO uint32_t CTRL; /*!< Control register */
+ __IO uint32_t RESERVED0;
+ __IO uint32_t IDT; /*!< Initial data register */
+ __IO uint32_t POLY; /*!< Polynomial coefficient register */
+} CRC_TypeDef;
+
+
+/* ================================================================================ */
+/* ================ CRM ================ */
+/* ================================================================================ */
+
+
+/**
+ * @brief Clock and reset management (CRM)
+ */
+
+typedef struct
+{ /*!< CRM Structure */
+ __IO uint32_t CTRL; /*!< Clock control register */
+ __IO uint32_t PLLCFG; /*!< PLL configuration register (CRM_PLLCFG) */
+ __IO uint32_t CFG; /*!< Clock configuration register(CRM_CFG) */
+ __IO uint32_t CLKINT; /*!< Clock interrupt register (CRM_CLKINT) */
+ __IO uint32_t AHBRST1; /*!< AHB peripheral reset register1 (CRM_AHBRST1) */
+ __IO uint32_t AHBRST2; /*!< AHB peripheral reset register 2 (CRM_AHBRST2) */
+ __IO uint32_t AHBRST3; /*!< AHB peripheral reset register 3 (CRM_AHBRST3) */
+ __IO uint32_t RESERVED0;
+ __IO uint32_t APB1RST; /*!< APB1 peripheral reset register (CRM_APB1RST) */
+ __IO uint32_t APB2RST; /*!< APB2 peripheral reset register (CRM_APB2RST) */
+ __IO uint32_t RESERVED1[2];
+ __IO uint32_t AHBEN1; /*!< AHB Peripheral Clock enable register 1 (CRM_AHBEN1) */
+ __IO uint32_t AHBEN2; /*!< AHB peripheral clock enable register 2 (CRM_AHBEN2) */
+ __IO uint32_t AHBEN3; /*!< AHB peripheral clock enable register 3 (CRM_AHBEN3) */
+ __IO uint32_t RESERVED2;
+ __IO uint32_t APB1EN; /*!< APB1 peripheral clock enable register (CRM_APB1EN) */
+ __IO uint32_t APB2EN; /*!< APB2 peripheral clock enable register (CRM_APB2EN) */
+ __IO uint32_t RESERVED3[2];
+ __IO uint32_t AHBLPEN1; /*!< AHB Low-power Peripheral Clock enable register 1 (CRM_AHBLPEN1) */
+ __IO uint32_t AHBLPEN2; /*!< AHB peripheral Low-power clock enable register 2 (CRM_AHBLPEN2) */
+ __IO uint32_t AHBLPEN3; /*!< AHB peripheral Low-power clock enable register 3 (CRM_AHBLPEN3) */
+ __IO uint32_t RESERVED4;
+ __IO uint32_t APB1LPEN; /*!< APB1 peripheral Low-power clock enable register (CRM_APB1LPEN) */
+ __IO uint32_t APB2LPEN; /*!< APB2 peripheral Low-power clock enable register (CRM_APB2LPEN) */
+ __IO uint32_t RESERVED5[2];
+ __IO uint32_t BPDC; /*!< Battery powered domain control register (CRM_BPDC) */
+ __IO uint32_t CTRLSTS; /*!< Control/status register (CRM_CTRLSTS) */
+ __IO uint32_t OTGHS; /*!< OTGHS register */
+ __IO uint32_t RESERVED6[9];
+ __IO uint32_t MISC1; /*!< Miscellaneous register1 */
+ __IO uint32_t MISC2; /*!< Miscellaneous register2 */
+} CRM_TypeDef;
+
+
+/* ================================================================================ */
+/* ================ DEBUG ================ */
+/* ================================================================================ */
+
+
+/**
+ * @brief Debug support (DEBUG)
+ */
+
+typedef struct
+{ /*!< DEBUG Structure */
+ __IO uint32_t IDCODE; /*!< DEBUG IDCODE */
+ __IO uint32_t CTRL; /*!< DEBUG CTRL */
+ __IO uint32_t APB1_PAUSE; /*!< DEBUG APB1 PAUSE */
+ __IO uint32_t APB2_PAUSE; /*!< DEBUG APB2 PAUSE */
+ __IO uint32_t RESERVED0[4];
+ __IO uint32_t SER_ID; /*!< SERIES ID */
+} DEBUG_TypeDef;
+
+
+/* ================================================================================ */
+/* ================ DMA ================ */
+/* ================================================================================ */
+
+
+/**
+ * @brief DMA controller (DMA)
+ */
+
+typedef struct
+{ /*!< DMA Structure */
+ __IO uint32_t STS; /*!< DMA interrupt status register (DMA_STS) */
+ __IO uint32_t CLR; /*!< DMA interrupt flag clear register (DMA_CLR) */
+ __IO uint32_t RESERVED1[62];
+ __IO uint32_t MUXSEL; /*!< DMAMUX Table Selection */
+ __IO uint32_t RESERVED2[11];
+ __IO uint32_t MUXSYNCSTS; /*!< Channel Interrupt Status Register */
+ __IO uint32_t MUXSYNCCLR; /*!< Channel Interrupt Clear Flag Register */
+ __IO uint32_t MUXGSTS; /*!< Generator Interrupt Status Register */
+ __IO uint32_t MUXGCLR; /*!< Generator Interrupt Clear Flag Register */
+} DMA_TypeDef;
+
+
+/* ================================================================================ */
+/* ================ DMA Channel ================ */
+/* ================================================================================ */
+
+
+/**
+ * @brief DMA controller Channel(DMA Channel)
+ */
+typedef struct
+{ /*!< DMA Channel Structure */
+ __IO uint32_t CTRL; /*!< DMA channel configuration register */
+ __IO uint32_t DTCNT; /*!< DMA channel number of data to transfer register */
+ __IO uint32_t PADDR; /*!< DMA channel peripheral base address register */
+ __IO uint32_t MADDR; /*!< DMA channel memory base address register */
+} DMA_Channel_TypeDef;
+
+
+/* ================================================================================ */
+/* ================ DMA MUX ================ */
+/* ================================================================================ */
+
+
+/**
+ * @brief DMA MUX controller
+ */
+typedef struct
+{
+ __IO uint32_t MUXCTRL; /*!< Channel Configuration Register */
+
+} DMAMUX_Channel_TypeDef;
+
+
+/* ================================================================================ */
+/* ================ DMA Generator ================ */
+/* ================================================================================ */
+
+
+/**
+ * @brief DMA MUX Generator Configuration
+ */
+typedef struct
+{
+ __IO uint32_t GCTRL; /*!< Generator Configuration Register */
+
+} DMAMUX_Generator_TypeDef;
+
+
+/* ================================================================================ */
+/* ================ ERTC ================ */
+/* ================================================================================ */
+
+
+/**
+ * @brief Real-time clock (ERTC)
+ */
+
+typedef struct
+{ /*!< ERTC Structure */
+ __IO uint32_t TIME; /*!< time register */
+ __IO uint32_t DATE; /*!< date register */
+ __IO uint32_t CTRL; /*!< control register */
+ __IO uint32_t STS; /*!< initialization and status register */
+ __IO uint32_t DIV; /*!< Diveder register */
+ __IO uint32_t WAT; /*!< Wakeup timer register */
+ __IO uint32_t CCAL; /*!< Calibration register */
+ __IO uint32_t ALA; /*!< Alarm A register */
+ __IO uint32_t ALB; /*!< Alarm B register */
+ __IO uint32_t WP; /*!< write protection register */
+ __IO uint32_t SBS; /*!< sub second register */
+ __IO uint32_t TADJ; /*!< time adjust register */
+ __IO uint32_t TSTM; /*!< time stamp time register */
+ __IO uint32_t TSDT; /*!< timestamp date register */
+ __IO uint32_t TSSBS; /*!< timestamp sub second register */
+ __IO uint32_t SCAL; /*!< calibration register */
+ __IO uint32_t TAMP; /*!< tamper and alternate function configuration register */
+ __IO uint32_t ALASBS; /*!< alarm A sub second register */
+ __IO uint32_t ALBSBS; /*!< alarm B sub second register */
+ __IO uint32_t RESERVED0;
+ __IO uint32_t BPR1; /*!< Battery powered domain register */
+ __IO uint32_t BPR2; /*!< Battery powered domain register */
+ __IO uint32_t BPR3; /*!< Battery powered domain register */
+ __IO uint32_t BPR4; /*!< Battery powered domain register */
+ __IO uint32_t BPR5; /*!< Battery powered domain register */
+ __IO uint32_t BPR6; /*!< Battery powered domain register */
+ __IO uint32_t BPR7; /*!< Battery powered domain register */
+ __IO uint32_t BPR8; /*!< Battery powered domain register */
+ __IO uint32_t BPR9; /*!< Battery powered domain register */
+ __IO uint32_t BPR10; /*!< Battery powered domain register */
+ __IO uint32_t BPR11; /*!< Battery powered domain register */
+ __IO uint32_t BPR12; /*!< Battery powered domain register */
+ __IO uint32_t BPR13; /*!< Battery powered domain register */
+ __IO uint32_t BPR14; /*!< Battery powered domain register */
+ __IO uint32_t BPR15; /*!< Battery powered domain register */
+ __IO uint32_t BPR16; /*!< Battery powered domain register */
+ __IO uint32_t BPR17; /*!< Battery powered domain register */
+ __IO uint32_t BPR18; /*!< Battery powered domain register */
+ __IO uint32_t BPR19; /*!< Battery powered domain register */
+ __IO uint32_t BPR20; /*!< Battery powered domain register */
+} ERTC_TypeDef;
+
+
+/* ================================================================================ */
+/* ================ EXINT ================ */
+/* ================================================================================ */
+
+
+/**
+ * @brief External Interrupt/Event Controller
+ */
+
+typedef struct
+{ /*!< EXINT Structure */
+ __IO uint32_t INTEN; /*!< Interrupt enable register */
+ __IO uint32_t EVTEN; /*!< Event enable register */
+ __IO uint32_t POLCFG1; /*!< Rising polarity configuration register */
+ __IO uint32_t POLCFG2; /*!< Falling polarity configuration register */
+ __IO uint32_t SWTRG; /*!< Software triggle register */
+ __IO uint32_t INTSTS; /*!< Interrupt status register */
+} EXINT_TypeDef;
+
+
+/* ================================================================================ */
+/* ================ FLASH ================ */
+/* ================================================================================ */
+
+
+/**
+ * @brief Flash memory controler (FLASH)
+ */
+
+typedef struct
+{ /*!< FLASH Structure */
+ __IO uint32_t PSR; /*!< Performance selection register */
+ __IO uint32_t UNLOCK; /*!< Unlock register */
+ __IO uint32_t USD_UNLOCK; /*!< USD unlock register */
+ __IO uint32_t STS; /*!< Status register */
+ __IO uint32_t CTRL; /*!< Control register */
+ __IO uint32_t ADDR; /*!< Address register */
+ __IO uint32_t RESERVED0;
+ __IO uint32_t USD; /*!< User system data register */
+ __IO uint32_t EPPS; /*!< Erase/program protection status register */
+ __IO uint32_t RESERVED1[20];
+ __IO uint32_t SLIB_STS0; /*!< sLib status 0 register */
+ __IO uint32_t SLIB_STS1; /*!< sLib status 1 register */
+ __IO uint32_t SLIB_PWD_CLR; /*!< SLIB password clear register */
+ __IO uint32_t SLIB_MISC_STS; /*!< sLib misc status register */
+ __IO uint32_t CRC_ADDR; /*!< Flash CRC data start address register */
+ __IO uint32_t CRC_CTRL; /*!< Flash CRC controll register */
+ __IO uint32_t CRC_CHKR; /*!< FLASH CRC check result register */
+ __IO uint32_t RESERVED2[52];
+ __IO uint32_t SLIB_SET_PWD; /*!< sLib password setting register */
+ __IO uint32_t SLIB_SET_RANGE; /*!< Configure sLib range register */
+ __IO uint32_t EM_SLIB_SET; /*!< Extension momery slib set register */
+ __IO uint32_t BTM_MODE_SET; /*!< Boot memory mode setting register */
+ __IO uint32_t SLIB_UNLOCK; /*!< sLib unlock register */
+} FLASH_TypeDef;
+
+
+/* ================================================================================ */
+/* ================ GPIO ================ */
+/* ================================================================================ */
+
+
+/**
+ * @brief General purpose I/Os (GPIO)
+ */
+
+typedef struct
+{ /*!< GPIO Structure */
+ __IO uint32_t CFGR; /*!< GPIO configuration register */
+ __IO uint32_t OMODE; /*!< GPIO output mode register */
+ __IO uint32_t ODRVR; /*!< GPIO drive capability register */
+ __IO uint32_t PULL; /*!< GPIO pull-up/pull-down register */
+ __IO uint32_t IDT; /*!< GPIO input data register */
+ __IO uint32_t ODT; /*!< GPIO output data register */
+ __IO uint32_t SCR; /*!< Port bit set/clear register */
+ __IO uint32_t WPR; /*!< Port write protect register */
+ __IO uint32_t MUXL; /*!< GPIO muxing function low register */
+ __IO uint32_t MUXH; /*!< GPIO muxing function high register */
+ __IO uint32_t CLR; /*!< GPIO bit reset register */
+ __IO uint32_t TOGR; /*!< GPIO bit toggle register */
+ __IO uint32_t RESERVED0[3];
+ __IO uint32_t HDRV; /*!< Huge current driver */
+ __IO uint32_t SRCTR;
+} GPIO_TypeDef;
+
+
+/* ================================================================================ */
+/* ================ I2C ================ */
+/* ================================================================================ */
+
+
+/**
+ * @brief Inter-integrated circuit (I2C)
+ */
+
+typedef struct
+{ /*!< I2C Structure */
+ __IO uint32_t CTRL1; /*!< Control register 1 */
+ __IO uint32_t CTRL2; /*!< Control register 2 */
+ __IO uint32_t OADDR1; /*!< Own address register 1 */
+ __IO uint32_t OADDR2; /*!< Own address register 2 */
+ __IO uint32_t CLKCTRL; /*!< Clock contorl register */
+ __IO uint32_t TIMEOUT; /*!< Timeout register */
+ __IO uint32_t STS; /*!< Interrupt and Status register */
+ __IO uint32_t CLR; /*!< Interrupt clear register */
+ __IO uint32_t PEC; /*!< PEC register */
+ __IO uint32_t RXDT; /*!< Receive data register */
+ __IO uint32_t TXDT; /*!< Transmit data register */
+} I2C_TypeDef;
+
+
+/* ================================================================================ */
+/* ================ PWC ================ */
+/* ================================================================================ */
+
+
+/**
+ * @brief Power control (PWC)
+ */
+
+typedef struct
+{ /*!< PWC Structure */
+ __IO uint32_t CTRL; /*!< Power control register (PWC_CTRL) */
+ __IO uint32_t CTRLSTS; /*!< Power control and status register (PWC_CTRLSTS) */
+ __IO uint32_t RESERVED0[2];
+ __IO uint32_t LDOOV; /*!< LDO output voltage register */
+} PWC_TypeDef;
+
+
+/* ================================================================================ */
+/* ================ QSPI ================ */
+/* ================================================================================ */
+
+
+/**
+ * @brief Quad SPI Controller (QSPI)
+ */
+
+typedef struct
+{ /*!< QSPI Structure */
+ __IO uint32_t CMD_W0; /*!< Command word 0 */
+ __IO uint32_t CMD_W1; /*!< Command word 1 */
+ __IO uint32_t CMD_W2; /*!< Command word 2 */
+ __IO uint32_t CMD_W3; /*!< Command word 3 */
+ __IO uint32_t CTRL; /*!< Control register */
+ __IO uint32_t RESERVED0;
+ __IO uint32_t FIFOSTS; /*!< FIFO Status register */
+ __IO uint32_t RESERVED1;
+ __IO uint32_t CTRL2; /*!< control register 2 */
+ __IO uint32_t CMDSTS; /*!< CMD status register */
+ __IO uint32_t RSTS; /*!< SPI read status register */
+ __IO uint32_t FSIZE; /*!< SPI flash size */
+ __IO uint32_t XIP_CMD_W0; /*!< XIP command word 0 */
+ __IO uint32_t XIP_CMD_W1; /*!< XIP command word 1 */
+ __IO uint32_t XIP_CMD_W2; /*!< XIP command word 2 */
+ __IO uint32_t XIP_CMD_W3; /*!< XIP command word 3 */
+ __IO uint32_t CTRL3; /*!< control register 3 */
+ __IO uint32_t RESERVED2[3];
+ __IO uint32_t REV; /*!< Revision */
+ __IO uint32_t RESERVED3[43];
+ __IO uint32_t DT; /*!< 32/16/8 bit data port register */
+} QSPI1_TypeDef;
+
+
+/* ================================================================================ */
+/* ================ SCFG ================ */
+/* ================================================================================ */
+
+
+/**
+ * @brief System configuration controller (SCFG)
+ */
+
+typedef struct
+{ /*!< SCFG Structure */
+ __IO uint32_t CFG1; /*!< configuration register 1 */
+ __IO uint32_t CFG2; /*!< configuration register 2 */
+ __IO uint32_t EXINTC[4]; /*!< external interrupt configuration register 1,2,3,4 */
+ __IO uint32_t RESERVED0[5];
+ __IO uint32_t UHDRV; /*!< Ultra high drive register */
+} SCFG_TypeDef;
+
+
+/* ================================================================================ */
+/* ================ SPI ================ */
+/* ================================================================================ */
+
+
+/**
+ * @brief Serial peripheral interface (SPI)
+ */
+
+typedef struct
+{ /*!< SPI Structure */
+ __IO uint32_t CTRL1; /*!< control register 1 */
+ __IO uint32_t CTRL2; /*!< control register 2 */
+ __IO uint32_t STS; /*!< status register */
+ __IO uint32_t DT; /*!< data register */
+ __IO uint32_t CPOLY; /*!< CRC polynomial register */
+ __IO uint32_t RCRC; /*!< Receive CRC register */
+ __IO uint32_t TCRC; /*!< Transmit CRC register */
+ __IO uint32_t I2SCTRL; /*!< I2S control register */
+ __IO uint32_t I2SCLK; /*!< I2S clock register */
+ __IO uint32_t RESERVED1[3];
+ __IO uint32_t MISC1; /*!< I2S additional register */
+} SPI_TypeDef;
+
+
+/* ================================================================================ */
+/* ================ TMR ================ */
+/* ================================================================================ */
+
+
+/**
+ * @brief timer (TMR)
+ */
+
+typedef struct
+{ /*!< TMR Structure */
+ __IO uint32_t CTRL1; /*!< Control register 1 */
+ __IO uint32_t CTRL2; /*!< Control register 2 */
+ __IO uint32_t STCTRL; /*!< Subordinate TMR control register */
+ __IO uint32_t IDEN; /*!< Interrupt/DMA enable register */
+ __IO uint32_t ISTS; /*!< Interrupt status register */
+ __IO uint32_t SWEVT; /*!< Software event register */
+ __IO uint32_t CM1; /*!< Channel mode register 1 */
+ __IO uint32_t CM2; /*!< Channel mode register 2 */
+ __IO uint32_t CCTRL; /*!< Channel control register */
+ __IO uint32_t CVAL; /*!< Counter value */
+ __IO uint32_t DIV; /*!< Divider value */
+ __IO uint32_t PR; /*!< Period value */
+ __IO uint32_t RPR; /*!< Repetition of period value */
+ __IO uint32_t C1DT; /*!< Channel 1 data register */
+ __IO uint32_t C2DT; /*!< Channel 2 data register */
+ __IO uint32_t C3DT; /*!< Channel 3 data register */
+ __IO uint32_t C4DT; /*!< Channel 4 data register */
+ __IO uint32_t BRK; /*!< Brake register */
+ __IO uint32_t DMACTRL; /*!< DMA control register */
+ __IO uint32_t DMADT; /*!< DMA data register */
+ __IO uint32_t RMP; /*!< TMR input remap register */
+ __IO uint32_t RESERVED0[7];
+ __IO uint32_t CM3; /*!< Channel output mode register */
+ __IO uint32_t C5DT; /*!< Channel 5 data register */
+} TMR_TypeDef;
+
+
+/* ================================================================================ */
+/* ================ USART ================ */
+/* ================================================================================ */
+
+
+/**
+ * @brief Universal synchronous asynchronous receiver transmitter (USART)
+ */
+
+typedef struct
+{ /*!< USART Structure */
+ __IO uint32_t STS; /*!< Status register */
+ __IO uint32_t DT; /*!< Data register */
+ __IO uint32_t BAUDR; /*!< Baud rate register */
+ __IO uint32_t CTRL1; /*!< Control register 1 */
+ __IO uint32_t CTRL2; /*!< Control register 2 */
+ __IO uint32_t CTRL3; /*!< Control register 3 */
+ __IO uint32_t GDIV; /*!< Guard time and division register */
+ __IO uint32_t RTOV; /*!< Receiver time out value register */
+ __IO uint32_t IFC; /*!< Interruption flag clear register */
+} USART_TypeDef;
+
+
+/* ================================================================================ */
+/* ================ WDT ================ */
+/* ================================================================================ */
+
+
+/**
+ * @brief Watchdog (WDT)
+ */
+
+typedef struct
+{ /*!< WDT Structure */
+ __IO uint32_t CMD; /*!< Command register */
+ __IO uint32_t DIV; /*!< Division register */
+ __IO uint32_t RLD; /*!< Reload register */
+ __IO uint32_t STS; /*!< Status register */
+ __IO uint32_t WIN; /*!< Window register */
+} WDT_TypeDef;
+
+
+
+/* ================================================================================ */
+/* ================ WWDT ================ */
+/* ================================================================================ */
+
+
+/**
+ * @brief Window watchdog (WWDT)
+ */
+
+typedef struct
+{ /*!< WWDT Structure */
+ __IO uint32_t CTRL; /*!< Control register */
+ __IO uint32_t CFG; /*!< Configuration register */
+ __IO uint32_t STS; /*!< Status register */
+} WWDT_TypeDef;
+
+
+/**
+ * @}
+ */
+
+/** @addtogroup Peripheral_memory_map
+ * @{
+ */
+
+#define QSPI2_MEM_BASE ((uint32_t)0xB0000000)
+#define QSPI2_REG_BASE ((uint32_t)0xA0002000)
+#define QSPI1_REG_BASE ((uint32_t)0xA0001000)
+#define QSPI1_MEM_BASE ((uint32_t)0x90000000)
+#define PERIPH_BASE ((uint32_t)0x40000000)
+#define SRAM_BB_BASE ((uint32_t)0x22000000)
+#define PERIPH_BB_BASE ((uint32_t)0x42000000)
+#define SRAM_BASE ((uint32_t)0x20000000)
+#define USD_BASE ((uint32_t)0x1FFFF800)
+#define FLASH_BASE ((uint32_t)0x08000000)
+
+#define DEBUG_BASE ((uint32_t)0xE0042000)
+
+#define APB1PERIPH_BASE (PERIPH_BASE)
+#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
+#define AHBPERIPH1_BASE (PERIPH_BASE + 0x20000)
+#define AHBPERIPH2_BASE (PERIPH_BASE + 0x10000000)
+
+/* apb1 bus base address */
+#define UART8_BASE (APB1PERIPH_BASE + 0x7C00)
+#define UART7_BASE (APB1PERIPH_BASE + 0x7800)
+#define PWC_BASE (APB1PERIPH_BASE + 0x7000)
+#define CAN1_BASE (APB1PERIPH_BASE + 0x6400)
+#define I2C3_BASE (APB1PERIPH_BASE + 0x5C00)
+#define I2C2_BASE (APB1PERIPH_BASE + 0x5800)
+#define I2C1_BASE (APB1PERIPH_BASE + 0x5400)
+#define USART5_BASE (APB1PERIPH_BASE + 0x5000)
+#define USART4_BASE (APB1PERIPH_BASE + 0x4C00)
+#define USART3_BASE (APB1PERIPH_BASE + 0x4800)
+#define USART2_BASE (APB1PERIPH_BASE + 0x4400)
+#define SPI3_BASE (APB1PERIPH_BASE + 0x3C00)
+#define SPI2_BASE (APB1PERIPH_BASE + 0x3800)
+#define WDT_BASE (APB1PERIPH_BASE + 0x3000)
+#define WWDT_BASE (APB1PERIPH_BASE + 0x2C00)
+#define ERTC_BASE (APB1PERIPH_BASE + 0x2800)
+#define TMR14_BASE (APB1PERIPH_BASE + 0x2000)
+#define TMR13_BASE (APB1PERIPH_BASE + 0x1C00)
+#define TMR7_BASE (APB1PERIPH_BASE + 0x1400)
+#define TMR6_BASE (APB1PERIPH_BASE + 0x1000)
+#define TMR4_BASE (APB1PERIPH_BASE + 0x0800)
+#define TMR3_BASE (APB1PERIPH_BASE + 0x0400)
+#define TMR2_BASE (APB1PERIPH_BASE + 0x0000)
+/* apb2 bus base address */
+#define OTGHS_PHY_BASE (APB2PERIPH_BASE + 0x7C00)
+#define ACC_BASE (APB2PERIPH_BASE + 0x7400)
+#define I2SF5_BASE (APB2PERIPH_BASE + 0x5000)
+#define TMR11_BASE (APB2PERIPH_BASE + 0x4800)
+#define TMR10_BASE (APB2PERIPH_BASE + 0x4400)
+#define TMR9_BASE (APB2PERIPH_BASE + 0x4000)
+#define EXINT_BASE (APB2PERIPH_BASE + 0x3C00)
+#define SCFG_BASE (APB2PERIPH_BASE + 0x3800)
+#define SPI1_BASE (APB2PERIPH_BASE + 0x3000)
+#define ADC1_BASE (APB2PERIPH_BASE + 0x2000)
+#define ADCCOM_BASE (APB2PERIPH_BASE + 0x2300)
+#define USART6_BASE (APB2PERIPH_BASE + 0x1400)
+#define USART1_BASE (APB2PERIPH_BASE + 0x1000)
+#define TMR1_BASE (APB2PERIPH_BASE + 0x0000)
+/* ahb bus base address */
+#define GPIOF_BASE (AHBPERIPH1_BASE + 0x1400)
+#define GPIOD_BASE (AHBPERIPH1_BASE + 0x0C00)
+#define GPIOC_BASE (AHBPERIPH1_BASE + 0x0800)
+#define GPIOB_BASE (AHBPERIPH1_BASE + 0x0400)
+#define GPIOA_BASE (AHBPERIPH1_BASE + 0x0000)
+
+#define DMA1_BASE (AHBPERIPH1_BASE + 0x6000)
+#define DMA1_CHANNEL1_BASE (DMA1_BASE + 0x0008)
+#define DMA1_CHANNEL2_BASE (DMA1_BASE + 0x001C)
+#define DMA1_CHANNEL3_BASE (DMA1_BASE + 0x0030)
+#define DMA1_CHANNEL4_BASE (DMA1_BASE + 0x0044)
+#define DMA1_CHANNEL5_BASE (DMA1_BASE + 0x0058)
+#define DMA1_CHANNEL6_BASE (DMA1_BASE + 0x006C)
+#define DMA1_CHANNEL7_BASE (DMA1_BASE + 0x0080)
+
+#define DMA1MUX_BASE (DMA1_BASE + 0x0104)
+#define DMA1MUX_CHANNEL1_BASE (DMA1MUX_BASE)
+#define DMA1MUX_CHANNEL2_BASE (DMA1MUX_BASE + 0x0004)
+#define DMA1MUX_CHANNEL3_BASE (DMA1MUX_BASE + 0x0008)
+#define DMA1MUX_CHANNEL4_BASE (DMA1MUX_BASE + 0x000C)
+#define DMA1MUX_CHANNEL5_BASE (DMA1MUX_BASE + 0x0010)
+#define DMA1MUX_CHANNEL6_BASE (DMA1MUX_BASE + 0x0014)
+#define DMA1MUX_CHANNEL7_BASE (DMA1MUX_BASE + 0x0018)
+
+#define DMA1MUX_GENERATOR1_BASE (DMA1_BASE + 0x0120)
+#define DMA1MUX_GENERATOR2_BASE (DMA1_BASE + 0x0124)
+#define DMA1MUX_GENERATOR3_BASE (DMA1_BASE + 0x0128)
+#define DMA1MUX_GENERATOR4_BASE (DMA1_BASE + 0x012C)
+
+#define DMA2_BASE (AHBPERIPH1_BASE + 0x6400)
+#define DMA2_CHANNEL1_BASE (DMA2_BASE + 0x0008)
+#define DMA2_CHANNEL2_BASE (DMA2_BASE + 0x001C)
+#define DMA2_CHANNEL3_BASE (DMA2_BASE + 0x0030)
+#define DMA2_CHANNEL4_BASE (DMA2_BASE + 0x0044)
+#define DMA2_CHANNEL5_BASE (DMA2_BASE + 0x0058)
+#define DMA2_CHANNEL6_BASE (DMA2_BASE + 0x006C)
+#define DMA2_CHANNEL7_BASE (DMA2_BASE + 0x0080)
+
+#define DMA2MUX_BASE (DMA2_BASE + 0x0104)
+#define DMA2MUX_CHANNEL1_BASE (DMA2MUX_BASE)
+#define DMA2MUX_CHANNEL2_BASE (DMA2MUX_BASE + 0x0004)
+#define DMA2MUX_CHANNEL3_BASE (DMA2MUX_BASE + 0x0008)
+#define DMA2MUX_CHANNEL4_BASE (DMA2MUX_BASE + 0x000C)
+#define DMA2MUX_CHANNEL5_BASE (DMA2MUX_BASE + 0x0010)
+#define DMA2MUX_CHANNEL6_BASE (DMA2MUX_BASE + 0x0014)
+#define DMA2MUX_CHANNEL7_BASE (DMA2MUX_BASE + 0x0018)
+
+#define DMA2MUX_GENERATOR1_BASE (DMA2_BASE + 0x0120)
+#define DMA2MUX_GENERATOR2_BASE (DMA2_BASE + 0x0124)
+#define DMA2MUX_GENERATOR3_BASE (DMA2_BASE + 0x0128)
+#define DMA2MUX_GENERATOR4_BASE (DMA2_BASE + 0x012C)
+
+#define FLASH_REG_BASE (AHBPERIPH1_BASE + 0x3C00)
+#define CRM_BASE (AHBPERIPH1_BASE + 0x3800)
+#define CRC_BASE (AHBPERIPH1_BASE + 0x3000)
+#define OTGHS_BASE (AHBPERIPH1_BASE + 0x20000)
+#define OTGFS1_BASE (AHBPERIPH2_BASE + 0x00000)
+
+/**
+ * @}
+ */
+
+
+/** @addtogroup Peripheral_instance
+ * @{
+ */
+
+#define EXINT ((EXINT_TypeDef *) EXINT_BASE)
+#define CRM ((CRM_TypeDef *) CRM_BASE)
+#define PWC ((PWC_TypeDef *) PWC_BASE)
+#define FLASH ((FLASH_TypeDef *) FLASH_REG_BASE)
+#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)
+#define GPIOB ((GPIO_TypeDef *) GPIOB_BASE)
+#define GPIOC ((GPIO_TypeDef *) GPIOC_BASE)
+#define GPIOD ((GPIO_TypeDef *) GPIOD_BASE)
+#define GPIOF ((GPIO_TypeDef *) GPIOF_BASE)
+#define SCFG ((SCFG_TypeDef *) SCFG_BASE)
+#define TMR1 ((TMR_TypeDef *) TMR1_BASE)
+#define TMR2 ((TMR_TypeDef *) TMR2_BASE)
+#define TMR3 ((TMR_TypeDef *) TMR3_BASE)
+#define TMR4 ((TMR_TypeDef *) TMR4_BASE)
+#define TMR6 ((TMR_TypeDef *) TMR6_BASE)
+#define TMR7 ((TMR_TypeDef *) TMR7_BASE)
+#define TMR9 ((TMR_TypeDef *) TMR9_BASE)
+#define TMR10 ((TMR_TypeDef *) TMR10_BASE)
+#define TMR11 ((TMR_TypeDef *) TMR11_BASE)
+#define TMR13 ((TMR_TypeDef *) TMR13_BASE)
+#define TMR14 ((TMR_TypeDef *) TMR14_BASE)
+#define DEBUGMCU ((DEBUG_TypeDef *) DEBUG_BASE)
+#define DEBUG ((DEBUG_TypeDef *) DEBUG_BASE)
+#define DMA1 ((DMA_TypeDef *) DMA1_BASE)
+#define DMA2 ((DMA_TypeDef *) DMA2_BASE)
+#define DMA1_CHANNEL1 ((DMA_Channel_TypeDef *) DMA1_CHANNEL1_BASE)
+#define DMA1_CHANNEL2 ((DMA_Channel_TypeDef *) DMA1_CHANNEL2_BASE)
+#define DMA1_CHANNEL3 ((DMA_Channel_TypeDef *) DMA1_CHANNEL3_BASE)
+#define DMA1_CHANNEL4 ((DMA_Channel_TypeDef *) DMA1_CHANNEL4_BASE)
+#define DMA1_CHANNEL5 ((DMA_Channel_TypeDef *) DMA1_CHANNEL5_BASE)
+#define DMA1_CHANNEL6 ((DMA_Channel_TypeDef *) DMA1_CHANNEL6_BASE)
+#define DMA1_CHANNEL7 ((DMA_Channel_TypeDef *) DMA1_CHANNEL7_BASE)
+#define DMA2_CHANNEL1 ((DMA_Channel_TypeDef *) DMA2_CHANNEL1_BASE)
+#define DMA2_CHANNEL2 ((DMA_Channel_TypeDef *) DMA2_CHANNEL2_BASE)
+#define DMA2_CHANNEL3 ((DMA_Channel_TypeDef *) DMA2_CHANNEL3_BASE)
+#define DMA2_CHANNEL4 ((DMA_Channel_TypeDef *) DMA2_CHANNEL4_BASE)
+#define DMA2_CHANNEL5 ((DMA_Channel_TypeDef *) DMA2_CHANNEL5_BASE)
+#define DMA2_CHANNEL6 ((DMA_Channel_TypeDef *) DMA2_CHANNEL6_BASE)
+#define DMA2_CHANNEL7 ((DMA_Channel_TypeDef *) DMA2_CHANNEL7_BASE)
+#define DMA1MUX_CHANNEL1 ((DMAMUX_Channel_TypeDef *) DMA1MUX_CHANNEL1_BASE)
+#define DMA1MUX_CHANNEL2 ((DMAMUX_Channel_TypeDef *) DMA1MUX_CHANNEL2_BASE)
+#define DMA1MUX_CHANNEL3 ((DMAMUX_Channel_TypeDef *) DMA1MUX_CHANNEL3_BASE)
+#define DMA1MUX_CHANNEL4 ((DMAMUX_Channel_TypeDef *) DMA1MUX_CHANNEL4_BASE)
+#define DMA1MUX_CHANNEL5 ((DMAMUX_Channel_TypeDef *) DMA1MUX_CHANNEL5_BASE)
+#define DMA1MUX_CHANNEL6 ((DMAMUX_Channel_TypeDef *) DMA1MUX_CHANNEL6_BASE)
+#define DMA1MUX_CHANNEL7 ((DMAMUX_Channel_TypeDef *) DMA1MUX_CHANNEL7_BASE)
+#define DMA2MUX_CHANNEL1 ((DMAMUX_Channel_TypeDef *) DMA2MUX_CHANNEL1_BASE)
+#define DMA2MUX_CHANNEL2 ((DMAMUX_Channel_TypeDef *) DMA2MUX_CHANNEL2_BASE)
+#define DMA2MUX_CHANNEL3 ((DMAMUX_Channel_TypeDef *) DMA2MUX_CHANNEL3_BASE)
+#define DMA2MUX_CHANNEL4 ((DMAMUX_Channel_TypeDef *) DMA2MUX_CHANNEL4_BASE)
+#define DMA2MUX_CHANNEL5 ((DMAMUX_Channel_TypeDef *) DMA2MUX_CHANNEL5_BASE)
+#define DMA2MUX_CHANNEL6 ((DMAMUX_Channel_TypeDef *) DMA2MUX_CHANNEL6_BASE)
+#define DMA2MUX_CHANNEL7 ((DMAMUX_Channel_TypeDef *) DMA2MUX_CHANNEL7_BASE)
+#define DMA1MUX_GENERATOR1 ((DMAMUX_Generator_TypeDef *) DMA1MUX_GENERATOR1_BASE)
+#define DMA1MUX_GENERATOR2 ((DMAMUX_Generator_TypeDef *) DMA1MUX_GENERATOR2_BASE)
+#define DMA1MUX_GENERATOR3 ((DMAMUX_Generator_TypeDef *) DMA1MUX_GENERATOR3_BASE)
+#define DMA1MUX_GENERATOR4 ((DMAMUX_Generator_TypeDef *) DMA1MUX_GENERATOR4_BASE)
+#define DMA2MUX_GENERATOR1 ((DMAMUX_Generator_TypeDef *) DMA2MUX_GENERATOR1_BASE)
+#define DMA2MUX_GENERATOR2 ((DMAMUX_Generator_TypeDef *) DMA2MUX_GENERATOR2_BASE)
+#define DMA2MUX_GENERATOR3 ((DMAMUX_Generator_TypeDef *) DMA2MUX_GENERATOR3_BASE)
+#define DMA2MUX_GENERATOR4 ((DMAMUX_Generator_TypeDef *) DMA2MUX_GENERATOR4_BASE)
+#define ADC1 ((ADC_TypeDef *) ADC1_BASE)
+#define ADCCOM ((ADCCOM_TypeDef *) ADCCOM_BASE)
+#define I2C1 ((I2C_TypeDef *) I2C1_BASE)
+#define I2C2 ((I2C_TypeDef *) I2C2_BASE)
+#define I2C3 ((I2C_TypeDef *) I2C3_BASE)
+#define USART1 ((USART_TypeDef *) USART1_BASE)
+#define USART2 ((USART_TypeDef *) USART2_BASE)
+#define USART3 ((USART_TypeDef *) USART3_BASE)
+#define UART4 ((USART_TypeDef *) USART4_BASE)
+#define UART5 ((USART_TypeDef *) USART5_BASE)
+#define USART6 ((USART_TypeDef *) USART6_BASE)
+#define UART7 ((USART_TypeDef *) UART7_BASE)
+#define UART8 ((USART_TypeDef *) UART8_BASE)
+#define SPI1 ((SPI_TypeDef *) SPI1_BASE)
+#define SPI2 ((SPI_TypeDef *) SPI2_BASE)
+#define SPI3 ((SPI_TypeDef *) SPI3_BASE)
+#define I2SF5 ((SPI_TypeDef *) I2SF5_BASE)
+#define ERTC ((ERTC_TypeDef *)ERTC_BASE)
+
+/**
+ * @}
+ */
+
+/** @defgroup FLASH_unlock_keys
+ * @brief flash unlock keys
+ * @{
+ */
+
+#define FLASH_UNLOCK_KEY1 ((uint32_t)0x45670123) /*!< flash operation unlock order key1 */
+#define FLASH_UNLOCK_KEY2 ((uint32_t)0xCDEF89AB) /*!< flash operation unlock order key2 */
+#define FAP_RELIEVE_KEY ((uint16_t)0x00A5) /*!< flash fap relieve key val */
+#define FAP_HIGH_LEVEL_KEY ((uint16_t)0x00CC) /*!< flash fap high level enable key val */
+#define SLIB_UNLOCK_KEY ((uint32_t)0xA35F6D24) /*!< flash slib operation unlock order key */
+
+#define FLASHSIZE_BASE ((uint32_t)0x1FFFF7E0U) /*!< FLASH Size register base address */
+#define UID_BASE ((uint32_t)0x1FFFF7E8U) /*!< Unique device ID register base address */
+
+/**
+ * @}
+ */
+
+
+/** @addtogroup Peripheral_Registers_Bits_Definition
+ * @{
+ */
+
+
+/* =========================================================================================================================== */
+/* ================ ADC ================ */
+/* =========================================================================================================================== */
+
+/****************** Bit definition for ADC_STS register ***************/
+#define ADC_STS_VMOR (0x1U << 0)
+#define ADC_STS_OCCC (0x1U << 1)
+#define ADC_STS_CCE (0x1U << 1)
+#define ADC_STS_PCCE (0x1U << 2)
+#define ADC_STS_PCCS (0x1U << 3)
+#define ADC_STS_OCCS (0x1U << 4)
+
+/****************** Bit definition for ADC_CTRL1 register ***************/
+#define ADC_CTRL1_CCEIEN (0x1U << 5)
+#define ADC_CTRL1_VMORIEN (0x1U << 6)
+#define ADC_CTRL1_PCCEIEN (0x1U << 7)
+#define ADC_CTRL1_SQEN (0x1U << 8)
+#define ADC_CTRL1_VMSGEN (0x1U << 9)
+#define ADC_CTRL1_PCAUTOEN (0x1U << 10)
+#define ADC_CTRL1_OCPEN (0x1U << 11)
+#define ADC_CTRL1_PCPEN (0x1U << 12)
+#define ADC_CTRL1_PCVMEN (0x1U << 22)
+#define ADC_CTRL1_OCVMEN (0x1U << 23)
+#define ADC_CTRL1_OCCOIE (0x1U << 26)
+
+/****************** Bit definition for ADC_CTRL2 register *******************/
+#define ADC_CTRL2_ADCEN (0x1U << 0)
+#define ADC_CTRL2_RPEN (0x1U << 1)
+#define ADC_CTRL2_ADCAL (0x1U << 2)
+#define ADC_CTRL2_ADCALINIT (0x1U << 3)
+#define ADC_CTRL2_OCDMAEN (0x1U << 8)
+#define ADC_CTRL2_DTALIGN (0x1U << 11)
+#define ADC_CTRL2_DTALIGN_R (0x0U << 11)
+#define ADC_CTRL2_DTALIGN_L (0x1U << 11)
+#define ADC_CTRL2_PCTEN (0x1U << 15)
+#define ADC_CTRL2_OCTEN (0x1U << 20)
+#define ADC_CTRL2_PCSWTRG (0x1U << 21)
+#define ADC_CTRL2_OCSWTRG (0x1U << 22)
+#define ADC_CTRL2_ITSRVEN (0x1U << 23)
+
+/****************** Bit definition for ADC_VMHB register ***************/
+#define ADC_VMHB_HB (0xFFFFU << 0)
+
+/****************** Bit definition for ADC_VMLB register ***************/
+#define ADC_VMLB_LB (0x0000U << 0)
+
+
+/* =========================================================================================================================== */
+/* ================ CRM ================ */
+/* =========================================================================================================================== */
+/****************** Bit definition for CRM_CTRL register *****************/
+#define CRM_CTRL_HICKEN (0x1U << 0)
+#define CRM_CTRL_HICKSTBL (0x1U << 1)
+#define CRM_CTRL_HICKTRIM (0x3FU << 2)
+#define CRM_CTRL_HEXTEN (0x1U << 16)
+#define CRM_CTRL_HEXTSTBL (0x1U << 17)
+#define CRM_CTRL_HEXTBYPS (0x1U << 18)
+#define CRM_CTRL_CFDEN (0x1U << 19)
+#define CRM_CTRL_PLLEN (0x1U << 24)
+#define CRM_CTRL_PLLSTBL (0x1U << 25)
+#define CRM_CTRL_PLLUSTBL (0x1U << 26)
+
+/****************** Bit definition for CRM_PLLCFG register *****************/
+#define CRM_PLLCFG_PLLUEN (0x1U << 29)
+#define CRM_PLLCFG_PLLRCS (0x1U << 30)
+
+/****************** Bit definition for CRM_CFG register ******************/
+#define CRM_CFG_SCLKSEL (0x3U << 0)
+#define CRM_CFG_SCLK_HICK (0x0U << 0)
+#define CRM_CFG_SCLK_HEXT (0x1U << 0)
+#define CRM_CFG_SCLK_PLL (0x2U << 0)
+#define CRM_CFG_SCLKSTS (0x3U << 2)
+#define CRM_CFG_SCLKSTS_HICK (0x0U << 2)
+#define CRM_CFG_SCLKSTS_HEXT (0x1U << 2)
+#define CRM_CFG_SCLKSTS_PLL (0x2U << 2)
+
+/***************** Bit definition for CRM_AHBRST1 register ***************/
+#define CRM_AHBRST1_GPIOARST (0x1U << 0)
+#define CRM_AHBRST1_GPIOBRST (0x1U << 1)
+#define CRM_AHBRST1_GPIOCRST (0x1U << 2)
+#define CRM_AHBRST1_GPIODRST (0x1U << 3)
+#define CRM_AHBRST1_GPIOFRST (0x1U << 5)
+#define CRM_AHBRST1_CRCRST (0x1U << 12)
+#define CRM_AHBRST1_DMA1RST (0x1U << 22)
+#define CRM_AHBRST1_DMA2RST (0x1U << 24)
+#define CRM_AHBRST1_OTGHSRST (0x1U << 29)
+
+/***************** Bit definition for CRM_AHBRST2 register ***************/
+#define CRM_AHBRST2_OTGFS1RST (0x1U << 7)
+
+/***************** Bit definition for CRM_AHBRST3 register ***************/
+#define CRM_AHBRST3_QSPI1RST (0x1U << 1)
+
+/***************** Bit definition for CRM_APB1RST register ***************/
+#define CRM_APB1RST_TMR2RST (0x1U << 0)
+#define CRM_APB1RST_TMR3RST (0x1U << 1)
+#define CRM_APB1RST_TMR4RST (0x1U << 2)
+#define CRM_APB1RST_TMR6RST (0x1U << 4)
+#define CRM_APB1RST_TMR7RST (0x1U << 5)
+#define CRM_APB1RST_TMR13RST (0x1U << 7)
+#define CRM_APB1RST_TMR14RST (0x1U << 8)
+#define CRM_APB1RST_WWDTRST (0x1U << 11)
+#define CRM_APB1RST_SPI2RST (0x1U << 14)
+#define CRM_APB1RST_SPI3RST (0x1U << 15)
+#define CRM_APB1RST_USART2RST (0x1U << 17)
+#define CRM_APB1RST_USART3RST (0x1U << 18)
+#define CRM_APB1RST_USART4RST (0x1U << 19)
+#define CRM_APB1RST_USART5RST (0x1U << 20)
+#define CRM_APB1RST_I2C1RST (0x1U << 21)
+#define CRM_APB1RST_I2C2RST (0x1U << 22)
+#define CRM_APB1RST_I2C3RST (0x1U << 23)
+#define CRM_APB1RST_CAN1RST (0x1U << 25)
+#define CRM_APB1RST_PWCRST (0x1U << 28)
+#define CRM_APB1RST_UART7RST (0x1U << 30)
+#define CRM_APB1RST_UART8RST (0x1U << 31)
+
+/***************** Bit definition for CRM_APB2RST register ***************/
+#define CRM_APB2RST_TMR1RST (0x1U << 0)
+#define CRM_APB2RST_USART1RST (0x1U << 4)
+#define CRM_APB2RST_USART6RST (0x1U << 5)
+#define CRM_APB2RST_ADC1RST (0x1U << 8)
+#define CRM_APB2RST_SPI1RST (0x1U << 12)
+#define CRM_APB2RST_SCFGRST (0x1U << 14)
+#define CRM_APB2RST_TMR9RST (0x1U << 16)
+#define CRM_APB2RST_TMR10RST (0x1U << 17)
+#define CRM_APB2RST_TMR11RST (0x1U << 18)
+#define CRM_APB2RST_I2SF5RST (0x1U << 20)
+#define CRM_APB2RST_ACCRST (0x1U << 29)
+
+/***************** Bit definition for CRM_AHBEN1 register ***************/
+#define CRM_AHBEN1_GPIOAEN (0x1U << 0)
+#define CRM_AHBEN1_GPIOBEN (0x1U << 1)
+#define CRM_AHBEN1_GPIOCEN (0x1U << 2)
+#define CRM_AHBEN1_GPIODEN (0x1U << 3)
+#define CRM_AHBEN1_GPIOFEN (0x1U << 5)
+#define CRM_AHBEN1_CRCEN (0x1U << 12)
+#define CRM_AHBEN1_DMA1EN (0x1U << 22)
+#define CRM_AHBEN1_DMA2EN (0x1U << 24)
+#define CRM_AHBEN1_OTGHSEN (0x1U << 29)
+
+/***************** Bit definition for CRM_AHBEN2 register ***************/
+#define CRM_AHBEN2_OTGFS1EN (0x1U << 7)
+
+/***************** Bit definition for CRM_AHBEN3 register ***************/
+#define CRM_AHBEN3_QSPI1EN (0x1U << 1)
+
+/***************** Bit definition for CRM_APB1EN register ***************/
+#define CRM_APB1EN_TMR2EN (0x1U << 0)
+#define CRM_APB1EN_TMR3EN (0x1U << 1)
+#define CRM_APB1EN_TMR4EN (0x1U << 2)
+#define CRM_APB1EN_TMR6EN (0x1U << 4)
+#define CRM_APB1EN_TMR7EN (0x1U << 5)
+#define CRM_APB1EN_TMR13EN (0x1U << 7)
+#define CRM_APB1EN_TMR14EN (0x1U << 8)
+#define CRM_APB1EN_WWDTEN (0x1U << 11)
+#define CRM_APB1EN_SPI2EN (0x1U << 14)
+#define CRM_APB1EN_SPI3EN (0x1U << 15)
+#define CRM_APB1EN_USART2EN (0x1U << 17)
+#define CRM_APB1EN_USART3EN (0x1U << 18)
+#define CRM_APB1EN_USART4EN (0x1U << 19)
+#define CRM_APB1EN_USART5EN (0x1U << 20)
+#define CRM_APB1EN_I2C1EN (0x1U << 21)
+#define CRM_APB1EN_I2C2EN (0x1U << 22)
+#define CRM_APB1EN_I2C3EN (0x1U << 23)
+#define CRM_APB1EN_CAN1EN (0x1U << 25)
+#define CRM_APB1EN_PWCEN (0x1U << 28)
+#define CRM_APB1EN_UART7EN (0x1U << 30)
+#define CRM_APB1EN_UART8EN (0x1U << 31)
+
+/***************** Bit definition for CRM_APB2EN register ***************/
+#define CRM_APB2EN_TMR1EN (0x1U << 0)
+#define CRM_APB2EN_USART1EN (0x1U << 4)
+#define CRM_APB2EN_USART6EN (0x1U << 5)
+#define CRM_APB2EN_ADC1EN (0x1U << 8)
+#define CRM_APB2EN_SPI1EN (0x1U << 12)
+#define CRM_APB2EN_SCFGEN (0x1U << 14)
+#define CRM_APB2EN_TMR9EN (0x1U << 16)
+#define CRM_APB2EN_TMR10EN (0x1U << 17)
+#define CRM_APB2EN_TMR11EN (0x1U << 18)
+#define CRM_APB2EN_I2SF5EN (0x1U << 20)
+#define CRM_APB2EN_ACCEN (0x1U << 29)
+
+/***************** Bit definition for CRM_AHBLPEN1 register ***************/
+#define CRM_AHBLPEN1_GPIOALPEN (0x1U << 0)
+#define CRM_AHBLPEN1_GPIOBLPEN (0x1U << 1)
+#define CRM_AHBLPEN1_GPIOCLPEN (0x1U << 2)
+#define CRM_AHBLPEN1_GPIODLPEN (0x1U << 3)
+#define CRM_AHBLPEN1_GPIOFLPEN (0x1U << 5)
+#define CRM_AHBLPEN1_CRCLPEN (0x1U << 12)
+#define CRM_AHBLPEN1_DMA1LPEN (0x1U << 22)
+#define CRM_AHBLPEN1_DMA2LPEN (0x1U << 24)
+#define CRM_AHBLPEN1_OTGHSLPEN (0x1U << 29)
+
+/***************** Bit definition for CRM_AHBLPEN2 register ***************/
+#define CRM_AHBLPEN2_OTGFS1LPEN (0x1U << 7)
+
+/***************** Bit definition for CRM_AHBLPEN3 register ***************/
+#define CRM_AHBLPEN3_QSPI1LPEN (0x1U << 1)
+
+/***************** Bit definition for CRM_APB1LPEN register ***************/
+#define CRM_APB1LPEN_TMR2LPEN (0x1U << 0)
+#define CRM_APB1LPEN_TMR3LPEN (0x1U << 1)
+#define CRM_APB1LPEN_TMR4LPEN (0x1U << 2)
+#define CRM_APB1LPEN_TMR6LPEN (0x1U << 4)
+#define CRM_APB1LPEN_TMR7LPEN (0x1U << 5)
+#define CRM_APB1LPEN_TMR13LPEN (0x1U << 7)
+#define CRM_APB1LPEN_TMR14LPEN (0x1U << 8)
+#define CRM_APB1LPEN_WWDTLPEN (0x1U << 11)
+#define CRM_APB1LPEN_SPI2LPEN (0x1U << 14)
+#define CRM_APB1LPEN_SPI3LPEN (0x1U << 15)
+#define CRM_APB1LPEN_USART2LPEN (0x1U << 17)
+#define CRM_APB1LPEN_USART3LPEN (0x1U << 18)
+#define CRM_APB1LPEN_USART4LPEN (0x1U << 19)
+#define CRM_APB1LPEN_USART5LPEN (0x1U << 20)
+#define CRM_APB1LPEN_I2C1LPEN (0x1U << 21)
+#define CRM_APB1LPEN_I2C2LPEN (0x1U << 22)
+#define CRM_APB1LPEN_I2C3LPEN (0x1U << 23)
+#define CRM_APB1LPEN_CAN1LPEN (0x1U << 25)
+#define CRM_APB1LPEN_PWCLPEN (0x1U << 28)
+#define CRM_APB1LPEN_UART7LPEN (0x1U << 30)
+#define CRM_APB1LPEN_UART8LPEN (0x1U << 31)
+
+/***************** Bit definition for CRM_APB2LPEN register ***************/
+#define CRM_APB2LPEN_TMR1LPEN (0x1U << 0)
+#define CRM_APB2LPEN_USART1LPEN (0x1U << 4)
+#define CRM_APB2LPEN_USART6LPEN (0x1U << 5)
+#define CRM_APB2LPEN_ADC1LPEN (0x1U << 8)
+#define CRM_APB2LPEN_SPI1LPEN (0x1U << 12)
+#define CRM_APB2LPEN_SCFGLPEN (0x1U << 14)
+#define CRM_APB2LPEN_TMR9LPEN (0x1U << 16)
+#define CRM_APB2LPEN_TMR10LPEN (0x1U << 17)
+#define CRM_APB2LPEN_TMR11LPEN (0x1U << 18)
+#define CRM_APB2LPEN_I2SF5LPEN (0x1U << 20)
+#define CRM_APB2LPEN_ACCLPEN (0x1U << 29)
+
+/****************** Bit definition for CRM_BPDC register *****************/
+#define CRM_BPDC_LEXTEN (0x1U << 0)
+#define CRM_BPDC_LEXTSTBL (0x1U << 1)
+#define CRM_BPDC_LEXTBYPS (0x1U << 2)
+#define CRM_BPDC_ERTCSEL (0x3U << 8)
+#define CRM_BPDC_ERTCSEL_LEXT (0x1U << 8)
+#define CRM_BPDC_ERTCSEL_LICK (0x2U << 8)
+#define CRM_BPDC_ERTCSEL_HEXTDIV (0x3U << 8)
+#define CRM_BPDC_ERTCEN (0x1U << 15)
+#define CRM_BPDC_BPDRST (0x1U << 16)
+
+/****************** Bit definition for CRM_CTRLSTS register **************/
+#define CRM_CTRLSTS_LICKEN (0x1U << 0)
+#define CRM_CTRLSTS_LICKSTBL (0x1U << 1)
+#define CRM_CTRLSTS_RSTFC (0x1U << 24)
+#define CRM_CTRLSTS_NRSTF (0x1U << 26)
+#define CRM_CTRLSTS_PORRSTF (0x1U << 27)
+#define CRM_CTRLSTS_SWRSTF (0x1U << 28)
+#define CRM_CTRLSTS_WDTRSTF (0x1U << 29)
+#define CRM_CTRLSTS_WWDTRSTF (0x1U << 30)
+#define CRM_CTRLSTS_LPRSTF (0x1U << 31)
+
+/****************** Bit definition for CRM_OTGHS register ****************/
+#define CRM_OTGHS_USBHS_PHY12_SEL (0x1U << 4)
+#define CRM_OTGHS_USBHS_PHY12_SEL_HEXT (0x0U << 4)
+
+/****************** Bit definition for CRM_MISC1 register ****************/
+#define CRM_MISC1_HICKDIV (0x1U << 12)
+#define CRM_MISC1_HICK_TO_SCLK (0x1U << 14)
+
+/****************** Bit definition for CRM_MISC2 register ****************/
+#define CRM_MISC2_AUTO_STEP_EN (0x3U << 4)
+#define CRM_MISC2_PLLU_USB48_SEL (0x1U << 10)
+#define CRM_MISC2_PLLU_USB48_SEL_PLLU (0x0U << 10)
+#define CRM_MISC2_PLLU_USB48_SEL_HICK (0x1U << 10)
+
+
+/* =========================================================================================================================== */
+/* ================ ERTC ================ */
+/* =========================================================================================================================== */
+
+/****************** Bit definition for ERTC_TIME register *******************/
+/*!< SU configuration */
+#define ERTC_TIME_SU_Pos (0U)
+#define ERTC_TIME_SU_Msk (0xFU << ERTC_TIME_SU_Pos) /*!< 0x0000000F */
+#define ERTC_TIME_SU ERTC_TIME_SU_Msk /*!< SU[3:0] (Second units) */
+#define ERTC_TIME_SU_0 (0x1U << ERTC_TIME_SU_Pos) /*!< 0x00000001 */
+#define ERTC_TIME_SU_1 (0x2U << ERTC_TIME_SU_Pos) /*!< 0x00000002 */
+#define ERTC_TIME_SU_2 (0x4U << ERTC_TIME_SU_Pos) /*!< 0x00000004 */
+#define ERTC_TIME_SU_3 (0x8U << ERTC_TIME_SU_Pos) /*!< 0x00000008 */
+
+/*!< ST configuration */
+#define ERTC_TIME_ST_Pos (4U)
+#define ERTC_TIME_ST_Msk (0x7U << ERTC_TIME_ST_Pos) /*!< 0x00000070 */
+#define ERTC_TIME_ST ERTC_TIME_ST_Msk /*!< ST[2:0] (Second tens) */
+#define ERTC_TIME_ST_0 (0x1U << ERTC_TIME_ST_Pos) /*!< 0x00000010 */
+#define ERTC_TIME_ST_1 (0x2U << ERTC_TIME_ST_Pos) /*!< 0x00000020 */
+#define ERTC_TIME_ST_2 (0x4U << ERTC_TIME_ST_Pos) /*!< 0x00000040 */
+
+/*!< MU configuration */
+#define ERTC_TIME_MU_Pos (8U)
+#define ERTC_TIME_MU_Msk (0xFU << ERTC_TIME_MU_Pos) /*!< 0x00000F00 */
+#define ERTC_TIME_MU ERTC_TIME_MU_Msk /*!< MU[3:0] (Minute units) */
+#define ERTC_TIME_MU_0 (0x1U << ERTC_TIME_MU_Pos) /*!< 0x00000100 */
+#define ERTC_TIME_MU_1 (0x2U << ERTC_TIME_MU_Pos) /*!< 0x00000200 */
+#define ERTC_TIME_MU_2 (0x4U << ERTC_TIME_MU_Pos) /*!< 0x00000400 */
+#define ERTC_TIME_MU_3 (0x8U << ERTC_TIME_MU_Pos) /*!< 0x00000800 */
+
+/*!< MT configuration */
+#define ERTC_TIME_MT_Pos (12U)
+#define ERTC_TIME_MT_Msk (0x7U << ERTC_TIME_MT_Pos) /*!< 0x00007000 */
+#define ERTC_TIME_MT ERTC_TIME_MT_Msk /*!< MT[2:0] (Minute tens) */
+#define ERTC_TIME_MT_0 (0x1U << ERTC_TIME_MT_Pos) /*!< 0x00001000 */
+#define ERTC_TIME_MT_1 (0x2U << ERTC_TIME_MT_Pos) /*!< 0x00002000 */
+#define ERTC_TIME_MT_2 (0x4U << ERTC_TIME_MT_Pos) /*!< 0x00004000 */
+
+/*!< HU configuration */
+#define ERTC_TIME_HU_Pos (16U)
+#define ERTC_TIME_HU_Msk (0xFU << ERTC_TIME_HU_Pos) /*!< 0x000F0000 */
+#define ERTC_TIME_HU ERTC_TIME_HU_Msk /*!< HU[3:0] (Hour units) */
+#define ERTC_TIME_HU_0 (0x1U << ERTC_TIME_HU_Pos) /*!< 0x00010000 */
+#define ERTC_TIME_HU_1 (0x2U << ERTC_TIME_HU_Pos) /*!< 0x00020000 */
+#define ERTC_TIME_HU_2 (0x4U << ERTC_TIME_HU_Pos) /*!< 0x00040000 */
+#define ERTC_TIME_HU_3 (0x8U << ERTC_TIME_HU_Pos) /*!< 0x00080000 */
+
+/*!< HT configuration */
+#define ERTC_TIME_HT_Pos (20U)
+#define ERTC_TIME_HT_Msk (0x3U << ERTC_TIME_HT_Pos) /*!< 0x00300000 */
+#define ERTC_TIME_HT ERTC_TIME_HT_Msk /*!< HT[1:0] (Hour tens) */
+#define ERTC_TIME_HT_0 (0x1U << ERTC_TIME_HT_Pos) /*!< 0x00100000 */
+#define ERTC_TIME_HT_1 (0x2U << ERTC_TIME_HT_Pos) /*!< 0x00200000 */
+
+#define ERTC_TIME_AMPM_Pos (22U)
+#define ERTC_TIME_AMPM_Msk (0x1U << ERTC_TIME_AMPM_Pos) /*!< 0x00400000 */
+#define ERTC_TIME_AMPM ERTC_TIME_AMPM_Msk /*!< AM/PM */
+
+/****************** Bit definition for ERTC_DATE register *******************/
+/*!< DU configuration */
+#define ERTC_DATE_DU_Pos (0U)
+#define ERTC_DATE_DU_Msk (0xFU << ERTC_DATE_DU_Pos) /*!< 0x0000000F */
+#define ERTC_DATE_DU ERTC_DATE_DU_Msk /*!< DU[3:0] (Date units) */
+#define ERTC_DATE_DU_0 (0x1U << ERTC_DATE_DU_Pos) /*!< 0x00000001 */
+#define ERTC_DATE_DU_1 (0x2U << ERTC_DATE_DU_Pos) /*!< 0x00000002 */
+#define ERTC_DATE_DU_2 (0x4U << ERTC_DATE_DU_Pos) /*!< 0x00000004 */
+#define ERTC_DATE_DU_3 (0x8U << ERTC_DATE_DU_Pos) /*!< 0x00000008 */
+
+/*!< DT configuration */
+#define ERTC_DATE_DT_Pos (4U)
+#define ERTC_DATE_DT_Msk (0x3U << ERTC_DATE_DT_Pos) /*!< 0x00300000 */
+#define ERTC_DATE_DT ERTC_DATE_DT_Msk /*!< DT[1:0] (Date tens) */
+#define ERTC_DATE_DT_0 (0x1U << ERTC_DATE_DT_Pos) /*!< 0x00000010 */
+#define ERTC_DATE_DT_1 (0x2U << ERTC_DATE_DT_Pos) /*!< 0x00000020 */
+
+/*!< MU configuration */
+#define ERTC_DATE_MU_Pos (8U)
+#define ERTC_DATE_MU_Msk (0xFU << ERTC_DATE_MU_Pos) /*!< 0x00000F00 */
+#define ERTC_DATE_MU ERTC_DATE_MU_Msk /*!< MU[3:0] (Month units) */
+#define ERTC_DATE_MU_0 (0x1U << ERTC_DATE_MU_Pos) /*!< 0x00000100 */
+#define ERTC_DATE_MU_1 (0x2U << ERTC_DATE_MU_Pos) /*!< 0x00000200 */
+#define ERTC_DATE_MU_2 (0x4U << ERTC_DATE_MU_Pos) /*!< 0x00000400 */
+#define ERTC_DATE_MU_3 (0x8U << ERTC_DATE_MU_Pos) /*!< 0x00000800 */
+
+#define ERTC_DATE_MT_Pos (12U)
+#define ERTC_DATE_MT_Msk (0x1U << ERTC_DATE_MT_Pos) /*!< 0x00001000 */
+#define ERTC_DATE_MT ERTC_DATE_MT_Msk /*!< Month tens */
+
+/*!< WK configuration */
+#define ERTC_DATE_WK_Pos (13U)
+#define ERTC_DATE_WK_Msk (0x7U << ERTC_DATE_WK_Pos) /*!< 0x0000E000 */
+#define ERTC_DATE_WK ERTC_DATE_WK_Msk /*!< WK[2:0] (Week day) */
+#define ERTC_DATE_WK_0 (0x1U << ERTC_DATE_WK_Pos) /*!< 0x00002000 */
+#define ERTC_DATE_WK_1 (0x2U << ERTC_DATE_WK_Pos) /*!< 0x00004000 */
+#define ERTC_DATE_WK_2 (0x4U << ERTC_DATE_WK_Pos) /*!< 0x00008000 */
+
+/*!< YU configuration */
+#define ERTC_DATE_YU_Pos (16U)
+#define ERTC_DATE_YU_Msk (0xFU << ERTC_DATE_YU_Pos) /*!< 0x000F0000 */
+#define ERTC_DATE_YU ERTC_DATE_YU_Msk /*!< YU[3:0] (Year units) */
+#define ERTC_DATE_YU_0 (0x1U << ERTC_DATE_YU_Pos) /*!< 0x00010000 */
+#define ERTC_DATE_YU_1 (0x2U << ERTC_DATE_YU_Pos) /*!< 0x00020000 */
+#define ERTC_DATE_YU_2 (0x4U << ERTC_DATE_YU_Pos) /*!< 0x00040000 */
+#define ERTC_DATE_YU_3 (0x8U << ERTC_DATE_YU_Pos) /*!< 0x00080000 */
+
+/*!< YT configuration */
+#define ERTC_DATE_YT_Pos (20U)
+#define ERTC_DATE_YT_Msk (0xFU << ERTC_DATE_YT_Pos) /*!< 0x00F00000 */
+#define ERTC_DATE_YT ERTC_DATE_YT_Msk /*!< YT[3:0] (Year tens) */
+#define ERTC_DATE_YT_0 (0x1U << ERTC_DATE_YT_Pos) /*!< 0x00100000 */
+#define ERTC_DATE_YT_1 (0x2U << ERTC_DATE_YT_Pos) /*!< 0x00200000 */
+#define ERTC_DATE_YT_2 (0x4U << ERTC_DATE_YT_Pos) /*!< 0x00400000 */
+#define ERTC_DATE_YT_3 (0x8U << ERTC_DATE_YT_Pos) /*!< 0x00800000 */
+
+/****************** Bit definition for ERTC_CTRL register *******************/
+/*!< WATCLK configuration */
+#define ERTC_CTRL_WATCLK_Pos (0U)
+#define ERTC_CTRL_WATCLK_Msk (0x7U << ERTC_CTRL_WATCLK_Pos) /*!< 0x00000007 */
+#define ERTC_CTRL_WATCLK ERTC_CTRL_WATCLK_Msk /*!< WATCLK[2:0] (Wakeup timer clock selection) */
+#define ERTC_CTRL_WATCLK_0 (0x1U << ERTC_CTRL_WATCLK_Pos) /*!< 0x00000001 */
+#define ERTC_CTRL_WATCLK_1 (0x2U << ERTC_CTRL_WATCLK_Pos) /*!< 0x00000002 */
+#define ERTC_CTRL_WATCLK_2 (0x4U << ERTC_CTRL_WATCLK_Pos) /*!< 0x00000004 */
+
+#define ERTC_CTRL_TSEDG_Pos (3U)
+#define ERTC_CTRL_TSEDG_Msk (0x1U << ERTC_CTRL_TSEDG_Pos) /*!< 0x00000008 */
+#define ERTC_CTRL_TSEDG ERTC_CTRL_TSEDG_Msk /*!< Timestamp trigger edge */
+#define ERTC_CTRL_RCDEN_Pos (4U)
+#define ERTC_CTRL_RCDEN_Msk (0x1U << ERTC_CTRL_RCDEN_Pos) /*!< 0x00000010 */
+#define ERTC_CTRL_RCDEN ERTC_CTRL_RCDEN_Msk /*!< Reference clock detection enable */
+#define ERTC_CTRL_DREN_Pos (5U)
+#define ERTC_CTRL_DREN_Msk (0x1U << ERTC_CTRL_DREN_Pos) /*!< 0x00000020 */
+#define ERTC_CTRL_DREN ERTC_CTRL_DREN_Msk /*!< Date/time register direct read enable */
+#define ERTC_CTRL_HM_Pos (6U)
+#define ERTC_CTRL_HM_Msk (0x1U << ERTC_CTRL_HM_Pos) /*!< 0x00000040 */
+#define ERTC_CTRL_HM ERTC_CTRL_HM_Msk /*!< Hour mode */
+#define ERTC_CTRL_CCALEN_Pos (7U)
+#define ERTC_CTRL_CCALEN_Msk (0x1U << ERTC_CTRL_CCALEN_Pos) /*!< 0x00000080 */
+#define ERTC_CTRL_CCALEN ERTC_CTRL_CCALEN_Msk /*!< Coarse calibration enable */
+#define ERTC_CTRL_ALAEN_Pos (8U)
+#define ERTC_CTRL_ALAEN_Msk (0x1U << ERTC_CTRL_ALAEN_Pos) /*!< 0x00000100 */
+#define ERTC_CTRL_ALAEN ERTC_CTRL_ALAEN_Msk /*!< Alarm A enable */
+#define ERTC_CTRL_ALBEN_Pos (9U)
+#define ERTC_CTRL_ALBEN_Msk (0x1U << ERTC_CTRL_ALBEN_Pos) /*!< 0x00000200 */
+#define ERTC_CTRL_ALBEN ERTC_CTRL_ALBEN_Msk /*!< Alarm B enable */
+#define ERTC_CTRL_WATEN_Pos (10U)
+#define ERTC_CTRL_WATEN_Msk (0x1U << ERTC_CTRL_WATEN_Pos) /*!< 0x00000400 */
+#define ERTC_CTRL_WATEN ERTC_CTRL_WATEN_Msk /*!< Wakeup timer enable */
+#define ERTC_CTRL_TSEN_Pos (11U)
+#define ERTC_CTRL_TSEN_Msk (0x1U << ERTC_CTRL_TSEN_Pos) /*!< 0x00000800 */
+#define ERTC_CTRL_TSEN ERTC_CTRL_TSEN_Msk /*!< Timestamp enable */
+#define ERTC_CTRL_ALAIEN_Pos (12U)
+#define ERTC_CTRL_ALAIEN_Msk (0x1U << ERTC_CTRL_ALAIEN_Pos) /*!< 0x00001000 */
+#define ERTC_CTRL_ALAIEN ERTC_CTRL_ALAIEN_Msk /*!< Alarm A interrupt enable */
+#define ERTC_CTRL_ALBIEN_Pos (13U)
+#define ERTC_CTRL_ALBIEN_Msk (0x1U << ERTC_CTRL_ALBIEN_Pos) /*!< 0x00002000 */
+#define ERTC_CTRL_ALBIEN ERTC_CTRL_ALBIEN_Msk /*!< Alarm B interrupt enable */
+#define ERTC_CTRL_WATIEN_Pos (14U)
+#define ERTC_CTRL_WATIEN_Msk (0x1U << ERTC_CTRL_WATIEN_Pos) /*!< 0x00004000 */
+#define ERTC_CTRL_WATIEN ERTC_CTRL_WATIEN_Msk /*!< Wakeup timer interrupt enable */
+#define ERTC_CTRL_TSIEN_Pos (15U)
+#define ERTC_CTRL_TSIEN_Msk (0x1U << ERTC_CTRL_TSIEN_Pos) /*!< 0x000008000 */
+#define ERTC_CTRL_TSIEN ERTC_CTRL_TSIEN_Msk /*!< Timestamp interrupt enable */
+#define ERTC_CTRL_ADD1H_Pos (16U)
+#define ERTC_CTRL_ADD1H_Msk (0x1U << ERTC_CTRL_ADD1H_Pos) /*!< 0x00010000 */
+#define ERTC_CTRL_ADD1H ERTC_CTRL_ADD1H_Msk /*!< Add 1 hour */
+#define ERTC_CTRL_DEC1H_Pos (17U)
+#define ERTC_CTRL_DEC1H_Msk (0x1U << ERTC_CTRL_DEC1H_Pos) /*!< 0x00020000 */
+#define ERTC_CTRL_DEC1H ERTC_CTRL_DEC1H_Msk /*!< Decrease 1 hour */
+#define ERTC_CTRL_BPR_Pos (18U)
+#define ERTC_CTRL_BPR_Msk (0x1U << ERTC_CTRL_BPR_Pos) /*!< 0x00040000 */
+#define ERTC_CTRL_BPR ERTC_CTRL_BPR_Msk /*!< Battery powered domain data register */
+#define ERTC_CTRL_CALOSEL_Pos (19U)
+#define ERTC_CTRL_CALOSEL_Msk (0x1U << ERTC_CTRL_CALOSEL_Pos) /*!< 0x00080000 */
+#define ERTC_CTRL_CALOSEL ERTC_CTRL_CALOSEL_Msk /*!< Calibration output selection */
+#define ERTC_CTRL_OUTP_Pos (20U)
+#define ERTC_CTRL_OUTP_Msk (0x1U << ERTC_CTRL_OUTP_Pos) /*!< 0x00100000 */
+#define ERTC_CTRL_OUTP ERTC_CTRL_OUTP_Msk /*!< Output polarity */
+
+/*!< OUTSEL configuration */
+#define ERTC_CTRL_OUTSEL_Pos (21U)
+#define ERTC_CTRL_OUTSEL_Msk (0x3U << ERTC_CTRL_OUTSEL_Pos) /*!< 0x00600000 */
+#define ERTC_CTRL_OUTSEL ERTC_CTRL_OUTSEL_Msk /*!< OUTSEL[1:0] (Output source selection) */
+#define ERTC_CTRL_OUTSEL_0 (0x1U << ERTC_CTRL_OUTSEL_Pos) /*!< 0x00200000 */
+#define ERTC_CTRL_OUTSEL_1 (0x2U << ERTC_CTRL_OUTSEL_Pos) /*!< 0x00400000 */
+
+#define ERTC_CTRL_CALOEN_Pos (23U)
+#define ERTC_CTRL_CALOEN_Msk (0x1U << ERTC_CTRL_CALOEN_Pos) /*!< 0x00800000 */
+#define ERTC_CTRL_CALOEN ERTC_CTRL_CALOEN_Msk /*!< Calibration output enable */
+
+/******************* Bit definition for ERTC_STS register *******************/
+#define ERTC_STS_ALAWF_Pos (0U)
+#define ERTC_STS_ALAWF_Msk (0x1U << ERTC_STS_ALAWF_Pos) /*!< 0x00000001 */
+#define ERTC_STS_ALAWF ERTC_STS_ALAWF_Msk /*!< Alarm A register allows write flag */
+#define ERTC_STS_ALBWF_Pos (1U)
+#define ERTC_STS_ALBWF_Msk (0x1U << ERTC_STS_ALBWF_Pos) /*!< 0x00000002 */
+#define ERTC_STS_ALBWF ERTC_STS_ALBWF_Msk /*!< Alarm B register allows write flag */
+#define ERTC_STS_WATWF_Pos (2U)
+#define ERTC_STS_WATWF_Msk (0x1U << ERTC_STS_WATWF_Pos) /*!< 0x00000004 */
+#define ERTC_STS_WATWF ERTC_STS_WATWF_Msk /*!< Wakeup timer register allows write flag */
+#define ERTC_STS_TADJF_Pos (3U)
+#define ERTC_STS_TADJF_Msk (0x1U << ERTC_STS_TADJF_Pos) /*!< 0x00000008 */
+#define ERTC_STS_TADJF ERTC_STS_TADJF_Msk /*!< Time adjustment flag */
+#define ERTC_STS_INITF_Pos (4U)
+#define ERTC_STS_INITF_Msk (0x1U << ERTC_STS_INITF_Pos) /*!< 0x00000010 */
+#define ERTC_STS_INITF ERTC_STS_INITF_Msk /*!< Calendar initialization flag */
+#define ERTC_STS_UPDF_Pos (5U)
+#define ERTC_STS_UPDF_Msk (0x1U << ERTC_STS_UPDF_Pos) /*!< 0x00000020 */
+#define ERTC_STS_UPDF ERTC_STS_UPDF_Msk /*!< Calendar update flag */
+#define ERTC_STS_IMF_Pos (6U)
+#define ERTC_STS_IMF_Msk (0x1U << ERTC_STS_IMF_Pos) /*!< 0x00000040 */
+#define ERTC_STS_IMF ERTC_STS_IMF_Msk /*!< Enter initialization mode flag */
+#define ERTC_STS_IMEN_Pos (7U)
+#define ERTC_STS_IMEN_Msk (0x1U << ERTC_STS_IMEN_Pos) /*!< 0x00000080 */
+#define ERTC_STS_IMEN ERTC_STS_IMEN_Msk /*!< Initialization mode enable */
+#define ERTC_STS_ALAF_Pos (8U)
+#define ERTC_STS_ALAF_Msk (0x1U << ERTC_STS_ALAF_Pos) /*!< 0x00000100 */
+#define ERTC_STS_ALAF ERTC_STS_ALAF_Msk /*!< Alarm clock A flag */
+#define ERTC_STS_ALBF_Pos (9U)
+#define ERTC_STS_ALBF_Msk (0x1U << ERTC_STS_ALBF_Pos) /*!< 0x00000200 */
+#define ERTC_STS_ALBF ERTC_STS_ALBF_Msk /*!< Alarm clock B flag */
+#define ERTC_STS_WATF_Pos (10U)
+#define ERTC_STS_WATF_Msk (0x1U << ERTC_STS_WATF_Pos) /*!< 0x00000400 */
+#define ERTC_STS_WATF ERTC_STS_WATF_Msk /*!< Wakeup timer flag */
+#define ERTC_STS_TSF_Pos (11U)
+#define ERTC_STS_TSF_Msk (0x1U << ERTC_STS_TSF_Pos) /*!< 0x00000800 */
+#define ERTC_STS_TSF ERTC_STS_TSF_Msk /*!< Timestamp flag */
+#define ERTC_STS_TSOF_Pos (12U)
+#define ERTC_STS_TSOF_Msk (0x1U << ERTC_STS_TSOF_Pos) /*!< 0x00001000 */
+#define ERTC_STS_TSOF ERTC_STS_TSOF_Msk /*!< Timestamp overflow flag */
+#define ERTC_STS_TP1F_Pos (13U)
+#define ERTC_STS_TP1F_Msk (0x1U << ERTC_STS_TP1F_Pos) /*!< 0x00002000 */
+#define ERTC_STS_TP1F ERTC_STS_TP1F_Msk /*!< Tamper detection 1 flag */
+#define ERTC_STS_CALUPDF_Pos (16U)
+#define ERTC_STS_CALUPDF_Msk (0x1U << ERTC_STS_CALUPDF_Pos) /*!< 0x00010000 */
+#define ERTC_STS_CALUPDF ERTC_STS_CALUPDF_Msk /*!< Calibration value update complete flag */
+
+/******************* Bit definition for ERTC_DIV register *******************/
+#define ERTC_DIV_DIVB_Pos (0U)
+#define ERTC_DIV_DIVB_Msk (0x7FFFU << ERTC_DIV_DIVB_Pos) /*!< 0x00007FFF */
+#define ERTC_DIV_DIVB ERTC_DIV_DIVB_Msk /*!< Divider B */
+#define ERTC_DIV_DIVA_Pos (16U)
+#define ERTC_DIV_DIVA_Msk (0x7FU << ERTC_DIV_DIVA_Pos) /*!< 0x007F0000 */
+#define ERTC_DIV_DIVA ERTC_DIV_DIVA_Msk /*!< Divider A */
+
+/******************* Bit definition for ERTC_WAT register *******************/
+#define ERTC_WAT_VAL_Pos (0U)
+#define ERTC_WAT_VAL_Msk (0xFFFFU << ERTC_WAT_VAL_Pos) /*!< 0x0000FFFF */
+#define ERTC_WAT_VAL ERTC_WAT_VAL_Msk /*!< Wakeup timer reload value */
+
+/****************** Bit definition for ERTC_CCAL register *******************/
+/*!< CALVAL configuration */
+#define ERTC_CCAL_CALVAL_Pos (0U)
+#define ERTC_CCAL_CALVAL_Msk (0x1FU << ERTC_CCAL_CALVAL_Pos) /*!< 0x0000001F */
+#define ERTC_CCAL_CALVAL ERTC_CCAL_CALVAL_Msk /*!< CALVAL[4:0] (Calibration value) */
+#define ERTC_CCAL_CALVAL_0 (0x1U << ERTC_CCAL_CALVAL_Pos) /*!< 0x00000001 */
+#define ERTC_CCAL_CALVAL_1 (0x2U << ERTC_CCAL_CALVAL_Pos) /*!< 0x00000002 */
+#define ERTC_CCAL_CALVAL_2 (0x4U << ERTC_CCAL_CALVAL_Pos) /*!< 0x00000004 */
+#define ERTC_CCAL_CALVAL_3 (0x8U << ERTC_CCAL_CALVAL_Pos) /*!< 0x00000008 */
+#define ERTC_CCAL_CALVAL_4 (0x10U << ERTC_CCAL_CALVAL_Pos) /*!< 0x00000010 */
+
+#define ERTC_CCAL_CALDIR_Pos (7U)
+#define ERTC_CCAL_CALDIR_Msk (0x1U << ERTC_CCAL_CALDIR_Pos) /*!< 0x00000080 */
+#define ERTC_CCAL_CALDIR ERTC_CCAL_CALDIR_Msk /*!< Calibration direction */
+
+/******************* Bit definition for ERTC_ALA register *******************/
+/*!< SU configuration */
+#define ERTC_ALA_SU_Pos (0U)
+#define ERTC_ALA_SU_Msk (0xFU << ERTC_ALA_SU_Pos) /*!< 0x0000000F */
+#define ERTC_ALA_SU ERTC_ALA_SU_Msk /*!< SU[3:0] (Second units) */
+#define ERTC_ALA_SU_0 (0x1U << ERTC_ALA_SU_Pos) /*!< 0x00000001 */
+#define ERTC_ALA_SU_1 (0x2U << ERTC_ALA_SU_Pos) /*!< 0x00000002 */
+#define ERTC_ALA_SU_2 (0x4U << ERTC_ALA_SU_Pos) /*!< 0x00000004 */
+#define ERTC_ALA_SU_3 (0x8U << ERTC_ALA_SU_Pos) /*!< 0x00000008 */
+
+/*!< ST configuration */
+#define ERTC_ALA_ST_Pos (4U)
+#define ERTC_ALA_ST_Msk (0x7U << ERTC_ALA_ST_Pos) /*!< 0x00000070 */
+#define ERTC_ALA_ST ERTC_ALA_ST_Msk /*!< ST[2:0] (Second tens) */
+#define ERTC_ALA_ST_0 (0x1U << ERTC_ALA_ST_Pos) /*!< 0x00000010 */
+#define ERTC_ALA_ST_1 (0x2U << ERTC_ALA_ST_Pos) /*!< 0x00000020 */
+#define ERTC_ALA_ST_2 (0x4U << ERTC_ALA_ST_Pos) /*!< 0x00000040 */
+
+#define ERTC_ALA_MASK1_Pos (7U)
+#define ERTC_ALA_MASK1_Msk (0x1U << ERTC_ALA_MASK1_Pos) /*!< 0x00000080 */
+#define ERTC_ALA_MASK1 ERTC_ALA_MASK1_Msk /*!< Second mask */
+
+/*!< MU configuration */
+#define ERTC_ALA_MU_Pos (8U)
+#define ERTC_ALA_MU_Msk (0xFU << ERTC_ALA_MU_Pos) /*!< 0x00000F00 */
+#define ERTC_ALA_MU ERTC_ALA_MU_Msk /*!< MU[3:0] (Minute units) */
+#define ERTC_ALA_MU_0 (0x1U << ERTC_ALA_MU_Pos) /*!< 0x00000100 */
+#define ERTC_ALA_MU_1 (0x2U << ERTC_ALA_MU_Pos) /*!< 0x00000200 */
+#define ERTC_ALA_MU_2 (0x4U << ERTC_ALA_MU_Pos) /*!< 0x00000400 */
+#define ERTC_ALA_MU_3 (0x8U << ERTC_ALA_MU_Pos) /*!< 0x00000800 */
+
+/*!< MT configuration */
+#define ERTC_ALA_MT_Pos (12U)
+#define ERTC_ALA_MT_Msk (0x7U << ERTC_ALA_MT_Pos) /*!< 0x00007000 */
+#define ERTC_ALA_MT ERTC_ALA_MT_Msk /*!< MT[2:0] (Minute tens) */
+#define ERTC_ALA_MT_0 (0x1U << ERTC_ALA_MT_Pos) /*!< 0x00001000 */
+#define ERTC_ALA_MT_1 (0x2U << ERTC_ALA_MT_Pos) /*!< 0x00002000 */
+#define ERTC_ALA_MT_2 (0x4U << ERTC_ALA_MT_Pos) /*!< 0x00004000 */
+
+#define ERTC_ALA_MASK2_Pos (15U)
+#define ERTC_ALA_MASK2_Msk (0x1U << ERTC_ALA_MASK2_Pos) /*!< 0x00008000 */
+#define ERTC_ALA_MASK2 ERTC_ALA_MASK2_Msk /*!< Minute mask */
+
+/*!< HU configuration */
+#define ERTC_ALA_HU_Pos (16U)
+#define ERTC_ALA_HU_Msk (0xFU << ERTC_ALA_HU_Pos) /*!< 0x000F0000 */
+#define ERTC_ALA_HU ERTC_ALA_HU_Msk /*!< HU[3:0] (Hour units) */
+#define ERTC_ALA_HU_0 (0x1U << ERTC_ALA_HU_Pos) /*!< 0x00010000 */
+#define ERTC_ALA_HU_1 (0x2U << ERTC_ALA_HU_Pos) /*!< 0x00020000 */
+#define ERTC_ALA_HU_2 (0x4U << ERTC_ALA_HU_Pos) /*!< 0x00040000 */
+#define ERTC_ALA_HU_3 (0x8U << ERTC_ALA_HU_Pos) /*!< 0x00080000 */
+
+/*!< HT configuration */
+#define ERTC_ALA_HT_Pos (20U)
+#define ERTC_ALA_HT_Msk (0x3U << ERTC_ALA_HT_Pos) /*!< 0x00300000 */
+#define ERTC_ALA_HT ERTC_ALA_HT_Msk /*!< HT[1:0] (Hour tens) */
+#define ERTC_ALA_HT_0 (0x1U << ERTC_ALA_HT_Pos) /*!< 0x00100000 */
+#define ERTC_ALA_HT_1 (0x2U << ERTC_ALA_HT_Pos) /*!< 0x00200000 */
+
+#define ERTC_ALA_AMPM_Pos (22U)
+#define ERTC_ALA_AMPM_Msk (0x1U << ERTC_ALA_AMPM_Pos) /*!< 0x00400000 */
+#define ERTC_ALA_AMPM ERTC_ALA_AMPM_Msk /*!< AM/PM */
+#define ERTC_ALA_MASK3_Pos (23U)
+#define ERTC_ALA_MASK3_Msk (0x1U << ERTC_ALA_MASK3_Pos) /*!< 0x00800000 */
+#define ERTC_ALA_MASK3 ERTC_ALA_MASK3_Msk /*!< Hour mask */
+
+/*!< DU configuration */
+#define ERTC_ALA_DU_Pos (24U)
+#define ERTC_ALA_DU_Msk (0xFU << ERTC_ALA_DU_Pos) /*!< 0x0F000000 */
+#define ERTC_ALA_DU ERTC_ALA_DU_Msk /*!< DU[3:0] (Date/week day units) */
+#define ERTC_ALA_DU_0 (0x1U << ERTC_ALA_DU_Pos) /*!< 0x01000000 */
+#define ERTC_ALA_DU_1 (0x2U << ERTC_ALA_DU_Pos) /*!< 0x02000000 */
+#define ERTC_ALA_DU_2 (0x4U << ERTC_ALA_DU_Pos) /*!< 0x04000000 */
+#define ERTC_ALA_DU_3 (0x8U << ERTC_ALA_DU_Pos) /*!< 0x08000000 */
+
+/*!< DT configuration */
+#define ERTC_ALA_DT_Pos (28U)
+#define ERTC_ALA_DT_Msk (0x3U << ERTC_ALA_DT_Pos) /*!< 0x30000000 */
+#define ERTC_ALA_DT ERTC_ALA_DT_Msk /*!< DT[1:0] (Date/week day tens) */
+#define ERTC_ALA_DT_0 (0x1U << ERTC_ALA_DT_Pos) /*!< 0x10000000 */
+#define ERTC_ALA_DT_1 (0x2U << ERTC_ALA_DT_Pos) /*!< 0x20000000 */
+
+#define ERTC_ALA_WKSEL_Pos (30U)
+#define ERTC_ALA_WKSEL_Msk (0x1U << ERTC_ALA_WKSEL_Pos) /*!< 0x40000000 */
+#define ERTC_ALA_WKSEL ERTC_ALA_WKSEL_Msk /*!< Date/week day select */
+#define ERTC_ALA_MASK4_Pos (31U)
+#define ERTC_ALA_MASK4_Msk (0x1U << ERTC_ALA_MASK4_Pos) /*!< 0x80000000 */
+#define ERTC_ALA_MASK4 ERTC_ALA_MASK4_Msk /*!< Date/week day mask */
+
+/******************* Bit definition for ERTC_ALB register *******************/
+/*!< SU configuration */
+#define ERTC_ALB_SU_Pos (0U)
+#define ERTC_ALB_SU_Msk (0xFU << ERTC_ALB_SU_Pos) /*!< 0x0000000F */
+#define ERTC_ALB_SU ERTC_ALB_SU_Msk /*!< SU[3:0] (Second units) */
+#define ERTC_ALB_SU_0 (0x1U << ERTC_ALB_SU_Pos) /*!< 0x00000001 */
+#define ERTC_ALB_SU_1 (0x2U << ERTC_ALB_SU_Pos) /*!< 0x00000002 */
+#define ERTC_ALB_SU_2 (0x4U << ERTC_ALB_SU_Pos) /*!< 0x00000004 */
+#define ERTC_ALB_SU_3 (0x8U << ERTC_ALB_SU_Pos) /*!< 0x00000008 */
+
+/*!< ST configuration */
+#define ERTC_ALB_ST_Pos (4U)
+#define ERTC_ALB_ST_Msk (0x7U << ERTC_ALB_ST_Pos) /*!< 0x00000070 */
+#define ERTC_ALB_ST ERTC_ALB_ST_Msk /*!< ST[2:0] (Second tens) */
+#define ERTC_ALB_ST_0 (0x1U << ERTC_ALB_ST_Pos) /*!< 0x00000010 */
+#define ERTC_ALB_ST_1 (0x2U << ERTC_ALB_ST_Pos) /*!< 0x00000020 */
+#define ERTC_ALB_ST_2 (0x4U << ERTC_ALB_ST_Pos) /*!< 0x00000040 */
+
+#define ERTC_ALB_MASK1_Pos (7U)
+#define ERTC_ALB_MASK1_Msk (0x1U << ERTC_ALB_MASK1_Pos) /*!< 0x00000080 */
+#define ERTC_ALB_MASK1 ERTC_ALB_MASK1_Msk /*!< Second mask */
+
+/*!< MU configuration */
+#define ERTC_ALB_MU_Pos (8U)
+#define ERTC_ALB_MU_Msk (0xFU << ERTC_ALB_MU_Pos) /*!< 0x00000F00 */
+#define ERTC_ALB_MU ERTC_ALB_MU_Msk /*!< MU[3:0] (Minute units) */
+#define ERTC_ALB_MU_0 (0x1U << ERTC_ALB_MU_Pos) /*!< 0x00000100 */
+#define ERTC_ALB_MU_1 (0x2U << ERTC_ALB_MU_Pos) /*!< 0x00000200 */
+#define ERTC_ALB_MU_2 (0x4U << ERTC_ALB_MU_Pos) /*!< 0x00000400 */
+#define ERTC_ALB_MU_3 (0x8U << ERTC_ALB_MU_Pos) /*!< 0x00000800 */
+
+/*!< MT configuration */
+#define ERTC_ALB_MT_Pos (12U)
+#define ERTC_ALB_MT_Msk (0x7U << ERTC_ALB_MT_Pos) /*!< 0x00007000 */
+#define ERTC_ALB_MT ERTC_ALB_MT_Msk /*!< MT[2:0] (Minute tens) */
+#define ERTC_ALB_MT_0 (0x1U << ERTC_ALB_MT_Pos) /*!< 0x00001000 */
+#define ERTC_ALB_MT_1 (0x2U << ERTC_ALB_MT_Pos) /*!< 0x00002000 */
+#define ERTC_ALB_MT_2 (0x4U << ERTC_ALB_MT_Pos) /*!< 0x00004000 */
+
+#define ERTC_ALB_MASK2_Pos (15U)
+#define ERTC_ALB_MASK2_Msk (0x1U << ERTC_ALB_MASK2_Pos) /*!< 0x00008000 */
+#define ERTC_ALB_MASK2 ERTC_ALB_MASK2_Msk /*!< Minute mask */
+
+/*!< HU configuration */
+#define ERTC_ALB_HU_Pos (16U)
+#define ERTC_ALB_HU_Msk (0xFU << ERTC_ALB_HU_Pos) /*!< 0x000F0000 */
+#define ERTC_ALB_HU ERTC_ALB_HU_Msk /*!< HU[3:0] (Hour units) */
+#define ERTC_ALB_HU_0 (0x1U << ERTC_ALB_HU_Pos) /*!< 0x00010000 */
+#define ERTC_ALB_HU_1 (0x2U << ERTC_ALB_HU_Pos) /*!< 0x00020000 */
+#define ERTC_ALB_HU_2 (0x4U << ERTC_ALB_HU_Pos) /*!< 0x00040000 */
+#define ERTC_ALB_HU_3 (0x8U << ERTC_ALB_HU_Pos) /*!< 0x00080000 */
+
+/*!< HT configuration */
+#define ERTC_ALB_HT_Pos (20U)
+#define ERTC_ALB_HT_Msk (0x3U << ERTC_ALB_HT_Pos) /*!< 0x00300000 */
+#define ERTC_ALB_HT ERTC_ALB_HT_Msk /*!< HT[1:0] (Hour tens) */
+#define ERTC_ALB_HT_0 (0x1U << ERTC_ALB_HT_Pos) /*!< 0x00100000 */
+#define ERTC_ALB_HT_1 (0x2U << ERTC_ALB_HT_Pos) /*!< 0x00200000 */
+
+#define ERTC_ALB_AMPM_Pos (22U)
+#define ERTC_ALB_AMPM_Msk (0x1U << ERTC_ALB_AMPM_Pos) /*!< 0x00400000 */
+#define ERTC_ALB_AMPM ERTC_ALB_AMPM_Msk /*!< AM/PM */
+#define ERTC_ALB_MASK3_Pos (23U)
+#define ERTC_ALB_MASK3_Msk (0x1U << ERTC_ALB_MASK3_Pos) /*!< 0x00800000 */
+#define ERTC_ALB_MASK3 ERTC_ALB_MASK3_Msk /*!< Hour mask */
+
+/*!< DU configuration */
+#define ERTC_ALB_DU_Pos (24U)
+#define ERTC_ALB_DU_Msk (0xFU << ERTC_ALB_DU_Pos) /*!< 0x0F000000 */
+#define ERTC_ALB_DU ERTC_ALB_DU_Msk /*!< DU[3:0] (Date/week day units) */
+#define ERTC_ALB_DU_0 (0x1U << ERTC_ALB_DU_Pos) /*!< 0x01000000 */
+#define ERTC_ALB_DU_1 (0x2U << ERTC_ALB_DU_Pos) /*!< 0x02000000 */
+#define ERTC_ALB_DU_2 (0x4U << ERTC_ALB_DU_Pos) /*!< 0x04000000 */
+#define ERTC_ALB_DU_3 (0x8U << ERTC_ALB_DU_Pos) /*!< 0x08000000 */
+
+/*!< DT configuration */
+#define ERTC_ALB_DT_Pos (28U)
+#define ERTC_ALB_DT_Msk (0x3U << ERTC_ALB_DT_Pos) /*!< 0x30000000 */
+#define ERTC_ALB_DT ERTC_ALB_DT_Msk /*!< DT[1:0] (Date/week day tens) */
+#define ERTC_ALB_DT_0 (0x1U << ERTC_ALB_DT_Pos) /*!< 0x10000000 */
+#define ERTC_ALB_DT_1 (0x2U << ERTC_ALB_DT_Pos) /*!< 0x20000000 */
+
+#define ERTC_ALB_WKSEL_Pos (30U)
+#define ERTC_ALB_WKSEL_Msk (0x1U << ERTC_ALB_WKSEL_Pos) /*!< 0x40000000 */
+#define ERTC_ALB_WKSEL ERTC_ALB_WKSEL_Msk /*!< Date/week day select */
+#define ERTC_ALB_MASK4_Pos (31U)
+#define ERTC_ALB_MASK4_Msk (0x1U << ERTC_ALB_MASK4_Pos) /*!< 0x80000000 */
+#define ERTC_ALB_MASK4 ERTC_ALB_MASK4_Msk /*!< Date/week day mask */
+
+/******************* Bit definition for ERTC_WP register ********************/
+#define ERTC_WP_CMD_Pos (0U)
+#define ERTC_WP_CMD_Msk (0xFFU << ERTC_WP_CMD_Pos) /*!< 0x000000FF */
+#define ERTC_WP_CMD ERTC_WP_CMD_Msk /*!< Command register */
+
+/******************* Bit definition for ERTC_SBS register *******************/
+#define ERTC_SBS_SBS_Pos (0U)
+#define ERTC_SBS_SBS_Msk (0xFFFFU << ERTC_SBS_SBS_Pos) /*!< 0x0000FFFF */
+#define ERTC_SBS_SBS ERTC_SBS_SBS_Msk /*!< Sub-second value */
+
+/****************** Bit definition for ERTC_TADJ register *******************/
+#define ERTC_TADJ_DECSBS_Pos (0U)
+#define ERTC_TADJ_DECSBS_Msk (0x7FFFU << ERTC_TADJ_DECSBS_Pos) /*!< 0x00007FFF */
+#define ERTC_TADJ_DECSBS ERTC_TADJ_DECSBS_Msk /*!< Decrease sub-second value */
+#define ERTC_TADJ_ADD1S_Pos (31U)
+#define ERTC_TADJ_ADD1S_Msk (0x1U << ERTC_TADJ_ADD1S_Pos) /*!< 0x80000000 */
+#define ERTC_TADJ_ADD1S ERTC_TADJ_ADD1S_Msk /*!< Add 1 second */
+
+/****************** Bit definition for ERTC_TSTM register *******************/
+/*!< SU configuration */
+#define ERTC_TSTM_SU_Pos (0U)
+#define ERTC_TSTM_SU_Msk (0xFU << ERTC_TSTM_SU_Pos) /*!< 0x0000000F */
+#define ERTC_TSTM_SU ERTC_TSTM_SU_Msk /*!< SU[3:0] (Second units) */
+#define ERTC_TSTM_SU_0 (0x1U << ERTC_TSTM_SU_Pos) /*!< 0x00000001 */
+#define ERTC_TSTM_SU_1 (0x2U << ERTC_TSTM_SU_Pos) /*!< 0x00000002 */
+#define ERTC_TSTM_SU_2 (0x4U << ERTC_TSTM_SU_Pos) /*!< 0x00000004 */
+#define ERTC_TSTM_SU_3 (0x8U << ERTC_TSTM_SU_Pos) /*!< 0x00000008 */
+
+/*!< ST configuration */
+#define ERTC_TSTM_ST_Pos (4U)
+#define ERTC_TSTM_ST_Msk (0x7U << ERTC_TSTM_ST_Pos) /*!< 0x00000070 */
+#define ERTC_TSTM_ST ERTC_TSTM_ST_Msk /*!< ST[2:0] (Second tens) */
+#define ERTC_TSTM_ST_0 (0x1U << ERTC_TSTM_ST_Pos) /*!< 0x00000010 */
+#define ERTC_TSTM_ST_1 (0x2U << ERTC_TSTM_ST_Pos) /*!< 0x00000020 */
+#define ERTC_TSTM_ST_2 (0x4U << ERTC_TSTM_ST_Pos) /*!< 0x00000040 */
+
+/*!< MU configuration */
+#define ERTC_TSTM_MU_Pos (8U)
+#define ERTC_TSTM_MU_Msk (0xFU << ERTC_TSTM_MU_Pos) /*!< 0x00000F00 */
+#define ERTC_TSTM_MU ERTC_TSTM_MU_Msk /*!< MU[3:0] (Minute units) */
+#define ERTC_TSTM_MU_0 (0x1U << ERTC_TSTM_MU_Pos) /*!< 0x00000100 */
+#define ERTC_TSTM_MU_1 (0x2U << ERTC_TSTM_MU_Pos) /*!< 0x00000200 */
+#define ERTC_TSTM_MU_2 (0x4U << ERTC_TSTM_MU_Pos) /*!< 0x00000400 */
+#define ERTC_TSTM_MU_3 (0x8U << ERTC_TSTM_MU_Pos) /*!< 0x00000800 */
+
+/*!< MT configuration */
+#define ERTC_TSTM_MT_Pos (12U)
+#define ERTC_TSTM_MT_Msk (0x7U << ERTC_TSTM_MT_Pos) /*!< 0x00007000 */
+#define ERTC_TSTM_MT ERTC_TSTM_MT_Msk /*!< MT[2:0] (Minute tens) */
+#define ERTC_TSTM_MT_0 (0x1U << ERTC_TSTM_MT_Pos) /*!< 0x00001000 */
+#define ERTC_TSTM_MT_1 (0x2U << ERTC_TSTM_MT_Pos) /*!< 0x00002000 */
+#define ERTC_TSTM_MT_2 (0x4U << ERTC_TSTM_MT_Pos) /*!< 0x00004000 */
+
+/*!< HU configuration */
+#define ERTC_TSTM_HU_Pos (16U)
+#define ERTC_TSTM_HU_Msk (0xFU << ERTC_TSTM_HU_Pos) /*!< 0x000F0000 */
+#define ERTC_TSTM_HU ERTC_TSTM_HU_Msk /*!< HU[3:0] (Hour units) */
+#define ERTC_TSTM_HU_0 (0x1U << ERTC_TSTM_HU_Pos) /*!< 0x00010000 */
+#define ERTC_TSTM_HU_1 (0x2U << ERTC_TSTM_HU_Pos) /*!< 0x00020000 */
+#define ERTC_TSTM_HU_2 (0x4U << ERTC_TSTM_HU_Pos) /*!< 0x00040000 */
+#define ERTC_TSTM_HU_3 (0x8U << ERTC_TSTM_HU_Pos) /*!< 0x00080000 */
+
+/*!< HT configuration */
+#define ERTC_TSTM_HT_Pos (20U)
+#define ERTC_TSTM_HT_Msk (0x3U << ERTC_TSTM_HT_Pos) /*!< 0x00300000 */
+#define ERTC_TSTM_HT ERTC_TSTM_HT_Msk /*!< HT[1:0] (Hour tens) */
+#define ERTC_TSTM_HT_0 (0x1U << ERTC_TSTM_HT_Pos) /*!< 0x00100000 */
+#define ERTC_TSTM_HT_1 (0x2U << ERTC_TSTM_HT_Pos) /*!< 0x00200000 */
+
+#define ERTC_TSTM_AMPM_Pos (22U)
+#define ERTC_TSTM_AMPM_Msk (0x1U << ERTC_TSTM_AMPM_Pos) /*!< 0x00400000 */
+#define ERTC_TSTM_AMPM ERTC_TSTM_AMPM_Msk /*!< AM/PM */
+
+/****************** Bit definition for ERTC_TSDT register *******************/
+/*!< DU configuration */
+#define ERTC_TSDT_DU_Pos (0U)
+#define ERTC_TSDT_DU_Msk (0xFU << ERTC_TSDT_DU_Pos) /*!< 0x0000000F */
+#define ERTC_TSDT_DU ERTC_TSDT_DU_Msk /*!< DU[3:0] (Date units) */
+#define ERTC_TSDT_DU_0 (0x1U << ERTC_TSDT_DU_Pos) /*!< 0x00000001 */
+#define ERTC_TSDT_DU_1 (0x2U << ERTC_TSDT_DU_Pos) /*!< 0x00000002 */
+#define ERTC_TSDT_DU_2 (0x4U << ERTC_TSDT_DU_Pos) /*!< 0x00000004 */
+#define ERTC_TSDT_DU_3 (0x8U << ERTC_TSDT_DU_Pos) /*!< 0x00000008 */
+
+/*!< DT configuration */
+#define ERTC_TSDT_DT_Pos (4U)
+#define ERTC_TSDT_DT_Msk (0x3U << ERTC_TSDT_DT_Pos) /*!< 0x00000030 */
+#define ERTC_TSDT_DT ERTC_TSDT_DT_Msk /*!< DT[1:0] (Date tens) */
+#define ERTC_TSDT_DT_0 (0x1U << ERTC_TSDT_DT_Pos) /*!< 0x00000010 */
+#define ERTC_TSDT_DT_1 (0x2U << ERTC_TSDT_DT_Pos) /*!< 0x00000020 */
+
+/*!< MU configuration */
+#define ERTC_TSDT_MU_Pos (8U)
+#define ERTC_TSDT_MU_Msk (0xFU << ERTC_TSDT_MU_Pos) /*!< 0x00000F00 */
+#define ERTC_TSDT_MU ERTC_TSDT_MU_Msk /*!< MU[3:0] (Month units) */
+#define ERTC_TSDT_MU_0 (0x1U << ERTC_TSDT_MU_Pos) /*!< 0x00000100 */
+#define ERTC_TSDT_MU_1 (0x2U << ERTC_TSDT_MU_Pos) /*!< 0x00000200 */
+#define ERTC_TSDT_MU_2 (0x4U << ERTC_TSDT_MU_Pos) /*!< 0x00000400 */
+#define ERTC_TSDT_MU_3 (0x8U << ERTC_TSDT_MU_Pos) /*!< 0x00000800 */
+
+#define ERTC_TSDT_MT_Pos (12U)
+#define ERTC_TSDT_MT_Msk (0x1U << ERTC_TSDT_MT_Pos) /*!< 0x00001000 */
+#define ERTC_TSDT_MT ERTC_TSDT_MT_Msk /*!< Month tens */
+
+/*!< WK configuration */
+#define ERTC_TSDT_WK_Pos (13U)
+#define ERTC_TSDT_WK_Msk (0x7U << ERTC_TSDT_WK_Pos) /*!< 0x0000E000 */
+#define ERTC_TSDT_WK ERTC_TSDT_WK_Msk /*!< WK[2:0] (Week day) */
+#define ERTC_TSDT_WK_0 (0x1U << ERTC_TSDT_WK_Pos) /*!< 0x00002000 */
+#define ERTC_TSDT_WK_1 (0x2U << ERTC_TSDT_WK_Pos) /*!< 0x00004000 */
+#define ERTC_TSDT_WK_2 (0x4U << ERTC_TSDT_WK_Pos) /*!< 0x00008000 */
+
+/****************** Bit definition for ERTC_TSSBS register ******************/
+#define ERTC_TSSBS_SBS_Pos (0U)
+#define ERTC_TSSBS_SBS_Msk (0xFFFFU << ERTC_TSSBS_SBS_Pos) /*!< 0x0000FFFF */
+#define ERTC_TSSBS_SBS ERTC_TSSBS_SBS_Msk /*!< Sub-second value */
+
+/****************** Bit definition for ERTC_SCAL register *******************/
+#define ERTC_SCAL_DEC_Pos (0U)
+#define ERTC_SCAL_DEC_Msk (0x1FFU << ERTC_SCAL_DEC_Pos) /*!< 0x000001FF */
+#define ERTC_SCAL_DEC ERTC_SCAL_DEC_Msk /*!< Decrease ERTC clock */
+#define ERTC_SCAL_CAL16_Pos (13U)
+#define ERTC_SCAL_CAL16_Msk (0x1U << ERTC_SCAL_CAL16_Pos) /*!< 0x00002000 */
+#define ERTC_SCAL_CAL16 ERTC_SCAL_CAL16_Msk /*!< 16 second calibration period */
+#define ERTC_SCAL_CAL8_Pos (14U)
+#define ERTC_SCAL_CAL8_Msk (0x1U << ERTC_SCAL_CAL8_Pos) /*!< 0x00004000 */
+#define ERTC_SCAL_CAL8 ERTC_SCAL_CAL8_Msk /*!< 8 second calibration period */
+#define ERTC_SCAL_ADD_Pos (15U)
+#define ERTC_SCAL_ADD_Msk (0x1U << ERTC_SCAL_ADD_Pos) /*!< 0x00008000 */
+#define ERTC_SCAL_ADD ERTC_SCAL_ADD_Msk /*!< Add ERTC clock */
+
+/****************** Bit definition for ERTC_TAMP register *******************/
+#define ERTC_TAMP_TP1EN_Pos (0U)
+#define ERTC_TAMP_TP1EN_Msk (0x1U << ERTC_TAMP_TP1EN_Pos) /*!< 0x00000001 */
+#define ERTC_TAMP_TP1EN ERTC_TAMP_TP1EN_Msk /*!< Tamper detection 1 enable */
+#define ERTC_TAMP_TP1EDG_Pos (1U)
+#define ERTC_TAMP_TP1EDG_Msk (0x1U << ERTC_TAMP_TP1EDG_Pos) /*!< 0x00000002 */
+#define ERTC_TAMP_TP1EDG ERTC_TAMP_TP1EDG_Msk /*!< Tamper detection 1 valid edge */
+#define ERTC_TAMP_TPIEN_Pos (2U)
+#define ERTC_TAMP_TPIEN_Msk (0x1U << ERTC_TAMP_TPIEN_Pos) /*!< 0x00000004 */
+#define ERTC_TAMP_TPIEN ERTC_TAMP_TPIEN_Msk /*!< Tamper detection interrupt enable */
+#define ERTC_TAMP_TPTSEN_Pos (7U)
+#define ERTC_TAMP_TPTSEN_Msk (0x1U << ERTC_TAMP_TPTSEN_Pos) /*!< 0x00000080 */
+#define ERTC_TAMP_TPTSEN ERTC_TAMP_TPTSEN_Msk /*!< Tamper detection timestamp enable */
+
+/*!< TPFREQ configuration */
+#define ERTC_TAMP_TPFREQ_Pos (8U)
+#define ERTC_TAMP_TPFREQ_Msk (0x7U << ERTC_TAMP_TPFREQ_Pos) /*!< 0x00000700 */
+#define ERTC_TAMP_TPFREQ ERTC_TAMP_TPFREQ_Msk /*!< TPFREQ[2:0] (Tamper detection frequency) */
+#define ERTC_TAMP_TPFREQ_0 (0x1U << ERTC_TAMP_TPFREQ_Pos) /*!< 0x00000100 */
+#define ERTC_TAMP_TPFREQ_1 (0x2U << ERTC_TAMP_TPFREQ_Pos) /*!< 0x00000200 */
+#define ERTC_TAMP_TPFREQ_2 (0x4U << ERTC_TAMP_TPFREQ_Pos) /*!< 0x00000400 */
+
+/*!< TPFLT configuration */
+#define ERTC_TAMP_TPFLT_Pos (11U)
+#define ERTC_TAMP_TPFLT_Msk (0x3U << ERTC_TAMP_TPFLT_Pos) /*!< 0x00001800 */
+#define ERTC_TAMP_TPFLT ERTC_TAMP_TPFLT_Msk /*!< TPFLT[1:0] (Tamper detection filter time) */
+#define ERTC_TAMP_TPFLT_0 (0x1U << ERTC_TAMP_TPFLT_Pos) /*!< 0x00000800 */
+#define ERTC_TAMP_TPFLT_1 (0x2U << ERTC_TAMP_TPFLT_Pos) /*!< 0x00001000 */
+
+/*!< TPPR configuration */
+#define ERTC_TAMP_TPPR_Pos (13U)
+#define ERTC_TAMP_TPPR_Msk (0x3U << ERTC_TAMP_TPPR_Pos) /*!< 0x00006000 */
+#define ERTC_TAMP_TPPR ERTC_TAMP_TPPR_Msk /*!< TPPR[1:0] (Tamper detection pre-charge time) */
+#define ERTC_TAMP_TPPR_0 (0x1U << ERTC_TAMP_TPPR_Pos) /*!< 0x00002000 */
+#define ERTC_TAMP_TPPR_1 (0x2U << ERTC_TAMP_TPPR_Pos) /*!< 0x00004000 */
+
+#define ERTC_TAMP_TPPU_Pos (15U)
+#define ERTC_TAMP_TPPU_Msk (0x1U << ERTC_TAMP_TPPU_Pos) /*!< 0x00008000 */
+#define ERTC_TAMP_TPPU ERTC_TAMP_TPPU_Msk /*!< Tamper detection pull-up */
+#define ERTC_TAMP_OUTTYPE_Pos (18U)
+#define ERTC_TAMP_OUTTYPE_Msk (0x1U << ERTC_TAMP_OUTTYPE_Pos) /*!< 0x00040000 */
+#define ERTC_TAMP_OUTTYPE ERTC_TAMP_OUTTYPE_Msk /*!< Output type */
+
+/***************** Bit definition for ERTC_ALASBS register ******************/
+#define ERTC_ALASBS_SBS_Pos (0U)
+#define ERTC_ALASBS_SBS_Msk (0x7FFFU << ERTC_ALASBS_SBS_Pos) /*!< 0x00007FFF */
+#define ERTC_ALASBS_SBS ERTC_ALASBS_SBS_Msk /*!< Sub-second value */
+
+/*!< SBSMSK configuration */
+#define ERTC_ALASBS_SBSMSK_Pos (24U)
+#define ERTC_ALASBS_SBSMSK_Msk (0xFU << ERTC_ALASBS_SBSMSK_Pos) /*!< 0x0F000000 */
+#define ERTC_ALASBS_SBSMSK ERTC_ALASBS_SBSMSK_Msk /*!< SBSMSK[3:0] (Sub-second mask) */
+#define ERTC_ALASBS_SBSMSK_0 (0x1U << ERTC_ALASBS_SBSMSK_Pos) /*!< 0x01000000 */
+#define ERTC_ALASBS_SBSMSK_1 (0x2U << ERTC_ALASBS_SBSMSK_Pos) /*!< 0x02000000 */
+#define ERTC_ALASBS_SBSMSK_2 (0x4U << ERTC_ALASBS_SBSMSK_Pos) /*!< 0x04000000 */
+#define ERTC_ALASBS_SBSMSK_3 (0x8U << ERTC_ALASBS_SBSMSK_Pos) /*!< 0x08000000 */
+
+/***************** Bit definition for ERTC_ALBSBS register ******************/
+#define ERTC_ALBSBS_SBS_Pos (0U)
+#define ERTC_ALBSBS_SBS_Msk (0x7FFFU << ERTC_ALBSBS_SBS_Pos) /*!< 0x00007FFF */
+#define ERTC_ALBSBS_SBS ERTC_ALBSBS_SBS_Msk /*!< Sub-second value */
+
+/*!< SBSMSK configuration */
+#define ERTC_ALBSBS_SBSMSK_Pos (24U)
+#define ERTC_ALBSBS_SBSMSK_Msk (0xFU << ERTC_ALBSBS_SBSMSK_Pos) /*!< 0x0F000000 */
+#define ERTC_ALBSBS_SBSMSK ERTC_ALBSBS_SBSMSK_Msk /*!< SBSMSK[3:0] (Sub-second mask) */
+#define ERTC_ALBSBS_SBSMSK_0 (0x1U << ERTC_ALBSBS_SBSMSK_Pos) /*!< 0x01000000 */
+#define ERTC_ALBSBS_SBSMSK_1 (0x2U << ERTC_ALBSBS_SBSMSK_Pos) /*!< 0x02000000 */
+#define ERTC_ALBSBS_SBSMSK_2 (0x4U << ERTC_ALBSBS_SBSMSK_Pos) /*!< 0x04000000 */
+#define ERTC_ALBSBS_SBSMSK_3 (0x8U << ERTC_ALBSBS_SBSMSK_Pos) /*!< 0x08000000 */
+
+/****************** Bit definition for ERTC_BPR1 register *******************/
+#define ERTC_BPR1_DT_Pos (0U)
+#define ERTC_BPR1_DT_Msk (0xFFFFFFFFU << ERTC_BPR1_DT_Pos) /*!< 0xFFFFFFFF */
+#define ERTC_BPR1_DT ERTC_BPR1_DT_Msk /*!< Battery powered domain data 1 */
+
+/****************** Bit definition for ERTC_BPR2 register *******************/
+#define ERTC_BPR2_DT_Pos (0U)
+#define ERTC_BPR2_DT_Msk (0xFFFFFFFFU << ERTC_BPR2_DT_Pos) /*!< 0xFFFFFFFF */
+#define ERTC_BPR2_DT ERTC_BPR2_DT_Msk /*!< Battery powered domain data 2 */
+
+/****************** Bit definition for ERTC_BPR3 register *******************/
+#define ERTC_BPR3_DT_Pos (0U)
+#define ERTC_BPR3_DT_Msk (0xFFFFFFFFU << ERTC_BPR3_DT_Pos) /*!< 0xFFFFFFFF */
+#define ERTC_BPR3_DT ERTC_BPR3_DT_Msk /*!< Battery powered domain data 3 */
+
+/****************** Bit definition for ERTC_BPR4 register *******************/
+#define ERTC_BPR4_DT_Pos (0U)
+#define ERTC_BPR4_DT_Msk (0xFFFFFFFFU << ERTC_BPR4_DT_Pos) /*!< 0xFFFFFFFF */
+#define ERTC_BPR4_DT ERTC_BPR4_DT_Msk /*!< Battery powered domain data 4 */
+
+/****************** Bit definition for ERTC_BPR5 register *******************/
+#define ERTC_BPR5_DT_Pos (0U)
+#define ERTC_BPR5_DT_Msk (0xFFFFFFFFU << ERTC_BPR5_DT_Pos) /*!< 0xFFFFFFFF */
+#define ERTC_BPR5_DT ERTC_BPR5_DT_Msk /*!< Battery powered domain data 5 */
+
+/****************** Bit definition for ERTC_BPR6 register *******************/
+#define ERTC_BPR6_DT_Pos (0U)
+#define ERTC_BPR6_DT_Msk (0xFFFFFFFFU << ERTC_BPR6_DT_Pos) /*!< 0xFFFFFFFF */
+#define ERTC_BPR6_DT ERTC_BPR6_DT_Msk /*!< Battery powered domain data 6 */
+
+/****************** Bit definition for ERTC_BPR7 register *******************/
+#define ERTC_BPR7_DT_Pos (0U)
+#define ERTC_BPR7_DT_Msk (0xFFFFFFFFU << ERTC_BPR7_DT_Pos) /*!< 0xFFFFFFFF */
+#define ERTC_BPR7_DT ERTC_BPR7_DT_Msk /*!< Battery powered domain data 7 */
+
+/****************** Bit definition for ERTC_BPR8 register *******************/
+#define ERTC_BPR8_DT_Pos (0U)
+#define ERTC_BPR8_DT_Msk (0xFFFFFFFFU << ERTC_BPR8_DT_Pos) /*!< 0xFFFFFFFF */
+#define ERTC_BPR8_DT ERTC_BPR8_DT_Msk /*!< Battery powered domain data 8 */
+
+/****************** Bit definition for ERTC_BPR9 register *******************/
+#define ERTC_BPR9_DT_Pos (0U)
+#define ERTC_BPR9_DT_Msk (0xFFFFFFFFU << ERTC_BPR9_DT_Pos) /*!< 0xFFFFFFFF */
+#define ERTC_BPR9_DT ERTC_BPR9_DT_Msk /*!< Battery powered domain data 9 */
+
+/****************** Bit definition for ERTC_BPR10 register ******************/
+#define ERTC_BPR10_DT_Pos (0U)
+#define ERTC_BPR10_DT_Msk (0xFFFFFFFFU << ERTC_BPR10_DT_Pos) /*!< 0xFFFFFFFF */
+#define ERTC_BPR10_DT ERTC_BPR10_DT_Msk /*!< Battery powered domain data 10 */
+
+/****************** Bit definition for ERTC_BPR11 register ******************/
+#define ERTC_BPR11_DT_Pos (0U)
+#define ERTC_BPR11_DT_Msk (0xFFFFFFFFU << ERTC_BPR11_DT_Pos) /*!< 0xFFFFFFFF */
+#define ERTC_BPR11_DT ERTC_BPR11_DT_Msk /*!< Battery powered domain data 11 */
+
+/****************** Bit definition for ERTC_BPR12 register ******************/
+#define ERTC_BPR12_DT_Pos (0U)
+#define ERTC_BPR12_DT_Msk (0xFFFFFFFFU << ERTC_BPR12_DT_Pos) /*!< 0xFFFFFFFF */
+#define ERTC_BPR12_DT ERTC_BPR12_DT_Msk /*!< Battery powered domain data 12 */
+
+/****************** Bit definition for ERTC_BPR13 register ******************/
+#define ERTC_BPR13_DT_Pos (0U)
+#define ERTC_BPR13_DT_Msk (0xFFFFFFFFU << ERTC_BPR13_DT_Pos) /*!< 0xFFFFFFFF */
+#define ERTC_BPR13_DT ERTC_BPR13_DT_Msk /*!< Battery powered domain data 13 */
+
+/****************** Bit definition for ERTC_BPR14 register ******************/
+#define ERTC_BPR14_DT_Pos (0U)
+#define ERTC_BPR14_DT_Msk (0xFFFFFFFFU << ERTC_BPR14_DT_Pos) /*!< 0xFFFFFFFF */
+#define ERTC_BPR14_DT ERTC_BPR14_DT_Msk /*!< Battery powered domain data 14 */
+
+/****************** Bit definition for ERTC_BPR15 register ******************/
+#define ERTC_BPR15_DT_Pos (0U)
+#define ERTC_BPR15_DT_Msk (0xFFFFFFFFU << ERTC_BPR15_DT_Pos) /*!< 0xFFFFFFFF */
+#define ERTC_BPR15_DT ERTC_BPR15_DT_Msk /*!< Battery powered domain data 15 */
+
+/****************** Bit definition for ERTC_BPR16 register ******************/
+#define ERTC_BPR16_DT_Pos (0U)
+#define ERTC_BPR16_DT_Msk (0xFFFFFFFFU << ERTC_BPR16_DT_Pos) /*!< 0xFFFFFFFF */
+#define ERTC_BPR16_DT ERTC_BPR16_DT_Msk /*!< Battery powered domain data 16 */
+
+/****************** Bit definition for ERTC_BPR17 register ******************/
+#define ERTC_BPR17_DT_Pos (0U)
+#define ERTC_BPR17_DT_Msk (0xFFFFFFFFU << ERTC_BPR17_DT_Pos) /*!< 0xFFFFFFFF */
+#define ERTC_BPR17_DT ERTC_BPR17_DT_Msk /*!< Battery powered domain data 17 */
+
+/****************** Bit definition for ERTC_BPR18 register ******************/
+#define ERTC_BPR18_DT_Pos (0U)
+#define ERTC_BPR18_DT_Msk (0xFFFFFFFFU << ERTC_BPR18_DT_Pos) /*!< 0xFFFFFFFF */
+#define ERTC_BPR18_DT ERTC_BPR18_DT_Msk /*!< Battery powered domain data 18 */
+
+/****************** Bit definition for ERTC_BPR19 register ******************/
+#define ERTC_BPR19_DT_Pos (0U)
+#define ERTC_BPR19_DT_Msk (0xFFFFFFFFU << ERTC_BPR19_DT_Pos) /*!< 0xFFFFFFFF */
+#define ERTC_BPR19_DT ERTC_BPR19_DT_Msk /*!< Battery powered domain data 19 */
+
+/****************** Bit definition for ERTC_BPR20 register ******************/
+#define ERTC_BPR20_DT_Pos (0U)
+#define ERTC_BPR20_DT_Msk (0xFFFFFFFFU << ERTC_BPR20_DT_Pos) /*!< 0xFFFFFFFF */
+#define ERTC_BPR20_DT ERTC_BPR20_DT_Msk /*!< Battery powered domain data 20 */
+
+/************************* Number of backup registers *************************/
+#define ERTC_BPR_NUMBER 0x000000014U
+
+/* =========================================================================================================================== */
+/* ================ PWC ================ */
+/* =========================================================================================================================== */
+/****************** Bit definition for PWC_CTRL register *****************/
+#define PWC_CTRL_PVMEN (0x1U << 4)
+#define PWC_CTRL_BPWEN (0x1U << 8)
+
+
+/* =========================================================================================================================== */
+/* ================ FLASH ================ */
+/* =========================================================================================================================== */
+/****************** Bit definition for FLASH_STS register ****************/
+#define FLASH_STS_OBF (0x1U << 0)
+#define FLASH_STS_PRGMERR (0x1U << 2)
+#define FLASH_STS_EPPERR (0x1U << 4)
+#define FLASH_STS_ODF (0x1U << 5)
+
+/****************** Bit definition for FLASH_CTRL register ***************/
+#define FLASH_CTRL_FPRGM (0x1U << 0)
+#define FLASH_CTRL_SECERS (0x1U << 1)
+#define FLASH_CTRL_BANKERS (0x1U << 2)
+#define FLASH_CTRL_USDPRGM (0x1U << 4)
+#define FLASH_CTRL_USDERS (0x1U << 5)
+#define FLASH_CTRL_ERSTR (0x1U << 6)
+#define FLASH_CTRL_OPLK (0x1U << 7)
+
+
+/* =========================================================================================================================== */
+/* ================ TMR ================ */
+/* =========================================================================================================================== */
+/****************** Bit definition for TMR_IDEN register ****************/
+#define TMR_IDEN_OVFIEN (0x1U << 0)
+#define TMR_IDEN_C1IEN (0x1U << 1)
+#define TMR_IDEN_C2IEN (0x1U << 2)
+#define TMR_IDEN_C3IEN (0x1U << 3)
+#define TMR_IDEN_C4IEN (0x1U << 4)
+#define TMR_IDEN_HALLIEN (0x1U << 5)
+#define TMR_IDEN_TIEN (0x1U << 6)
+#define TMR_IDEN_BRKIEN (0x1U << 7)
+#define TMR_IDEN_OVFDEN (0x1U << 8)
+#define TMR_IDEN_C1DEN (0x1U << 9)
+#define TMR_IDEN_C2DEN (0x1U << 10)
+#define TMR_IDEN_C3DEN (0x1U << 11)
+#define TMR_IDEN_C4DEN (0x1U << 12)
+#define TMR_IDEN_HALLDEN (0x1U << 13)
+#define TMR_IDEN_TDEN (0x1U << 14)
+
+
+/* =========================================================================================================================== */
+/* ================ DMA ================ */
+/* =========================================================================================================================== */
+/****************** Bit definition for DMA_CxCTRL register **************/
+#define DMA_CTRL_CHEN (0x1U << 0)
+#define DMA_CTRL_FDTIEN (0x1U << 1)
+#define DMA_CTRL_HDTIEN (0x1U << 2)
+#define DMA_CTRL_DTERRIEN (0x1U << 3)
+#define DMA_CTRL_DTD (0x1U << 4)
+#define DMA_CTRL_LM (0x1U << 5)
+#define DMA_CTRL_PINCM (0x1U << 6)
+#define DMA_CTRL_MINCM (0x1U << 7)
+#define DMA_CTRL_PWIDTH (0x3U << 8)
+#define DMA_CTRL_PWIDTH_8BITS (0x0U << 8)
+#define DMA_CTRL_PWIDTH_16BITS (0x1U << 8)
+#define DMA_CTRL_PWIDTH_32BITS (0x2U << 8)
+#define DMA_CTRL_MWIDTH (0x3U << 10)
+#define DMA_CTRL_MWIDTH_8BITS (0x0U << 10)
+#define DMA_CTRL_MWIDTH_16BITS (0x1U << 10)
+#define DMA_CTRL_MWIDTH_32BITS (0x2U << 10)
+#define DMA_CTRL_CHPL (0x3U << 12)
+#define DMA_CTRL_CHPL_LOW (0x0U << 12)
+#define DMA_CTRL_CHPL_MID (0x1U << 12)
+#define DMA_CTRL_CHPL_HIGH (0x2U << 12)
+#define DMA_CTRL_CHPL_HIGHEST (0x3U << 12)
+#define DMA_CTRL_M2M (0x1U << 14)
+
+/****************** Bit definition for DMA_MUXSEL register *************/
+#define DMA_MUXSEL_TBL_SEL (0x1U << 0)
+
+/****************** Bit definition for DMA_MUXCxCTRL register *************/
+#define DMA_MUXCTRL_SYNCOVIEN (0x1U << 8)
+#define DMA_MUXCTRL_EVTGEN (0x1U << 9)
+#define DMA_MUXCTRL_SYNCEN (0x1U << 16)
+#define DMA_MUXCTRL_SYNCPOL (0x3U << 17)
+#define DMA_MUXCTRL_SYNCPOL_NONE (0x0U << 17)
+#define DMA_MUXCTRL_SYNCPOL_RISING (0x1U << 17)
+#define DMA_MUXCTRL_SYNCPOL_FALLING (0x2U << 17)
+#define DMA_MUXCTRL_SYNCPOL_BOTH (0x3U << 17)
+
+/****************** Bit definition for DMA_MUXGxCTRL register *************/
+#define DMA_MUXGCTRL_TRGOVIEN (0x1U << 8)
+#define DMA_MUXGCTRL_GEN (0x1U << 16)
+#define DMA_MUXGCTRL_GPOL (0x3U << 17)
+#define DMA_MUXGCTRL_GPOL_NONE (0x0U << 17)
+#define DMA_MUXGCTRL_GPOL_RISING (0x1U << 17)
+#define DMA_MUXGCTRL_GPOL_FALLING (0x2U << 17)
+#define DMA_MUXGCTRL_GPOL_BOTH (0x3U << 17)
+
+
+/* =========================================================================================================================== */
+/* ================ I2C ================ */
+/* =========================================================================================================================== */
+/****************** Bit definition for I2C_CTRL1 register ***************/
+#define I2C_CTRL1_I2CEN (0x1U << 0)
+#define I2C_CTRL1_TDIEN (0x1U << 1)
+#define I2C_CTRL1_RDIEN (0x1U << 2)
+#define I2C_CTRL1_ADDRIEN (0x1U << 3)
+#define I2C_CTRL1_ACKFAILIEN (0x1U << 4)
+#define I2C_CTRL1_STOPIEN (0x1U << 5)
+#define I2C_CTRL1_TDCIEN (0x1U << 6)
+#define I2C_CTRL1_ERRIEN (0x1U << 7)
+#define I2C_CTRL1_DMATEN (0x1U << 14)
+#define I2C_CTRL1_DMAREN (0x1U << 15)
+#define I2C_CTRL1_SCTRL (0x1U << 16)
+#define I2C_CTRL1_STRETCH (0x1U << 17)
+#define I2C_CTRL1_GCAEN (0x1U << 19)
+#define I2C_CTRL1_HADDREN (0x1U << 20)
+#define I2C_CTRL1_DEVADDREN (0x1U << 21)
+#define I2C_CTRL1_SMBALERT (0x1U << 22)
+#define I2C_CTRL1_PECEN (0x1U << 23)
+
+/****************** Bit definition for I2C_CTRL2 register ***************/
+#define I2C_CTRL2_DIR (0x1U << 10)
+#define I2C_CTRL2_ADDR10 (0x1U << 11)
+#define I2C_CTRL2_READH10 (0x1U << 12)
+#define I2C_CTRL2_GENSTART (0x1U << 13)
+#define I2C_CTRL2_GENSTOP (0x1U << 14)
+#define I2C_CTRL2_NACKEN (0x1U << 15)
+#define I2C_CTRL2_RLDEN (0x1U << 24)
+#define I2C_CTRL2_ASTOPEN (0x1U << 25)
+#define I2C_CTRL2_PECTEN (0x1U << 26)
+#define I2C_CTRL2_CNT_MASK (0xFF << 16)
+
+/****************** Bit definition for I2C_TIMEOUT register ***************/
+#define I2C_TIMEOUT_TOMODE (0x1U << 12)
+#define I2C_TIMEOUT_TOMODE_LOW (0x0U << 12)
+#define I2C_TIMEOUT_TOMODE_HIGH (0x1U << 12)
+#define I2C_TIMEOUT_TOEN (0x1U << 15)
+#define I2C_TIMEOUT_EXTEN (0x1U << 31)
+
+/****************** Bit definition for I2C_STS register ***************/
+#define I2C_STS_TDBE (0x1U << 0)
+#define I2C_STS_TDIS (0x1U << 1)
+#define I2C_STS_RDBF (0x1U << 2)
+#define I2C_STS_ADDRF (0x1U << 3)
+#define I2C_STS_ACKFAILF (0x1U << 4)
+#define I2C_STS_STOPF (0x1U << 5)
+#define I2C_STS_TDC (0x1U << 6)
+#define I2C_STS_TCRLD (0x1U << 7)
+#define I2C_STS_BUSERR (0x1U << 8)
+#define I2C_STS_ARLOST (0x1U << 9)
+#define I2C_STS_OUF (0x1U << 10)
+#define I2C_STS_PECERR (0x1U << 11)
+#define I2C_STS_TMOUT (0x1U << 12)
+#define I2C_STS_ALERTF (0x1U << 13)
+#define I2C_STS_BUSYF (0x1U << 15)
+#define I2C_STS_SDIR (0x1U << 16)
+
+
+/* =========================================================================================================================== */
+/* ================ USART ================ */
+/* =========================================================================================================================== */
+
+
+/******************* Bit definition for USART_STS register **************/
+#define USART_STS_PERR (0x1U << 0)
+#define USART_STS_FERR (0x1U << 1)
+#define USART_STS_NERR (0x1U << 2)
+#define USART_STS_ROERR (0x1U << 3)
+#define USART_STS_IDLEF (0x1U << 4)
+#define USART_STS_RDBF (0x1U << 5)
+#define USART_STS_TDC (0x1U << 6)
+#define USART_STS_TDBE (0x1U << 7)
+#define USART_STS_BFF (0x1U << 8)
+#define USART_STS_CTSCF (0x1U << 9)
+#define USART_STS_RTODF (0x1U << 11)
+#define USART_STS_CMDF (0x1U << 17)
+
+/******************* Bit definition for USART_DT register ***************/
+#define USART_DT_DT (0x1FFU << 0)
+
+/****************** Bit definition for USART_CTRL1 register *************/
+#define USART_CTRL1_SBF (0x1U << 0)
+#define USART_CTRL1_RM (0x1U << 1)
+#define USART_CTRL1_REN (0x1U << 2)
+#define USART_CTRL1_TEN (0x1U << 3)
+#define USART_CTRL1_IDLEIEN (0x1U << 4)
+#define USART_CTRL1_RDBFIEN (0x1U << 5)
+#define USART_CTRL1_TDCIEN (0x1U << 6)
+#define USART_CTRL1_TDBEIEN (0x1U << 7)
+#define USART_CTRL1_PERRIEN (0x1U << 8)
+#define USART_CTRL1_PSEL (0x1U << 9)
+#define USART_CTRL1_PEN (0x1U << 10)
+#define USART_CTRL1_WUM (0x1U << 11)
+#define USART_CTRL1_DBN0 (0x1U << 12)
+#define USART_CTRL1_UEN (0x1U << 13)
+#define USART_CTRL1_CMDIE (0x1U << 14)
+#define USART_CTRL1_RETODIE (0x1U << 26)
+#define USART_CTRL1_RTODEN (0x1U << 27)
+#define USART_CTRL1_DBN1 (0x1U << 28)
+#define USART_CTRL1_DBN_7BITS (0x1U << 28)
+#define USART_CTRL1_DBN_8BITS (0x0U << 28)
+#define USART_CTRL1_DBN_9BITS (0x1U << 12)
+#define USART_CTRL1_DBN (0x1U << 12)
+
+/****************** Bit definition for USART_CTRL2 register *************/
+#define USART_CTRL2_IDL (0xFU << 0)
+#define USART_CTRL2_IDBN (0x1U << 4)
+#define USART_CTRL2_BFBN (0x1U << 5)
+#define USART_CTRL2_BFIEN (0x1U << 6)
+#define USART_CTRL2_LBCP (0x1U << 8)
+#define USART_CTRL2_CLKPHA (0x1U << 9)
+#define USART_CTRL2_CLKPOL (0x1U << 10)
+#define USART_CTRL2_CLKEN (0x1U << 11)
+#define USART_CTRL2_STOPBN (0x3U << 12)
+#define USART_CTRL2_STOP_0 (0x1U << 12)
+#define USART_CTRL2_STOP_1 (0x1U << 13)
+#define USART_CTRL2_STOPBN_1_BITS (0x0U << 12)
+#define USART_CTRL2_STOPBN_0P5_BITS (0x1U << 12)
+#define USART_CTRL2_STOPBN_2_BITS (0x2U << 12)
+#define USART_CTRL2_STOPBN_1P5_BITS (0x3U << 12)
+#define USART_CTRL2_LINEN (0x1U << 14)
+#define USART_CTRL2_TRPSWAP (0x1U << 15)
+#define USART_CTRL2_RXREV (0x1U << 16)
+#define USART_CTRL2_TXREV (0x1U << 17)
+#define USART_CTRL2_DTREV (0x1U << 18)
+#define USART_CTRL2_MTF (0x1U << 19)
+#define USART_CTRL2_IDH (0xFU << 28)
+
+/****************** Bit definition for USART_CTRL3 register *************/
+#define USART_CTRL3_ERRIEN (0x1U << 0)
+#define USART_CTRL3_IRDAEN (0x1U << 1)
+#define USART_CTRL3_IRDALP (0x1U << 2)
+#define USART_CTRL3_SLBEN (0x1U << 3)
+#define USART_CTRL3_SCNACKEN (0x1U << 4)
+#define USART_CTRL3_SCMEN (0x1U << 5)
+#define USART_CTRL3_DMAREN (0x1U << 6)
+#define USART_CTRL3_DMATEN (0x1U << 7)
+#define USART_CTRL3_RTSEN (0x1U << 8)
+#define USART_CTRL3_CTSEN (0x1U << 9)
+#define USART_CTRL3_CTSCFIEN (0x1U << 10)
+#define USART_CTRL3_RS485EN (0x1U << 14)
+#define USART_CTRL3_DEP (0x1U << 15)
+
+/******************* Bit definition for USART_IFC register ***************/
+#define USART_IFC_RTODFC (0x1U << 11)
+#define USART_IFC_CMDFC (0x1U << 17)
+
+
+/* =========================================================================================================================== */
+/* ================ SPI ================ */
+/* =========================================================================================================================== */
+
+/******************* Bit definition for SPI_CTRL1 register **************/
+#define SPI_CTRL1_CLKPHA (0x1U << 0)
+#define SPI_CTRL1_CLKPOL (0x1U << 1)
+#define SPI_CTRL1_MSTEN (0x1U << 2)
+#define SPI_CTRL1_MDIV (0x7U << 3)
+#define SPI_CTRL1_MDIV_2 (0x0U << 3)
+#define SPI_CTRL1_MDIV_4 (0x1U << 3)
+#define SPI_CTRL1_MDIV_8 (0x2U << 3)
+#define SPI_CTRL1_MDIV_16 (0x3U << 3)
+#define SPI_CTRL1_MDIV_32 (0x4U << 3)
+#define SPI_CTRL1_MDIV_64 (0x5U << 3)
+#define SPI_CTRL1_MDIV_128 (0x6U << 3)
+#define SPI_CTRL1_MDIV_256 (0x7U << 3)
+#define SPI_CTRL1_MDIV_512 (0x0U << 3)
+#define SPI_CTRL1_MDIV_1024 (0x1U << 3)
+#define SPI_CTRL1_SPIEN (0x1U << 6)
+#define SPI_CTRL1_LTF (0x1U << 7)
+#define SPI_CTRL1_SWCSIL (0x1U << 8)
+#define SPI_CTRL1_SWCSEN (0x1U << 9)
+#define SPI_CTRL1_ORA (0x1U << 10)
+#define SPI_CTRL1_FBN (0x1U << 11)
+#define SPI_CTRL1_NTC (0x1U << 12)
+#define SPI_CTRL1_CCEN (0x1U << 13)
+#define SPI_CTRL1_SLBTD (0x1U << 14)
+#define SPI_CTRL1_SLBEN (0x1U << 15)
+
+/******************* Bit definition for SPI_CTRL2 register **************/
+#define SPI_CTRL2_DMAREN (0x1U << 0)
+#define SPI_CTRL2_DMATEN (0x1U << 1)
+#define SPI_CTRL2_HWCSOE (0x1U << 2)
+#define SPI_CTRL2_TIEN (0x1U << 4)
+#define SPI_CTRL2_ERRIE (0x1U << 5)
+#define SPI_CTRL2_RDBFIE (0x1U << 6)
+#define SPI_CTRL2_TDBEIE (0x1U << 7)
+#define SPI_CTRL2_MDIV (0x1U << 8)
+#define SPI_CTRL2_MDIV_512_1024 (0x1U << 8)
+#define SPI_CTRL2_MDIV3EN (0x1U << 9)
+
+/******************* Bit definition for SPI_STS register ********************/
+#define SPI_STS_RDBF (0x1U << 0)
+#define SPI_STS_TDBE (0x1U << 1)
+#define SPI_STS_ACS (0x1U << 2)
+#define SPI_STS_TUERR (0x1U << 3)
+#define SPI_STS_CCERR (0x1U << 4)
+#define SPI_STS_MMERR (0x1U << 5)
+#define SPI_STS_ROERR (0x1U << 6)
+#define SPI_STS_BF (0x1U << 7)
+#define SPI_STS_CSPAS (0x1U << 8)
+
+/******************* Bit definition for SPI_I2SCTRL register *****************/
+#define SPI_I2SCTRL_I2SCBN (0x1U << 0)
+#define SPI_I2SCTRL_I2SDBN (0x3U << 1)
+#define SPI_I2SCTRL_I2SDBN_16BITS (0x0U << 1)
+#define SPI_I2SCTRL_I2SDBN_24BITS (0x1U << 1)
+#define SPI_I2SCTRL_I2SDBN_32BITS (0x2U << 1)
+#define SPI_I2SCTRL_I2SDBN_NONE (0x3U << 1)
+#define SPI_I2SCTRL_I2SCLKPOL (0x1U << 3)
+#define SPI_I2SCTRL_STDSEL (0x3U << 4)
+#define SPI_I2SCTRL_STDSEL_PHILIPS (0x0U << 4)
+#define SPI_I2SCTRL_STDSEL_MSB (0x1U << 4)
+#define SPI_I2SCTRL_STDSEL_LSB (0x2U << 4)
+#define SPI_I2SCTRL_STDSEL_PCM (0x3U << 4)
+#define SPI_I2SCTRL_PCMFSSEL (0x1U << 7)
+#define SPI_I2SCTRL_OPERSEL (0x3U << 8)
+#define SPI_I2SCTRL_OPERSEL_ST (0x0U << 8)
+#define SPI_I2SCTRL_OPERSEL_SR (0x1U << 8)
+#define SPI_I2SCTRL_OPERSEL_HT (0x2U << 8)
+#define SPI_I2SCTRL_OPERSEL_HR (0x3U << 8)
+#define SPI_I2SCTRL_I2SEN (0x1U << 10)
+#define SPI_I2SCTRL_I2SMSEL (0x1U << 11)
+
+/******************* Bit definition for SPI_I2SCLKP register ************/
+#define SPI_I2SCLKP_I2SDIV_1 (0xFFU << 0)
+#define SPI_I2SCLKP_I2SODD (0x1U << 8)
+#define SPI_I2SCLKP_I2SMCLKOE (0x1U << 9)
+#define SPI_I2SCLKP_I2SDIV_2 (0x3U << 10)
+
+
+/* =========================================================================================================================== */
+/* ================ DEBUG ================ */
+/* =========================================================================================================================== */
+
+/****************** Bit definition for DEBUG_APB1_PAUSE register **************/
+#define DEBUG_APB1_PAUSE_TMR2_PAUSE (0x1U << 0)
+#define DEBUG_APB1_PAUSE_TMR3_PAUSE (0x1U << 1)
+#define DEBUG_APB1_PAUSE_TMR4_PAUSE (0x1U << 2)
+#define DEBUG_APB1_PAUSE_TMR6_PAUSE (0x1U << 4)
+#define DEBUG_APB1_PAUSE_TMR7_PAUSE (0x1U << 5)
+#define DEBUG_APB1_PAUSE_TMR13_PAUSE (0x1U << 7)
+#define DEBUG_APB1_PAUSE_TMR14_PAUSE (0x1U << 8)
+#define DEBUG_APB1_PAUSE_ERTC_PAUSE (0x1U << 10)
+#define DEBUG_APB1_PAUSE_WWDT_PAUSE (0x1U << 11)
+#define DEBUG_APB1_PAUSE_WDT_PAUSE (0x1U << 12)
+#define DEBUG_APB1_PAUSE_I2C1_SMBUS_TIMEOUT (0x1U << 24)
+#define DEBUG_APB1_PAUSE_CAN1_PAUSE (0x1U << 25)
+#define DEBUG_APB1_PAUSE_I2C2_SMBUS_TIMEOUT (0x1U << 27)
+#define DEBUG_APB1_PAUSE_I2C3_SMBUS_TIMEOUT (0x1U << 28)
+
+/****************** Bit definition for DEBUG_APB2_PAUSE register **************/
+#define DEBUG_APB2_PAUSE_TMR1_PAUSE (0x1U << 0)
+#define DEBUG_APB2_PAUSE_TMR9_PAUSE (0x1U << 16)
+#define DEBUG_APB2_PAUSE_TMR10_PAUSE (0x1U << 17)
+#define DEBUG_APB2_PAUSE_TMR11_PAUSE (0x1U << 18)
+
+/**
+ * @}
+ */
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/os/common/startup/ARMCMx/compilers/GCC/ld/AT32F405xB.ld b/os/common/startup/ARMCMx/compilers/GCC/ld/AT32F405xB.ld
new file mode 100644
index 0000000000..bc182b3840
--- /dev/null
+++ b/os/common/startup/ARMCMx/compilers/GCC/ld/AT32F405xB.ld
@@ -0,0 +1,85 @@
+/*
+ COPYRIGHT(C) 2023, Artery
+
+ Licensed 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.
+*/
+
+/*
+ * AT32F402_405xB memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 128k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 64k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/os/common/startup/ARMCMx/compilers/GCC/ld/AT32F405xC.ld b/os/common/startup/ARMCMx/compilers/GCC/ld/AT32F405xC.ld
new file mode 100644
index 0000000000..758f2285e4
--- /dev/null
+++ b/os/common/startup/ARMCMx/compilers/GCC/ld/AT32F405xC.ld
@@ -0,0 +1,85 @@
+/*
+ COPYRIGHT(C) 2023, Artery
+
+ Licensed 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.
+*/
+
+/*
+ * AT32F402_405xC memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 256k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 96k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/os/common/startup/ARMCMx/compilers/GCC/mk/startup_at32f405xx.mk b/os/common/startup/ARMCMx/compilers/GCC/mk/startup_at32f405xx.mk
new file mode 100644
index 0000000000..ac07851b44
--- /dev/null
+++ b/os/common/startup/ARMCMx/compilers/GCC/mk/startup_at32f405xx.mk
@@ -0,0 +1,19 @@
+# List of the ChibiOS generic AT32F402_405 startup and CMSIS files.
+STARTUPSRC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt1.c
+
+STARTUPASM = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt0_v7m.S \
+ $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/vectors.S \
+
+STARTUPINC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC \
+ $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/ld \
+ $(CHIBIOS_CONTRIB)/os/common/startup/ARMCMx/devices/AT32F402_405xx \
+ $(CHIBIOS)/os/common/ext/ARM/CMSIS/Core/Include \
+ $(CHIBIOS_CONTRIB)/os/common/ext/CMSIS/ArteryTek/AT32F402_405xx
+
+STARTUPLD = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/ld
+STARTUPLD_CONTRIB = $(CHIBIOS_CONTRIB)/os/common/startup/ARMCMx/compilers/GCC/ld
+
+# Shared variables
+ALLXASMSRC += $(STARTUPASM)
+ALLCSRC += $(STARTUPSRC)
+ALLINC += $(STARTUPINC)
\ No newline at end of file
diff --git a/os/common/startup/ARMCMx/devices/AT32F402_405xx/cmparams.h b/os/common/startup/ARMCMx/devices/AT32F402_405xx/cmparams.h
new file mode 100644
index 0000000000..3b4ed7770d
--- /dev/null
+++ b/os/common/startup/ARMCMx/devices/AT32F402_405xx/cmparams.h
@@ -0,0 +1,88 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2014 Giovanni Di Sirio.
+ ChibiOS/RT - Copyright (C) 2023..2024 Zhaqian
+ ChibiOS/RT - Copyright (C) 2023..2024 Maxjta
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file AT32F402_405xx/cmparams.h
+ * @brief ARM Cortex-M4 parameters for the ArteryTek AT32F402_405
+ *
+ * @defgroup ARMCMx_AT32F402_405 ArteryTek AT32F402_405 Specific Parameters
+ * @ingroup ARMCMx_SPECIFIC
+ * @details This file contains the Cortex-M4 specific parameters for the
+ * ArteryTek AT32F402_405 platform.
+ * @{
+ */
+
+#ifndef _CMPARAMS_H_
+#define _CMPARAMS_H_
+
+/**
+ * @brief Cortex core model.
+ */
+#define CORTEX_MODEL 4
+
+/**
+ * @brief Systick unit presence.
+ */
+#define CORTEX_HAS_ST TRUE
+
+/**
+ * @brief Floating Point unit presence.
+ */
+#define CORTEX_HAS_FPU TRUE
+
+/**
+ * @brief Number of bits in priority masks.
+ */
+#define CORTEX_PRIORITY_BITS 4
+
+/**
+ * @brief Number of interrupt vectors.
+ * @note This number does not include the 16 system vectors and must be
+ * rounded to a multiple of 8.
+ */
+#define CORTEX_NUM_VECTORS 112
+
+/* The following code is not processed when the file is included from an
+ asm module.*/
+#if !defined(_FROM_ASM_)
+
+#if !defined (AT32F405xx) && !defined (AT32F402xx)
+ #include "board.h"
+#endif
+
+/* Including the device CMSIS header. Note, we are not using the definitions
+ from this header because we need this file to be usable also from
+ assembler source files. We verify that the info matches instead.*/
+#include "at32f402_405xx.h"
+
+#if CORTEX_MODEL != __CORTEX_M
+#error "CMSIS __CORTEX_M mismatch"
+#endif
+
+#if CORTEX_PRIORITY_BITS != __NVIC_PRIO_BITS
+#error "CMSIS __NVIC_PRIO_BITS mismatch"
+#endif
+
+#endif /* !defined(_FROM_ASM_) */
+
+#endif /* _CMPARAMS_H_ */
+
+/** @} */
diff --git a/os/hal/boards/AT_START_F405/board.c b/os/hal/boards/AT_START_F405/board.c
new file mode 100644
index 0000000000..346e5194fb
--- /dev/null
+++ b/os/hal/boards/AT_START_F405/board.c
@@ -0,0 +1,186 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+ ChibiOS - Copyright (C) 2023..2024 HorrorTroll
+ ChibiOS - Copyright (C) 2023..2024 Zhaqian
+ ChibiOS - Copyright (C) 2003..2024 Maxjta
+
+ Licensed 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 "hal.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+/**
+ * @brief Type of AT32 GPIO port setup.
+ */
+typedef struct {
+ uint32_t cfgr;
+ uint32_t omode;
+ uint32_t odrvr;
+ uint32_t pull;
+ uint32_t odt;
+ uint32_t muxl;
+ uint32_t muxh;
+ uint32_t hdrv;
+} gpio_setup_t;
+
+
+/**
+ * @brief Type of AT32 GPIO initialization data.
+ */
+typedef struct {
+#if AT32_HAS_GPIOA || defined(__DOXYGEN__)
+ gpio_setup_t PAData;
+#endif
+#if AT32_HAS_GPIOB || defined(__DOXYGEN__)
+ gpio_setup_t PBData;
+#endif
+#if AT32_HAS_GPIOC || defined(__DOXYGEN__)
+ gpio_setup_t PCData;
+#endif
+#if AT32_HAS_GPIOD || defined(__DOXYGEN__)
+ gpio_setup_t PDData;
+#endif
+#if AT32_HAS_GPIOF || defined(__DOXYGEN__)
+ gpio_setup_t PFData;
+#endif
+} gpio_config_t;
+
+/**
+ * @brief AT32 GPIO static initialization data.
+ */
+static const gpio_config_t gpio_default_config = {
+#if AT32_HAS_GPIOA
+ {VAL_GPIOA_MODE, VAL_GPIOA_OUTPUT, VAL_GPIOA_ODRVR, VAL_GPIOA_PULL,
+ VAL_GPIOA_ODT, VAL_GPIOA_MUXL, VAL_GPIOA_MUXH, VAL_GPIOA_HDRV},
+#endif
+#if AT32_HAS_GPIOB
+ {VAL_GPIOB_MODE, VAL_GPIOB_OUTPUT, VAL_GPIOB_ODRVR, VAL_GPIOB_PULL,
+ VAL_GPIOB_ODT, VAL_GPIOB_MUXL, VAL_GPIOB_MUXH, VAL_GPIOB_HDRV},
+#endif
+#if AT32_HAS_GPIOC
+ {VAL_GPIOC_MODE, VAL_GPIOC_OUTPUT, VAL_GPIOC_ODRVR, VAL_GPIOC_PULL,
+ VAL_GPIOC_ODT, VAL_GPIOC_MUXL, VAL_GPIOC_MUXH, VAL_GPIOC_HDRV},
+#endif
+#if AT32_HAS_GPIOD
+ {VAL_GPIOD_MODE, VAL_GPIOD_OUTPUT, VAL_GPIOD_ODRVR, VAL_GPIOD_PULL,
+ VAL_GPIOD_ODT, VAL_GPIOD_MUXL, VAL_GPIOD_MUXH, VAL_GPIOD_HDRV},
+#endif
+#if AT32_HAS_GPIOF
+ {VAL_GPIOF_MODE, VAL_GPIOF_OUTPUT, VAL_GPIOF_ODRVR, VAL_GPIOF_PULL,
+ VAL_GPIOF_ODT, VAL_GPIOF_MUXL, VAL_GPIOF_MUXH, VAL_GPIOF_HDRV},
+#endif
+};
+
+/**
+ * @brief PAL setup.
+ * @details Digital I/O ports static configuration as defined in @p board.h.
+ * This variable is used by the HAL when initializing the PAL driver.
+ */
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+static void gpio_init_lld(at32_gpio_t *gpiop, const gpio_setup_t *config) {
+
+ gpiop->OMODE = config->omode;
+ gpiop->ODRVR = config->odrvr;
+ gpiop->PULL = config->pull;
+ gpiop->ODT = config->odt;
+ gpiop->MUXL = config->muxl;
+ gpiop->MUXH = config->muxh;
+ gpiop->CFGR = config->cfgr;
+ gpiop->HDRV = config->hdrv;
+
+}
+
+static void at32_gpio_init(void) {
+
+ /* Enabling GPIO-related clocks, the mask comes from the
+ registry header file.*/
+ crmEnableAHB1(AT32_GPIO_EN_MASK, false);
+ crmResetAHB1(AT32_GPIO_EN_MASK);
+
+ /* Initializing all the defined GPIO ports.*/
+#if AT32_HAS_GPIOA
+ gpio_init_lld(GPIOA, &gpio_default_config.PAData);
+#endif
+#if AT32_HAS_GPIOB
+ gpio_init_lld(GPIOB, &gpio_default_config.PBData);
+#endif
+#if AT32_HAS_GPIOC
+ gpio_init_lld(GPIOC, &gpio_default_config.PCData);
+#endif
+#if AT32_HAS_GPIOD
+ gpio_init_lld(GPIOD, &gpio_default_config.PDData);
+#endif
+#if AT32_HAS_GPIOF
+ gpio_init_lld(GPIOF, &gpio_default_config.PFData);
+#endif
+}
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Early initialization code.
+ * @details System clocks are initialized before everything else.
+ */
+void __early_init(void) {
+ at32_clock_init();
+ at32_gpio_init();
+}
+
+#if HAL_USE_SDC || defined(__DOXYGEN__)
+/**
+ * @brief SDC card detection.
+ */
+bool sdc_lld_is_card_inserted(SDCDriver *sdcp) {
+ static bool last_status = false;
+
+ if (blkIsTransferring(sdcp))
+ return last_status;
+ return last_status = (bool)palReadPad(GPIOA, GPIOA_ARD_A2);
+}
+
+/**
+ * @brief SDC card write protection detection.
+ */
+bool sdc_lld_is_write_protected(SDCDriver *sdcp) {
+
+ (void)sdcp;
+ return false;
+}
+#endif /* HAL_USE_SDC */
+
+/**
+ * @brief Board-specific initialization code.
+ * @note You can add your board-specific code here.
+ */
+void boardInit(void) {
+
+}
diff --git a/os/hal/boards/AT_START_F405/board.h b/os/hal/boards/AT_START_F405/board.h
new file mode 100644
index 0000000000..c38edc6ff7
--- /dev/null
+++ b/os/hal/boards/AT_START_F405/board.h
@@ -0,0 +1,682 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+ ChibiOS - Copyright (C) 2023..2024 HorrorTroll
+ ChibiOS - Copyright (C) 2023..2024 Zhaqian
+ ChibiOS - Copyright (C) 2023..2024 Maxjta
+
+ Licensed 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 _BOARD_H_
+#define _BOARD_H_
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*
+ * Setup for a AT-START-F405 board.
+ */
+
+/*
+ * Board identifier.
+ */
+#define BOARD_AT_START_F405
+#define BOARD_NAME "Artery AT-START-F405"
+
+/*
+ * Board oscillators-related settings.
+ */
+#if !defined(AT32_LEXTCLK)
+#define AT32_LEXTCLK 32768
+#endif
+
+#if !defined(AT32_HEXTCLK)
+#define AT32_HEXTCLK 12000000
+#endif
+
+/*
+ * MCU type, supported types are defined in ./os/hal/platforms/hal_lld.h.
+ */
+#define AT32F405RCT7
+
+/*
+ * IO pins assignments.
+ */
+#define GPIOA_BUTTON 0U
+#define GPIOA_PIN1 1U
+#define GPIOA_PIN2 2U
+#define GPIOA_PIN3 3U
+#define GPIOA_PIN4 4U
+#define GPIOA_PIN5 5U
+#define GPIOA_PIN6 6U
+#define GPIOA_PIN7 7U
+#define GPIOA_PIN8 8U
+#define GPIOA_PIN9 9U
+#define GPIOA_PIN10 10U
+#define GPIOA_PIN11 11U
+#define GPIOA_PIN12 12U
+#define GPIOA_SWDIO 13U
+#define GPIOA_SWCLK 14U
+#define GPIOA_PIN15 15U
+
+#define GPIOB_PIN0 0U
+#define GPIOB_PIN1 1U
+#define GPIOB_PIN2 2U
+#define GPIOB_PIN3 3U
+#define GPIOB_PIN4 4U
+#define GPIOB_PIN5 5U
+#define GPIOB_PIN6 6U
+#define GPIOB_PIN7 7U
+#define GPIOB_PIN8 8U
+#define GPIOB_PIN9 9U
+#define GPIOB_PIN10 10U
+#define GPIOB_PIN11 11U
+#define GPIOB_PIN12 12U
+#define GPIOB_PIN13 13U
+#define GPIOB_PIN14 14U
+#define GPIOB_PIN15 15U
+
+#define GPIOC_PIN0 0U
+#define GPIOC_PIN1 1U
+#define GPIOC_PIN2 2U
+#define GPIOC_PIN3 3U
+#define GPIOC_PIN4 4U
+#define GPIOC_PIN5 5U
+#define GPIOC_PIN6 6U
+#define GPIOC_PIN7 7U
+#define GPIOC_PIN8 8U
+#define GPIOC_PIN9 9U
+#define GPIOC_PIN10 10U
+#define GPIOC_PIN11 11U
+#define GPIOC_PIN12 12U
+#define GPIOC_PIN13 13U
+#define GPIOC_PIN14 14U
+#define GPIOC_PIN15 15U
+
+#define GPIOD_PIN2 15U
+
+#define GPIOF_HEXT_IN 0U
+#define GPIOF_HEXT_OUT 1U
+#define GPIOF_PIN4 4U
+#define GPIOF_PIN5 5U
+#define GPIOF_PIN6 6U
+#define GPIOF_PIN7 7U
+#define GPIOF_PIN11 11U
+
+
+/*
+ * IO lines assignments.
+ */
+#define LINE_BUTTON PAL_LINE(GPIOA, 0U)
+#define LINE_LED_RED PAL_LINE(GPIOF, 4U)
+#define LINE_LED_YELLOW PAL_LINE(GPIOF, 5U)
+#define LINE_LED_GREEN PAL_LINE(GPIOF, 6U)
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+
+/*
+ * I/O ports initial setup, this configuration is established soon after reset
+ * in the initialization code.
+ * Please refer to the AT32 Reference Manual for details.
+ */
+#define PIN_MODE_INPUT(n) (0U << ((n) * 2U))
+#define PIN_MODE_OUTPUT(n) (1U << ((n) * 2U))
+#define PIN_MODE_MUX(n) (2U << ((n) * 2U))
+#define PIN_MODE_ANALOG(n) (3U << ((n) * 2U))
+#define PIN_ODT_LOW(n) (0U << (n))
+#define PIN_ODT_HIGH(n) (1U << (n))
+#define PIN_OUTPUT_PUSHPULL(n) (0U << (n))
+#define PIN_OUTPUT_OPENDRAIN(n) (1U << (n))
+#define PIN_ODRVR_STRONGER(n) (1U << ((n) * 2U))
+#define PIN_ODRVR_MODERATE(n) (2U << ((n) * 2U))
+#define PIN_PULL_NONE(n) (0U << ((n) * 2U))
+#define PIN_PULL_UP(n) (1U << ((n) * 2U))
+#define PIN_PULL_DOWN(n) (2U << ((n) * 2U))
+#define PIN_MUX(n, v) ((v) << (((n) % 8U) * 4U))
+#define PIN_HDRV_NOTACTIVE(n) (0U << (n))
+#define PIN_HDRV_ACTIVE(n) (1U << (n))
+
+
+/*
+ * GPIOA setup:
+ *
+ * PA0 - PIN0 (output none pull).
+ * PA1 - PIN1 (input none pull).
+ * PA2 - PIN2 (input none pull).
+ * PA3 - PIN3 (input none pull).
+ * PA4 - PIN4 (input none pull).
+ * PA5 - PIN5 (input none pull).
+ * PA6 - PIN6 (input none pull).
+ * PA7 - PIN7 (input none pull).
+ * PA8 - PIN8 (input none pull).
+ * PA9 - PIN9 (mux 7).
+ * PA10 - PIN10 (mux 7).
+ * PA11 - PIN11 (input none pull).
+ * PA12 - PIN12 (input none pull).
+ * PA13 - SWDIO (mux 0).
+ * PA14 - SWCLK (mux 0).
+ * PA15 - PIN15 (input none pull).
+ */
+#define VAL_GPIOA_MODE (PIN_MODE_INPUT(GPIOA_BUTTON) | \
+ PIN_MODE_INPUT(GPIOA_PIN1) | \
+ PIN_MODE_INPUT(GPIOA_PIN2) | \
+ PIN_MODE_INPUT(GPIOA_PIN3) | \
+ PIN_MODE_INPUT(GPIOA_PIN4) | \
+ PIN_MODE_INPUT(GPIOA_PIN5) | \
+ PIN_MODE_INPUT(GPIOA_PIN6) | \
+ PIN_MODE_INPUT(GPIOA_PIN7) | \
+ PIN_MODE_INPUT(GPIOA_PIN8) | \
+ PIN_MODE_MUX(GPIOA_PIN9) | \
+ PIN_MODE_MUX(GPIOA_PIN10) | \
+ PIN_MODE_INPUT(GPIOA_PIN11) | \
+ PIN_MODE_INPUT(GPIOA_PIN12) | \
+ PIN_MODE_MUX(GPIOA_SWDIO) | \
+ PIN_MODE_MUX(GPIOA_SWCLK) | \
+ PIN_MODE_INPUT(GPIOA_PIN15))
+
+#define VAL_GPIOA_ODT (PIN_ODT_HIGH(GPIOA_BUTTON) | \
+ PIN_ODT_HIGH(GPIOA_PIN1) | \
+ PIN_ODT_HIGH(GPIOA_PIN2) | \
+ PIN_ODT_HIGH(GPIOA_PIN3) | \
+ PIN_ODT_HIGH(GPIOA_PIN4) | \
+ PIN_ODT_HIGH(GPIOA_PIN5) | \
+ PIN_ODT_HIGH(GPIOA_PIN6) | \
+ PIN_ODT_HIGH(GPIOA_PIN7) | \
+ PIN_ODT_HIGH(GPIOA_PIN8) | \
+ PIN_ODT_HIGH(GPIOA_PIN9) | \
+ PIN_ODT_HIGH(GPIOA_PIN10) | \
+ PIN_ODT_HIGH(GPIOA_PIN11) | \
+ PIN_ODT_HIGH(GPIOA_PIN12) | \
+ PIN_ODT_HIGH(GPIOA_SWDIO) | \
+ PIN_ODT_HIGH(GPIOA_SWCLK) | \
+ PIN_ODT_HIGH(GPIOA_PIN15))
+
+#define VAL_GPIOA_OUTPUT (PIN_OUTPUT_PUSHPULL(GPIOA_BUTTON) | \
+ PIN_OUTPUT_PUSHPULL(GPIOA_PIN1) | \
+ PIN_OUTPUT_PUSHPULL(GPIOA_PIN2) | \
+ PIN_OUTPUT_PUSHPULL(GPIOA_PIN3) | \
+ PIN_OUTPUT_PUSHPULL(GPIOA_PIN4) | \
+ PIN_OUTPUT_PUSHPULL(GPIOA_PIN5) | \
+ PIN_OUTPUT_PUSHPULL(GPIOA_PIN6) | \
+ PIN_OUTPUT_PUSHPULL(GPIOA_PIN7) | \
+ PIN_OUTPUT_PUSHPULL(GPIOA_PIN8) | \
+ PIN_OUTPUT_PUSHPULL(GPIOA_PIN9) | \
+ PIN_OUTPUT_PUSHPULL(GPIOA_PIN10) | \
+ PIN_OUTPUT_PUSHPULL(GPIOA_PIN11) | \
+ PIN_OUTPUT_PUSHPULL(GPIOA_PIN12) | \
+ PIN_OUTPUT_PUSHPULL(GPIOA_SWDIO) | \
+ PIN_OUTPUT_PUSHPULL(GPIOA_SWCLK) | \
+ PIN_OUTPUT_PUSHPULL(GPIOA_PIN15))
+
+#define VAL_GPIOA_ODRVR (PIN_ODRVR_STRONGER(GPIOA_BUTTON) | \
+ PIN_ODRVR_STRONGER(GPIOA_PIN1) | \
+ PIN_ODRVR_STRONGER(GPIOA_PIN2) | \
+ PIN_ODRVR_STRONGER(GPIOA_PIN3) | \
+ PIN_ODRVR_STRONGER(GPIOA_PIN4) | \
+ PIN_ODRVR_STRONGER(GPIOA_PIN5) | \
+ PIN_ODRVR_STRONGER(GPIOA_PIN6) | \
+ PIN_ODRVR_STRONGER(GPIOA_PIN7) | \
+ PIN_ODRVR_STRONGER(GPIOA_PIN8) | \
+ PIN_ODRVR_STRONGER(GPIOA_PIN9) | \
+ PIN_ODRVR_STRONGER(GPIOA_PIN10) | \
+ PIN_ODRVR_STRONGER(GPIOA_PIN11) | \
+ PIN_ODRVR_STRONGER(GPIOA_PIN12) | \
+ PIN_ODRVR_STRONGER(GPIOA_SWDIO) | \
+ PIN_ODRVR_STRONGER(GPIOA_SWCLK) | \
+ PIN_ODRVR_STRONGER(GPIOA_PIN15))
+
+#define VAL_GPIOA_PULL (PIN_PULL_NONE(GPIOA_BUTTON) | \
+ PIN_PULL_NONE(GPIOA_PIN1) | \
+ PIN_PULL_NONE(GPIOA_PIN2) | \
+ PIN_PULL_NONE(GPIOA_PIN3) | \
+ PIN_PULL_NONE(GPIOA_PIN4) | \
+ PIN_PULL_NONE(GPIOA_PIN5) | \
+ PIN_PULL_NONE(GPIOA_PIN6) | \
+ PIN_PULL_NONE(GPIOA_PIN7) | \
+ PIN_PULL_NONE(GPIOA_PIN8) | \
+ PIN_PULL_NONE(GPIOA_PIN9) | \
+ PIN_PULL_NONE(GPIOA_PIN10) | \
+ PIN_PULL_NONE(GPIOA_PIN11) | \
+ PIN_PULL_NONE(GPIOA_PIN12) | \
+ PIN_PULL_NONE(GPIOA_SWDIO) | \
+ PIN_PULL_NONE(GPIOA_SWCLK) | \
+ PIN_PULL_NONE(GPIOA_PIN15))
+
+#define VAL_GPIOA_MUXL (PIN_MUX(GPIOA_BUTTON, 0U) | \
+ PIN_MUX(GPIOA_PIN1, 0U) | \
+ PIN_MUX(GPIOA_PIN2, 0U) | \
+ PIN_MUX(GPIOA_PIN3, 0U) | \
+ PIN_MUX(GPIOA_PIN4, 5U) | \
+ PIN_MUX(GPIOA_PIN5, 5U) | \
+ PIN_MUX(GPIOA_PIN6, 5U) | \
+ PIN_MUX(GPIOA_PIN7, 5U))
+
+#define VAL_GPIOA_MUXH (PIN_MUX(GPIOA_PIN8, 0U) | \
+ PIN_MUX(GPIOA_PIN9, 7U) | \
+ PIN_MUX(GPIOA_PIN10, 7U) | \
+ PIN_MUX(GPIOA_PIN11, 0U) | \
+ PIN_MUX(GPIOA_PIN12, 0U) | \
+ PIN_MUX(GPIOA_SWDIO, 0U) | \
+ PIN_MUX(GPIOA_SWCLK, 0U) | \
+ PIN_MUX(GPIOA_PIN15, 0U))
+
+#define VAL_GPIOA_HDRV (PIN_HDRV_NOTACTIVE(GPIOA_BUTTON) | \
+ PIN_HDRV_NOTACTIVE(GPIOA_PIN1) | \
+ PIN_HDRV_NOTACTIVE(GPIOA_PIN2) | \
+ PIN_HDRV_NOTACTIVE(GPIOA_PIN3) | \
+ PIN_HDRV_NOTACTIVE(GPIOA_PIN4) | \
+ PIN_HDRV_NOTACTIVE(GPIOA_PIN5) | \
+ PIN_HDRV_NOTACTIVE(GPIOA_PIN6) | \
+ PIN_HDRV_NOTACTIVE(GPIOA_PIN7) | \
+ PIN_HDRV_NOTACTIVE(GPIOA_PIN8) | \
+ PIN_HDRV_NOTACTIVE(GPIOA_PIN9) | \
+ PIN_HDRV_NOTACTIVE(GPIOA_PIN10) | \
+ PIN_HDRV_NOTACTIVE(GPIOA_PIN11) | \
+ PIN_HDRV_NOTACTIVE(GPIOA_PIN12) | \
+ PIN_HDRV_NOTACTIVE(GPIOA_SWDIO) | \
+ PIN_HDRV_NOTACTIVE(GPIOA_SWCLK) | \
+ PIN_HDRV_NOTACTIVE(GPIOA_PIN15))
+/*
+ * GPIOB setup:
+ *
+ * PB0 - PIN0 (input none pull).
+ * PB1 - PIN1 (input none pull).
+ * PB2 - PIN2 (input none pull).
+ * PB3 - PIN3 (input none pull).
+ * PB4 - PIN4 (input none pull).
+ * PB5 - PIN5 (input none pull).
+ * PB6 - PIN6 (input none pull).
+ * PB7 - PIN7 (input none pull).
+ * PB8 - PIN8 (input none pull).
+ * PB9 - PIN9 (input none pull).
+ * PB10 - PIN10 (input none pull).
+ * PB11 - PIN11 (input none pull).
+ * PB12 - PIN12 (input none pull).
+ * PB13 - PIN13 (input none pull).
+ * PB14 - PIN14 (input none pull).
+ * PB15 - PIN15 (input none pull).
+ */
+#define VAL_GPIOB_MODE (PIN_MODE_INPUT(GPIOB_PIN0) | \
+ PIN_MODE_INPUT(GPIOB_PIN1) | \
+ PIN_MODE_INPUT(GPIOB_PIN2) | \
+ PIN_MODE_INPUT(GPIOB_PIN3) | \
+ PIN_MODE_INPUT(GPIOB_PIN4) | \
+ PIN_MODE_INPUT(GPIOB_PIN5) | \
+ PIN_MODE_INPUT(GPIOB_PIN6) | \
+ PIN_MODE_INPUT(GPIOB_PIN7) | \
+ PIN_MODE_INPUT(GPIOB_PIN8) | \
+ PIN_MODE_INPUT(GPIOB_PIN9) | \
+ PIN_MODE_INPUT(GPIOB_PIN10) | \
+ PIN_MODE_INPUT(GPIOB_PIN11) | \
+ PIN_MODE_INPUT(GPIOB_PIN12) | \
+ PIN_MODE_INPUT(GPIOB_PIN13) | \
+ PIN_MODE_INPUT(GPIOB_PIN14) | \
+ PIN_MODE_INPUT(GPIOB_PIN15))
+
+#define VAL_GPIOB_ODT (PIN_ODT_HIGH(GPIOB_PIN0) | \
+ PIN_ODT_HIGH(GPIOB_PIN1) | \
+ PIN_ODT_HIGH(GPIOB_PIN2) | \
+ PIN_ODT_HIGH(GPIOB_PIN3) | \
+ PIN_ODT_HIGH(GPIOB_PIN4) | \
+ PIN_ODT_HIGH(GPIOB_PIN5) | \
+ PIN_ODT_HIGH(GPIOB_PIN6) | \
+ PIN_ODT_HIGH(GPIOB_PIN7) | \
+ PIN_ODT_HIGH(GPIOB_PIN8) | \
+ PIN_ODT_HIGH(GPIOB_PIN9) | \
+ PIN_ODT_HIGH(GPIOB_PIN10) | \
+ PIN_ODT_HIGH(GPIOB_PIN11) | \
+ PIN_ODT_HIGH(GPIOB_PIN12) | \
+ PIN_ODT_HIGH(GPIOB_PIN13) | \
+ PIN_ODT_HIGH(GPIOB_PIN14) | \
+ PIN_ODT_HIGH(GPIOB_PIN15))
+
+#define VAL_GPIOB_OUTPUT (PIN_OUTPUT_PUSHPULL(GPIOB_PIN0) | \
+ PIN_OUTPUT_PUSHPULL(GPIOB_PIN1) | \
+ PIN_OUTPUT_PUSHPULL(GPIOB_PIN2) | \
+ PIN_OUTPUT_PUSHPULL(GPIOB_PIN3) | \
+ PIN_OUTPUT_PUSHPULL(GPIOB_PIN4) | \
+ PIN_OUTPUT_PUSHPULL(GPIOB_PIN5) | \
+ PIN_OUTPUT_PUSHPULL(GPIOB_PIN6) | \
+ PIN_OUTPUT_PUSHPULL(GPIOB_PIN7) | \
+ PIN_OUTPUT_PUSHPULL(GPIOB_PIN8) | \
+ PIN_OUTPUT_PUSHPULL(GPIOB_PIN9) | \
+ PIN_OUTPUT_PUSHPULL(GPIOB_PIN10) | \
+ PIN_OUTPUT_PUSHPULL(GPIOB_PIN11) | \
+ PIN_OUTPUT_PUSHPULL(GPIOB_PIN12) | \
+ PIN_OUTPUT_PUSHPULL(GPIOB_PIN13) | \
+ PIN_OUTPUT_PUSHPULL(GPIOB_PIN14) | \
+ PIN_OUTPUT_PUSHPULL(GPIOB_PIN15))
+
+#define VAL_GPIOB_ODRVR (PIN_ODRVR_STRONGER(GPIOB_PIN0) | \
+ PIN_ODRVR_STRONGER(GPIOB_PIN1) | \
+ PIN_ODRVR_STRONGER(GPIOB_PIN2) | \
+ PIN_ODRVR_STRONGER(GPIOB_PIN3) | \
+ PIN_ODRVR_STRONGER(GPIOB_PIN4) | \
+ PIN_ODRVR_STRONGER(GPIOB_PIN5) | \
+ PIN_ODRVR_STRONGER(GPIOB_PIN6) | \
+ PIN_ODRVR_STRONGER(GPIOB_PIN7) | \
+ PIN_ODRVR_STRONGER(GPIOB_PIN8) | \
+ PIN_ODRVR_STRONGER(GPIOB_PIN9) | \
+ PIN_ODRVR_STRONGER(GPIOB_PIN10) | \
+ PIN_ODRVR_STRONGER(GPIOB_PIN11) | \
+ PIN_ODRVR_STRONGER(GPIOB_PIN12) | \
+ PIN_ODRVR_STRONGER(GPIOB_PIN13) | \
+ PIN_ODRVR_STRONGER(GPIOB_PIN14) | \
+ PIN_ODRVR_STRONGER(GPIOB_PIN15))
+
+#define VAL_GPIOB_PULL (PIN_PULL_NONE(GPIOB_PIN0) | \
+ PIN_PULL_NONE(GPIOB_PIN1) | \
+ PIN_PULL_NONE(GPIOB_PIN2) | \
+ PIN_PULL_NONE(GPIOB_PIN3) | \
+ PIN_PULL_NONE(GPIOB_PIN4) | \
+ PIN_PULL_NONE(GPIOB_PIN5) | \
+ PIN_PULL_NONE(GPIOB_PIN6) | \
+ PIN_PULL_NONE(GPIOB_PIN7) | \
+ PIN_PULL_NONE(GPIOB_PIN8) | \
+ PIN_PULL_NONE(GPIOB_PIN9) | \
+ PIN_PULL_NONE(GPIOB_PIN10) | \
+ PIN_PULL_NONE(GPIOB_PIN11) | \
+ PIN_PULL_NONE(GPIOB_PIN12) | \
+ PIN_PULL_NONE(GPIOB_PIN13) | \
+ PIN_PULL_NONE(GPIOB_PIN14) | \
+ PIN_PULL_NONE(GPIOB_PIN15))
+
+#define VAL_GPIOB_MUXL (PIN_MUX(GPIOB_PIN0, 0U) | \
+ PIN_MUX(GPIOB_PIN1, 0U) | \
+ PIN_MUX(GPIOB_PIN2, 0U) | \
+ PIN_MUX(GPIOB_PIN3, 0U) | \
+ PIN_MUX(GPIOB_PIN4, 0U) | \
+ PIN_MUX(GPIOB_PIN5, 0U) | \
+ PIN_MUX(GPIOB_PIN6, 0U) | \
+ PIN_MUX(GPIOB_PIN7, 0U))
+
+#define VAL_GPIOB_MUXH (PIN_MUX(GPIOB_PIN8, 0U) | \
+ PIN_MUX(GPIOB_PIN9, 0U) | \
+ PIN_MUX(GPIOB_PIN10, 0U) | \
+ PIN_MUX(GPIOB_PIN11, 0U) | \
+ PIN_MUX(GPIOB_PIN12, 0U) | \
+ PIN_MUX(GPIOB_PIN13, 0U) | \
+ PIN_MUX(GPIOB_PIN14, 0U) | \
+ PIN_MUX(GPIOB_PIN15, 0U))
+
+#define VAL_GPIOB_HDRV (PIN_HDRV_NOTACTIVE(GPIOB_PIN0) | \
+ PIN_HDRV_NOTACTIVE(GPIOB_PIN1) | \
+ PIN_HDRV_NOTACTIVE(GPIOB_PIN2) | \
+ PIN_HDRV_NOTACTIVE(GPIOB_PIN3) | \
+ PIN_HDRV_NOTACTIVE(GPIOB_PIN4) | \
+ PIN_HDRV_NOTACTIVE(GPIOB_PIN5) | \
+ PIN_HDRV_NOTACTIVE(GPIOB_PIN6) | \
+ PIN_HDRV_NOTACTIVE(GPIOB_PIN7) | \
+ PIN_HDRV_NOTACTIVE(GPIOB_PIN8) | \
+ PIN_HDRV_NOTACTIVE(GPIOB_PIN9) | \
+ PIN_HDRV_NOTACTIVE(GPIOB_PIN10) | \
+ PIN_HDRV_NOTACTIVE(GPIOB_PIN11) | \
+ PIN_HDRV_NOTACTIVE(GPIOB_PIN12) | \
+ PIN_HDRV_NOTACTIVE(GPIOB_PIN13) | \
+ PIN_HDRV_NOTACTIVE(GPIOB_PIN14) | \
+ PIN_HDRV_NOTACTIVE(GPIOB_PIN15))
+
+/*
+ * GPIOC setup:
+ *
+ * PC0 - PIN0 (input none pull).
+ * PC1 - PIN1 (input none pull).
+ * PC2 - PIN2 (input none pull).
+ * PC3 - PIN3 (input none pull).
+ * PC4 - PIN4 (input none pull).
+ * PC5 - PIN5 (input none pull).
+ * PC6 - PIN6 (input none pull).
+ * PC7 - PIN7 (input none pull).
+ * PC8 - PIN8 (input none pull).
+ * PC9 - PIN9 (input none pull).
+ * PC10 - PIN10 (input none pull).
+ * PC11 - PIN11 (input none pull).
+ * PC12 - PIN12 (input none pull).
+ * PC13 - PIN13 (input none pull).
+ * PC14 - PIN14 (input none pull).
+ * PC15 - PIN15 (input none pull).
+ */
+#define VAL_GPIOC_MODE (PIN_MODE_INPUT(GPIOC_PIN0) | \
+ PIN_MODE_INPUT(GPIOC_PIN1) | \
+ PIN_MODE_INPUT(GPIOC_PIN2) | \
+ PIN_MODE_INPUT(GPIOC_PIN3) | \
+ PIN_MODE_INPUT(GPIOC_PIN4) | \
+ PIN_MODE_INPUT(GPIOC_PIN5) | \
+ PIN_MODE_INPUT(GPIOC_PIN6) | \
+ PIN_MODE_INPUT(GPIOC_PIN7) | \
+ PIN_MODE_INPUT(GPIOC_PIN8) | \
+ PIN_MODE_INPUT(GPIOC_PIN9) | \
+ PIN_MODE_INPUT(GPIOC_PIN10) | \
+ PIN_MODE_INPUT(GPIOC_PIN11) | \
+ PIN_MODE_INPUT(GPIOC_PIN12) | \
+ PIN_MODE_INPUT(GPIOC_PIN13) | \
+ PIN_MODE_INPUT(GPIOC_PIN14) | \
+ PIN_MODE_INPUT(GPIOC_PIN15))
+
+#define VAL_GPIOC_ODT (PIN_ODT_HIGH(GPIOC_PIN0) | \
+ PIN_ODT_HIGH(GPIOC_PIN1) | \
+ PIN_ODT_HIGH(GPIOC_PIN2) | \
+ PIN_ODT_HIGH(GPIOC_PIN3) | \
+ PIN_ODT_HIGH(GPIOC_PIN4) | \
+ PIN_ODT_HIGH(GPIOC_PIN5) | \
+ PIN_ODT_HIGH(GPIOC_PIN6) | \
+ PIN_ODT_HIGH(GPIOC_PIN7) | \
+ PIN_ODT_HIGH(GPIOC_PIN8) | \
+ PIN_ODT_HIGH(GPIOC_PIN9) | \
+ PIN_ODT_HIGH(GPIOC_PIN10) | \
+ PIN_ODT_HIGH(GPIOC_PIN11) | \
+ PIN_ODT_HIGH(GPIOC_PIN12) | \
+ PIN_ODT_HIGH(GPIOC_PIN13) | \
+ PIN_ODT_HIGH(GPIOC_PIN14) | \
+ PIN_ODT_HIGH(GPIOC_PIN15))
+
+#define VAL_GPIOC_OUTPUT (PIN_OUTPUT_PUSHPULL(GPIOC_PIN0) | \
+ PIN_OUTPUT_PUSHPULL(GPIOC_PIN1) | \
+ PIN_OUTPUT_PUSHPULL(GPIOC_PIN2) | \
+ PIN_OUTPUT_PUSHPULL(GPIOC_PIN3) | \
+ PIN_OUTPUT_PUSHPULL(GPIOC_PIN4) | \
+ PIN_OUTPUT_PUSHPULL(GPIOC_PIN5) | \
+ PIN_OUTPUT_PUSHPULL(GPIOC_PIN6) | \
+ PIN_OUTPUT_PUSHPULL(GPIOC_PIN7) | \
+ PIN_OUTPUT_PUSHPULL(GPIOC_PIN8) | \
+ PIN_OUTPUT_PUSHPULL(GPIOC_PIN9) | \
+ PIN_OUTPUT_PUSHPULL(GPIOC_PIN10) | \
+ PIN_OUTPUT_PUSHPULL(GPIOC_PIN11) | \
+ PIN_OUTPUT_PUSHPULL(GPIOC_PIN12) | \
+ PIN_OUTPUT_PUSHPULL(GPIOC_PIN13) | \
+ PIN_OUTPUT_PUSHPULL(GPIOC_PIN14) | \
+ PIN_OUTPUT_PUSHPULL(GPIOC_PIN15))
+
+#define VAL_GPIOC_ODRVR (PIN_ODRVR_STRONGER(GPIOC_PIN0) | \
+ PIN_ODRVR_STRONGER(GPIOC_PIN1) | \
+ PIN_ODRVR_STRONGER(GPIOC_PIN2) | \
+ PIN_ODRVR_STRONGER(GPIOC_PIN3) | \
+ PIN_ODRVR_STRONGER(GPIOC_PIN4) | \
+ PIN_ODRVR_STRONGER(GPIOC_PIN5) | \
+ PIN_ODRVR_STRONGER(GPIOC_PIN6) | \
+ PIN_ODRVR_STRONGER(GPIOC_PIN7) | \
+ PIN_ODRVR_STRONGER(GPIOC_PIN8) | \
+ PIN_ODRVR_STRONGER(GPIOC_PIN9) | \
+ PIN_ODRVR_STRONGER(GPIOC_PIN10) | \
+ PIN_ODRVR_STRONGER(GPIOC_PIN11) | \
+ PIN_ODRVR_STRONGER(GPIOC_PIN12) | \
+ PIN_ODRVR_STRONGER(GPIOC_PIN13) | \
+ PIN_ODRVR_STRONGER(GPIOC_PIN14) | \
+ PIN_ODRVR_STRONGER(GPIOC_PIN15))
+
+#define VAL_GPIOC_PULL (PIN_PULL_NONE(GPIOC_PIN0) | \
+ PIN_PULL_NONE(GPIOC_PIN1) | \
+ PIN_PULL_NONE(GPIOC_PIN2) | \
+ PIN_PULL_NONE(GPIOC_PIN3) | \
+ PIN_PULL_NONE(GPIOC_PIN4) | \
+ PIN_PULL_NONE(GPIOC_PIN5) | \
+ PIN_PULL_NONE(GPIOC_PIN6) | \
+ PIN_PULL_NONE(GPIOC_PIN7) | \
+ PIN_PULL_NONE(GPIOC_PIN8) | \
+ PIN_PULL_NONE(GPIOC_PIN9) | \
+ PIN_PULL_NONE(GPIOC_PIN10) | \
+ PIN_PULL_NONE(GPIOC_PIN11) | \
+ PIN_PULL_NONE(GPIOC_PIN12) | \
+ PIN_PULL_NONE(GPIOC_PIN13) | \
+ PIN_PULL_NONE(GPIOC_PIN14) | \
+ PIN_PULL_NONE(GPIOC_PIN15))
+
+#define VAL_GPIOC_MUXL (PIN_MUX(GPIOC_PIN0, 0U) | \
+ PIN_MUX(GPIOC_PIN1, 0U) | \
+ PIN_MUX(GPIOC_PIN2, 0U) | \
+ PIN_MUX(GPIOC_PIN3, 0U) | \
+ PIN_MUX(GPIOC_PIN4, 0U) | \
+ PIN_MUX(GPIOC_PIN5, 0U) | \
+ PIN_MUX(GPIOC_PIN6, 0U) | \
+ PIN_MUX(GPIOC_PIN7, 0U))
+
+#define VAL_GPIOC_MUXH (PIN_MUX(GPIOC_PIN8, 0U) | \
+ PIN_MUX(GPIOC_PIN9, 0U) | \
+ PIN_MUX(GPIOC_PIN10, 0U) | \
+ PIN_MUX(GPIOC_PIN11, 0U) | \
+ PIN_MUX(GPIOC_PIN12, 0U) | \
+ PIN_MUX(GPIOC_PIN13, 0U) | \
+ PIN_MUX(GPIOC_PIN14, 0U) | \
+ PIN_MUX(GPIOC_PIN15, 0U))
+
+#define VAL_GPIOC_HDRV (PIN_HDRV_NOTACTIVE(GPIOC_PIN0) | \
+ PIN_HDRV_NOTACTIVE(GPIOC_PIN1) | \
+ PIN_HDRV_NOTACTIVE(GPIOC_PIN2) | \
+ PIN_HDRV_NOTACTIVE(GPIOC_PIN3) | \
+ PIN_HDRV_NOTACTIVE(GPIOC_PIN4) | \
+ PIN_HDRV_NOTACTIVE(GPIOC_PIN5) | \
+ PIN_HDRV_NOTACTIVE(GPIOC_PIN6) | \
+ PIN_HDRV_NOTACTIVE(GPIOC_PIN7) | \
+ PIN_HDRV_NOTACTIVE(GPIOC_PIN8) | \
+ PIN_HDRV_NOTACTIVE(GPIOC_PIN9) | \
+ PIN_HDRV_NOTACTIVE(GPIOC_PIN10) | \
+ PIN_HDRV_NOTACTIVE(GPIOC_PIN11) | \
+ PIN_HDRV_NOTACTIVE(GPIOC_PIN12) | \
+ PIN_HDRV_NOTACTIVE(GPIOC_PIN13) | \
+ PIN_HDRV_NOTACTIVE(GPIOC_PIN14) | \
+ PIN_HDRV_NOTACTIVE(GPIOC_PIN15))
+
+/*
+ * GPIOD setup:
+ * PD2 - PIN2 (input none pull).
+ */
+#define VAL_GPIOD_MODE (PIN_MODE_INPUT(GPIOD_PIN2))
+#define VAL_GPIOD_ODT (PIN_ODT_HIGH(GPIOD_PIN2))
+#define VAL_GPIOD_OUTPUT (PIN_OUTPUT_PUSHPULL(GPIOD_PIN2))
+#define VAL_GPIOD_ODRVR (PIN_ODRVR_STRONGER(GPIOD_PIN2))
+#define VAL_GPIOD_PULL (PIN_PULL_NONE(GPIOD_PIN2))
+#define VAL_GPIOD_MUXL (PIN_MUX(GPIOD_PIN2, 0U))
+#define VAL_GPIOD_MUXH 0U
+#define VAL_GPIOD_HDRV (PIN_HDRV_NOTACTIVE(GPIOD_PIN2))
+
+/*
+ * GPIOF setup:
+ *
+ * PF0 - PIN0 (input none pull).
+ * PF1 - PIN1 (input none pull).
+ * PF4 - PIN4 (output none pull).
+ * PF5 - PIN5 (output none pull).
+ * PF6 - PIN6 (output none pull).
+ * PF7 - PIN7 (input none pull).
+ * PF11 - PIN11 (input none pull).
+ */
+#define VAL_GPIOF_MODE (PIN_MODE_INPUT(GPIOF_HEXT_IN) | \
+ PIN_MODE_INPUT(GPIOF_HEXT_OUT) | \
+ PIN_MODE_OUTPUT(GPIOF_PIN4) | \
+ PIN_MODE_OUTPUT(GPIOF_PIN5) | \
+ PIN_MODE_OUTPUT(GPIOF_PIN6) | \
+ PIN_MODE_INPUT(GPIOF_PIN7) | \
+ PIN_MODE_INPUT(GPIOF_PIN11))
+
+#define VAL_GPIOF_ODT (PIN_ODT_HIGH(GPIOF_HEXT_IN) | \
+ PIN_ODT_HIGH(GPIOF_HEXT_OUT) | \
+ PIN_ODT_HIGH(GPIOF_PIN4) | \
+ PIN_ODT_HIGH(GPIOF_PIN5) | \
+ PIN_ODT_HIGH(GPIOF_PIN6) | \
+ PIN_ODT_HIGH(GPIOF_PIN7) | \
+ PIN_ODT_HIGH(GPIOF_PIN11))
+
+
+#define VAL_GPIOF_OUTPUT (PIN_OUTPUT_PUSHPULL(GPIOF_HEXT_IN) | \
+ PIN_OUTPUT_PUSHPULL(GPIOF_HEXT_OUT) | \
+ PIN_OUTPUT_PUSHPULL(GPIOF_PIN4) | \
+ PIN_OUTPUT_PUSHPULL(GPIOF_PIN5) | \
+ PIN_OUTPUT_PUSHPULL(GPIOF_PIN6) | \
+ PIN_OUTPUT_PUSHPULL(GPIOF_PIN7) | \
+ PIN_OUTPUT_PUSHPULL(GPIOF_PIN11))
+
+
+#define VAL_GPIOF_ODRVR (PIN_ODRVR_STRONGER(GPIOF_HEXT_IN) | \
+ PIN_ODRVR_STRONGER(GPIOF_HEXT_OUT) | \
+ PIN_ODRVR_STRONGER(GPIOF_PIN4) | \
+ PIN_ODRVR_STRONGER(GPIOF_PIN5) | \
+ PIN_ODRVR_STRONGER(GPIOF_PIN6) | \
+ PIN_ODRVR_STRONGER(GPIOF_PIN7) | \
+ PIN_ODRVR_STRONGER(GPIOF_PIN11))
+
+#define VAL_GPIOF_PULL (PIN_PULL_NONE(GPIOF_HEXT_IN) | \
+ PIN_PULL_NONE(GPIOF_HEXT_OUT) | \
+ PIN_PULL_NONE(GPIOF_PIN4) | \
+ PIN_PULL_NONE(GPIOF_PIN5) | \
+ PIN_PULL_NONE(GPIOF_PIN6) | \
+ PIN_PULL_NONE(GPIOF_PIN7) | \
+ PIN_PULL_NONE(GPIOF_PIN11))
+
+#define VAL_GPIOF_MUXL (PIN_MUX(GPIOF_HEXT_IN, 0U) | \
+ PIN_MUX(GPIOF_HEXT_OUT, 0U) | \
+ PIN_MUX(GPIOF_PIN4, 0U) | \
+ PIN_MUX(GPIOF_PIN5, 0U) | \
+ PIN_MUX(GPIOF_PIN6, 0U) | \
+ PIN_MUX(GPIOF_PIN7, 0U) | \
+ PIN_MUX(GPIOF_PIN11, 0U))
+#define VAL_GPIOF_MUXH 0U
+
+#define VAL_GPIOF_HDRV (PIN_HDRV_NOTACTIVE(GPIOF_HEXT_IN) | \
+ PIN_HDRV_NOTACTIVE(GPIOF_HEXT_OUT) | \
+ PIN_HDRV_NOTACTIVE(GPIOF_PIN4) | \
+ PIN_HDRV_NOTACTIVE(GPIOF_PIN5) | \
+ PIN_HDRV_NOTACTIVE(GPIOF_PIN6) | \
+ PIN_HDRV_NOTACTIVE(GPIOF_PIN7) | \
+ PIN_HDRV_NOTACTIVE(GPIOF_PIN11))
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(_FROM_ASM_)
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void boardInit(void);
+#ifdef __cplusplus
+}
+#endif
+#endif /* _FROM_ASM_ */
+
+#endif /* _BOARD_H_ */
diff --git a/os/hal/boards/AT_START_F405/board.mk b/os/hal/boards/AT_START_F405/board.mk
new file mode 100644
index 0000000000..5486230056
--- /dev/null
+++ b/os/hal/boards/AT_START_F405/board.mk
@@ -0,0 +1,9 @@
+# List of all the board related files.
+BOARDSRC = $(CHIBIOS_CONTRIB)/os/hal/boards/AT_START_F405/board.c
+
+# Required include directories
+BOARDINC = ${CHIBIOS_CONTRIB}/os/hal/boards/AT_START_F405
+
+# Shared variables
+ALLCSRC += $(BOARDSRC)
+ALLINC += $(BOARDINC)
diff --git a/os/hal/ports/AT32/AT32F405xx/at32_crm.h b/os/hal/ports/AT32/AT32F405xx/at32_crm.h
new file mode 100644
index 0000000000..fb5a4274cc
--- /dev/null
+++ b/os/hal/ports/AT32/AT32F405xx/at32_crm.h
@@ -0,0 +1,1192 @@
+/*
+ ChibiOS - Copyright (C) 2023..2024 Zhaqian
+ ChibiOS - Copyright (C) 2024 Maxjta
+
+ Licensed 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.
+*/
+
+/**
+ * @file AT32F405xx/at32_crm.h
+ * @brief CRM helper driver header.
+ * @note This file requires definitions from the AT header file
+ * @p at32f402_405xx.h.
+ *
+ * @addtogroup AT32F405xx_CRM
+ * @{
+ */
+
+#ifndef AT32_CRM_H
+#define AT32_CRM_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile TMRe settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @name Generic CRM operations
+ * @{
+ */
+/**
+ * @brief Enables the clock of one or more peripheral on the APB1 bus.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] mask APB1 peripherals mask
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableAPB1(mask, lp) { \
+ CRM->APB1EN |= (mask); \
+ if (lp) \
+ CRM->APB1LPEN |= (mask); \
+ else \
+ CRM->APB1LPEN &= ~(mask); \
+ (void)CRM->APB1LPEN; \
+}
+
+/**
+ * @brief Disables the clock of one or more peripheral on the APB1 bus.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] mask APB1 peripherals mask
+ *
+ * @api
+ */
+#define crmDisableAPB1(mask) { \
+ CRM->APB1EN &= ~(mask); \
+ CRM->APB1LPEN &= ~(mask); \
+ (void)CRM->APB1LPEN; \
+}
+
+/**
+ * @brief Resets one or more peripheral on the APB1 bus.
+ *
+ * @param[in] mask APB1 peripherals mask
+ *
+ * @api
+ */
+#define crmResetAPB1(mask) { \
+ CRM->APB1RST |= (mask); \
+ CRM->APB1RST &= ~(mask); \
+ (void)CRM->APB1RST; \
+}
+
+/**
+ * @brief Enables the clock of one or more peripheral on the APB2 bus.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] mask APB2 peripherals mask
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableAPB2(mask, lp) { \
+ CRM->APB2EN |= (mask); \
+ if (lp) \
+ CRM->APB2LPEN |= (mask); \
+ else \
+ CRM->APB2LPEN &= ~(mask); \
+ (void)CRM->APB2LPEN; \
+}
+
+/**
+ * @brief Disables the clock of one or more peripheral on the APB2 bus.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] mask APB2 peripherals mask
+ *
+ * @api
+ */
+#define crmDisableAPB2(mask) { \
+ CRM->APB2EN &= ~(mask); \
+ CRM->APB2LPEN &= ~(mask); \
+ (void)CRM->APB2LPEN; \
+}
+
+/**
+ * @brief Resets one or more peripheral on the APB2 bus.
+ *
+ * @param[in] mask APB2 peripherals mask
+ *
+ * @api
+ */
+#define crmResetAPB2(mask) { \
+ CRM->APB2RST |= (mask); \
+ CRM->APB2RST &= ~(mask); \
+ (void)CRM->APB2RST; \
+}
+
+/**
+ * @brief Enables the clock of one or more peripheral on the AHB1 bus.
+ *
+ * @param[in] mask AHB1 peripherals mask
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableAHB1(mask, lp) { \
+ CRM->AHBEN1 |= (mask); \
+ if (lp) \
+ CRM->AHBLPEN1 |= (mask); \
+ else \
+ CRM->AHBLPEN1 &= ~(mask); \
+ (void)CRM->AHBLPEN1; \
+}
+
+/**
+ * @brief Disables the clock of one or more peripheral on the AHB1 bus.
+ *
+ * @param[in] mask AHB1 peripherals mask
+ *
+ * @api
+ */
+#define crmDisableAHB1(mask) { \
+ CRM->AHBEN1 &= ~(mask); \
+ CRM->AHBLPEN1 &= ~(mask); \
+ (void)CRM->AHBLPEN1; \
+}
+
+/**
+ * @brief Resets one or more peripheral on the AHB1 bus.
+ *
+ * @param[in] mask AHB1 peripherals mask
+ *
+ * @api
+ */
+#define crmResetAHB1(mask) { \
+ CRM->AHBRST1 |= (mask); \
+ CRM->AHBRST1 &= ~(mask); \
+ (void)CRM->AHBRST1; \
+}
+
+/**
+ * @brief Enables the clock of one or more peripheral on the AHB2 bus.
+ *
+ * @param[in] mask AHB2 peripherals mask
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableAHB2(mask, lp) { \
+ CRM->AHBEN2 |= (mask); \
+ if (lp) \
+ CRM->AHBLPEN2 |= (mask); \
+ else \
+ CRM->AHBLPEN2 &= ~(mask); \
+ (void)CRM->AHBLPEN2; \
+}
+
+/**
+ * @brief Disables the clock of one or more peripheral on the AHB2 bus.
+ *
+ * @param[in] mask AHB2 peripherals mask
+ *
+ * @api
+ */
+#define crmDisableAHB2(mask) { \
+ CRM->AHBEN2 &= ~(mask); \
+ CRM->AHBLPEN2 &= ~(mask); \
+ (void)CRM->AHBLPEN2; \
+}
+
+/**
+ * @brief Resets one or more peripheral on the AHB2 bus.
+ *
+ * @param[in] mask AHB2 peripherals mask
+ *
+ * @api
+ */
+#define crmResetAHB2(mask) { \
+ CRM->AHBRST2 |= (mask); \
+ CRM->AHBRST2 &= ~(mask); \
+ (void)CRM->AHBRST2; \
+}
+
+/**
+ * @brief Enables the clock of one or more peripheral on the AHB3 (FSMC) bus.
+ *
+ * @param[in] mask AHB3 peripherals mask
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableAHB3(mask, lp) { \
+ CRM->AHBEN3 |= (mask); \
+ if (lp) \
+ CRM->AHBLPEN3 |= (mask); \
+ else \
+ CRM->AHBLPEN3 &= ~(mask); \
+ (void)CRM->AHBLPEN3; \
+}
+
+/**
+ * @brief Disables the clock of one or more peripheral on the AHB3 (FSMC) bus.
+ *
+ * @param[in] mask AHB3 peripherals mask
+ *
+ * @api
+ */
+#define crmDisableAHB3(mask) { \
+ CRM->AHBEN3 &= ~(mask); \
+ CRM->AHBLPEN3 &= ~(mask); \
+ (void)CRM->AHBLPEN3; \
+}
+
+/**
+ * @brief Resets one or more peripheral on the AHB3 (FSMC) bus.
+ *
+ * @param[in] mask AHB3 peripherals mask
+ *
+ * @api
+ */
+#define crmResetAHB3(mask) { \
+ CRM->AHBRST3 |= (mask); \
+ CRM->AHBRST3 &= ~(mask); \
+ (void)CRM->AHBRST3; \
+}
+/** @} */
+
+/**
+ * @name ADC peripherals specific CRM operations
+ * @{
+ */
+/**
+ * @brief Enables the ADC1 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableADC1(lp) crmEnableAPB2(CRM_APB2EN_ADC1EN, lp)
+
+/**
+ * @brief Disables the ADC1 peripheral clock.
+ *
+ * @api
+ */
+#define crmDisableADC1() crmDisableAPB2(CRM_APB2EN_ADC1EN)
+
+/**
+ * @brief Resets the ADC1 peripheral.
+ *
+ * @api
+ */
+#define crmResetADC1() crmResetAPB2(CRM_APB2RST_ADC1RST)
+/** @} */
+
+/**
+ * @name PWC interface specific CRM operations
+ * @{
+ */
+/**
+ * @brief Enables the PWC interface clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnablePWCInterface(lp) crmEnableAPB1(CRM_APB1EN_PWCEN, lp)
+
+/**
+ * @brief Disables PWC interface clock.
+ *
+ * @api
+ */
+#define crmDisablePWCInterface() crmDisableAPB1(CRM_APB1EN_PWCEN)
+
+/**
+ * @brief Resets the PWC interface.
+ *
+ * @api
+ */
+#define crmResetPWCInterface() crmResetAPB1(CRM_APB1RST_PWCRST)
+/** @} */
+
+/**
+ * @name CAN peripherals specific CRM operations
+ * @{
+ */
+/**
+ * @brief Enables the CAN1 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableCAN1(lp) crmEnableAPB1(CRM_APB1EN_CAN1EN, lp)
+
+/**
+ * @brief Disables the CAN1 peripheral clock.
+ *
+ * @api
+ */
+#define crmDisableCAN1() crmDisableAPB1(CRM_APB1EN_CAN1EN)
+
+/**
+ * @brief Resets the CAN1 peripheral.
+ *
+ * @api
+ */
+#define crmResetCAN1() crmResetAPB1(CRM_APB1RST_CAN1RST)
+
+/**
+ * @name DMA peripherals specific CRM operations
+ * @{
+ */
+/**
+ * @brief Enables the DMA1 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableDMA1(lp) crmEnableAHB1(CRM_AHBEN1_DMA1EN, lp)
+
+/**
+ * @brief Disables the DMA1 peripheral clock.
+ *
+ * @api
+ */
+#define crmDisableDMA1() crmDisableAHB1(CRM_AHBEN1_DMA1EN)
+
+/**
+ * @brief Resets the DMA1 peripheral.
+ * @note Not supported in this family, does nothing.
+ *
+ * @api
+ */
+#define crmResetDMA1() crmResetAHB1(CRM_AHBRST1_DMA1RST)
+
+/**
+ * @brief Enables the DMA2 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableDMA2(lp) crmEnableAHB1(CRM_AHBEN1_DMA2EN, lp)
+
+/**
+ * @brief Disables the DMA2 peripheral clock.
+ *
+ * @api
+ */
+#define crmDisableDMA2() crmDisableAHB1(CRM_AHBEN1_DMA2EN)
+
+/**
+ * @brief Resets the DMA2 peripheral.
+ * @note Not supported in this family, does nothing.
+ *
+ * @api
+ */
+#define crmResetDMA2() crmResetAHB1(CRM_AHBRST1_DMA2RST)
+/** @} */
+
+/**
+ * @name I2C peripherals specific CRM operations
+ * @{
+ */
+/**
+ * @brief Enables the I2C1 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableI2C1(lp) crmEnableAPB1(CRM_APB1EN_I2C1EN, lp)
+
+/**
+ * @brief Disables the I2C1 peripheral clock.
+ *
+ * @api
+ */
+#define crmDisableI2C1() crmDisableAPB1(CRM_APB1EN_I2C1EN)
+
+/**
+ * @brief Resets the I2C1 peripheral.
+ *
+ * @api
+ */
+#define crmResetI2C1() crmResetAPB1(CRM_APB1RST_I2C1RST)
+
+/**
+ * @brief Enables the I2C2 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableI2C2(lp) crmEnableAPB1(CRM_APB1EN_I2C2EN, lp)
+
+/**
+ * @brief Disables the I2C2 peripheral clock.
+ *
+ * @api
+ */
+#define crmDisableI2C2() crmDisableAPB1(CRM_APB1EN_I2C2EN)
+
+/**
+ * @brief Resets the I2C2 peripheral.
+ *
+ * @api
+ */
+#define crmResetI2C2() crmResetAPB1(CRM_APB1RST_I2C2RST)
+
+/**
+ * @brief Enables the I2C3 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableI2C3(lp) crmEnableAPB1(CRM_APB1EN_I2C3EN, lp)
+
+/**
+ * @brief Disables the I2C3 peripheral clock.
+ *
+ * @api
+ */
+#define crmDisableI2C3() crmDisableAPB1(CRM_APB1EN_I2C3EN)
+
+/**
+ * @brief Resets the I2C3 peripheral.
+ *
+ * @api
+ */
+#define crmResetI2C3() crmResetAPB1(CRM_APB1RST_I2C3RST)
+/** @} */
+
+/**
+ * @name OTG peripherals specific CRM operations
+ * @{
+ */
+/**
+ * @brief Enables the OTG_FS peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableOTG_FS1(lp) crmEnableAHB2(CRM_AHBEN2_OTGFS1EN, lp)
+#define crmEnableOTG_FS(lp) crmEnableOTG_FS1(lp)
+
+/**
+ * @brief Disables the OTG_FS peripheral clock.
+ *
+ * @api
+ */
+#define crmDisableOTG_FS1() crmDisableAHB2(CRM_AHBEN2_OTGFS1EN)
+#define crmDisableOTG_FS() crmDisableOTG_FS1()
+
+/**
+ * @brief Resets the OTG_FS peripheral.
+ *
+ * @api
+ */
+#define crmResetOTG_FS1() crmResetAHB2(CRM_AHBRST2_OTGFS1RST)
+#define crmResetOTG_FS() crmResetOTG_FS1()
+/**
+ * @brief Enables the OTG_HS peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableOTG_HS(lp) crmEnableAHB1(CRM_AHBEN1_OTGHSEN, lp)
+
+/**
+ * @brief Disables the OTG_HS peripheral clock.
+ *
+ * @api
+ */
+#define crmDisableOTG_HS() crmDisableAHB1(CRM_AHBEN1_OTGHSEN)
+
+/**
+ * @brief Resets the OTG_HS peripheral.
+ *
+ * @api
+ */
+#define crmResetOTG_HS() crmResetAHB1(CRM_AHBRST1_OTGHSRST)
+/** @} */
+
+/**
+ * @name QUADSPI peripherals specific CRM operations
+ * @{
+ */
+/**
+ * @brief Enables the QUADSPI1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableQUADSPI1(lp) crmEnableAHB3(CRM_AHBEN3_QSPI1EN, lp)
+
+/**
+ * @brief Disables the QUADSPI1 peripheral clock.
+ *
+ * @api
+ */
+#define crmDisableQUADSPI1() crmDisableAHB3(CRM_AHBEN3_QSPI1EN)
+
+/**
+ * @brief Resets the QUADSPI1 peripheral.
+ *
+ * @api
+ */
+#define crmResetQUADSPI1() crmResetAHB3(CRM_AHBRST3_QSPI1RST)
+/** @} */
+
+/**
+ * @name SPI peripherals specific CRM operations
+ * @{
+ */
+/**
+ * @brief Enables the SPI1 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableSPI1(lp) crmEnableAPB2(CRM_APB2EN_SPI1EN, lp)
+
+/**
+ * @brief Disables the SPI1 peripheral clock.
+ *
+ * @api
+ */
+#define crmDisableSPI1() crmDisableAPB2(CRM_APB2EN_SPI1EN)
+
+/**
+ * @brief Resets the SPI1 peripheral.
+ *
+ * @api
+ */
+#define crmResetSPI1() crmResetAPB2(CRM_APB2RST_SPI1RST)
+
+/**
+ * @brief Enables the SPI2 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableSPI2(lp) crmEnableAPB1(CRM_APB1EN_SPI2EN, lp)
+
+/**
+ * @brief Disables the SPI2 peripheral clock.
+ *
+ * @api
+ */
+#define crmDisableSPI2() crmDisableAPB1(CRM_APB1EN_SPI2EN)
+
+/**
+ * @brief Resets the SPI2 peripheral.
+ *
+ * @api
+ */
+#define crmResetSPI2() crmResetAPB1(CRM_APB1RST_SPI2RST)
+
+/**
+ * @brief Enables the SPI3 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableSPI3(lp) crmEnableAPB1(CRM_APB1EN_SPI3EN, lp)
+
+/**
+ * @brief Disables the SPI3 peripheral clock.
+ *
+ * @api
+ */
+#define crmDisableSPI3() crmDisableAPB1(CRM_APB1EN_SPI3EN)
+
+/**
+ * @brief Resets the SPI3 peripheral.
+ *
+ * @api
+ */
+#define crmResetSPI3() crmResetAPB1(CRM_APB1RST_SPI3RST)
+/** @} */
+
+/**
+ * @name TMR peripherals specific CRM operations
+ * @{
+ */
+/**
+ * @brief Enables the TMR1 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableTMR1(lp) crmEnableAPB2(CRM_APB2EN_TMR1EN, lp)
+
+/**
+ * @brief Disables the TMR1 peripheral clock.
+ *
+ * @api
+ */
+#define crmDisableTMR1() crmDisableAPB2(CRM_APB2EN_TMR1EN)
+
+/**
+ * @brief Resets the TMR1 peripheral.
+ *
+ * @api
+ */
+#define crmResetTMR1() crmResetAPB2(CRM_APB2RST_TMR1RST)
+
+/**
+ * @brief Enables the TMR2 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableTMR2(lp) crmEnableAPB1(CRM_APB1EN_TMR2EN, lp)
+
+/**
+ * @brief Disables the TMR2 peripheral clock.
+ *
+ * @api
+ */
+#define crmDisableTMR2() crmDisableAPB1(CRM_APB1EN_TMR2EN)
+
+/**
+ * @brief Resets the TMR2 peripheral.
+ *
+ * @api
+ */
+#define crmResetTMR2() crmResetAPB1(CRM_APB1RST_TMR2RST)
+
+/**
+ * @brief Enables the TMR3 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableTMR3(lp) crmEnableAPB1(CRM_APB1EN_TMR3EN, lp)
+
+/**
+ * @brief Disables the TMR3 peripheral clock.
+ *
+ * @api
+ */
+#define crmDisableTMR3() crmDisableAPB1(CRM_APB1EN_TMR3EN)
+
+/**
+ * @brief Resets the TMR3 peripheral.
+ *
+ * @api
+ */
+#define crmResetTMR3() crmResetAPB1(CRM_APB1RST_TMR3RST)
+
+/**
+ * @brief Enables the TMR4 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableTMR4(lp) crmEnableAPB1(CRM_APB1EN_TMR4EN, lp)
+
+/**
+ * @brief Disables the TMR4 peripheral clock.
+ *
+ * @api
+ */
+#define crmDisableTMR4() crmDisableAPB1(CRM_APB1EN_TMR4EN)
+
+/**
+ * @brief Resets the TMR4 peripheral.
+ *
+ * @api
+ */
+#define crmResetTMR4() crmResetAPB1(CRM_APB1RST_TMR4RST)
+
+/**
+ * @brief Enables the TMR6 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableTMR6(lp) crmEnableAPB1(CRM_APB1EN_TMR6EN, lp)
+
+/**
+ * @brief Disables the TMR6 peripheral clock.
+ *
+ * @api
+ */
+#define crmDisableTMR6() crmDisableAPB1(CRM_APB1EN_TMR6EN)
+
+/**
+ * @brief Resets the TMR6 peripheral.
+ *
+ * @api
+ */
+#define crmResetTMR6() crmResetAPB1(CRM_APB1RST_TMR6RST)
+
+/**
+ * @brief Enables the TMR7 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableTMR7(lp) crmEnableAPB1(CRM_APB1EN_TMR7EN, lp)
+
+/**
+ * @brief Disables the TMR7 peripheral clock.
+ *
+ * @api
+ */
+#define crmDisableTMR7() crmDisableAPB1(CRM_APB1EN_TMR7EN)
+
+/**
+ * @brief Resets the TMR7 peripheral.
+ *
+ * @api
+ */
+#define crmResetTMR7() crmResetAPB1(CRM_APB1RST_TMR7RST)
+
+/**
+
+ * @brief Enables the TMR9 peripheral clock.
+
+ * @note The @p lp parameter is ignored in this family.
+
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableTMR9(lp) crmEnableAPB2(CRM_APB2EN_TMR9EN, lp)
+
+/**
+ * @brief Disables the TMR9 peripheral clock.
+ *
+ * @api
+ */
+#define crmDisableTMR9() crmDisableAPB2(CRM_APB2EN_TMR9EN)
+
+/**
+ * @brief Resets the TMR9 peripheral.
+ *
+ * @api
+ */
+#define crmResetTMR9() crmResetAPB2(CRM_APB2RST_TMR9RST)
+
+/**
+ * @brief Enables the TMR10 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableTMR10(lp) crmEnableAPB2(CRM_APB2EN_TMR10EN, lp)
+
+/**
+ * @brief Disables the TMR10 peripheral clock.
+ *
+ * @api
+ */
+#define crmDisableTMR10() crmDisableAPB2(CRM_APB2EN_TMR10EN)
+
+/**
+ * @brief Resets the TMR10 peripheral.
+ *
+ * @api
+ */
+#define crmResetTMR10() crmResetAPB2(CRM_APB2RST_TMR10RST)
+
+/**
+ * @brief Enables the TMR11 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableTMR11(lp) crmEnableAPB2(CRM_APB2EN_TMR11EN, lp)
+
+/**
+ * @brief Disables the TMR11 peripheral clock.
+ *
+ * @api
+ */
+#define crmDisableTMR11() crmDisableAPB2(CRM_APB2EN_TMR11EN)
+
+/**
+ * @brief Resets the TMR11 peripheral.
+ *
+ * @api
+ */
+#define crmResetTMR11() crmResetAPB2(CRM_APB2RST_TMR11RST)
+
+/**
+ * @brief Enables the TMR13 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableTMR13(lp) crmEnableAPB1(CRM_APB1EN_TMR13EN, lp)
+
+/**
+ * @brief Disables the TMR13 peripheral clock.
+ *
+ * @api
+ */
+#define crmDisableTMR13() crmDisableAPB1(CRM_APB1EN_TMR13EN)
+
+/**
+ * @brief Resets the TMR13 peripheral.
+ *
+ * @api
+ */
+#define crmResetTMR13() crmResetAPB1(CRM_APB1RST_TMR13RST)
+
+/**
+ * @brief Enables the TMR14 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableTMR14(lp) crmEnableAPB1(CRM_APB1EN_TMR14EN, lp)
+
+/**
+ * @brief Disables the TMR14 peripheral clock.
+ *
+ * @api
+ */
+#define crmDisableTMR14() crmDisableAPB1(CRM_APB1EN_TMR14EN)
+
+/**
+ * @brief Resets the TMR14 peripheral.
+ *
+ * @api
+ */
+#define crmResetTMR14() crmResetAPB1(CRM_APB1RST_TMR14RST)
+/** @} */
+
+/**
+ * @name USART/UART peripherals specific CRM operations
+ * @{
+ */
+/**
+ * @brief Enables the USART1 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableUSART1(lp) crmEnableAPB2(CRM_APB2EN_USART1EN, lp)
+
+/**
+ * @brief Disables the USART1 peripheral clock.
+ *
+ * @api
+ */
+#define crmDisableUSART1() crmDisableAPB2(CRM_APB2EN_USART1EN)
+
+/**
+ * @brief Resets the USART1 peripheral.
+ *
+ * @api
+ */
+#define crmResetUSART1() crmResetAPB2(CRM_APB2RST_USART1RST)
+
+/**
+ * @brief Enables the USART2 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableUSART2(lp) crmEnableAPB1(CRM_APB1EN_USART2EN, lp)
+
+/**
+ * @brief Disables the USART2 peripheral clock.
+ *
+ * @api
+ */
+#define crmDisableUSART2() crmDisableAPB1(CRM_APB1EN_USART2EN)
+
+/**
+ * @brief Resets the USART2 peripheral.
+ *
+ * @api
+ */
+#define crmResetUSART2() crmResetAPB1(CRM_APB1RST_USART2RST)
+
+/**
+ * @brief Enables the USART3 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableUSART3(lp) crmEnableAPB1(CRM_APB1EN_USART3EN, lp)
+
+/**
+ * @brief Disables the USART3 peripheral clock.
+ *
+ * @api
+ */
+#define crmDisableUSART3() crmDisableAPB1(CRM_APB1EN_USART3EN)
+
+/**
+ * @brief Resets the USART3 peripheral.
+ *
+ * @api
+ */
+#define crmResetUSART3() crmResetAPB1(CRM_APB1RST_USART3RST)
+/** @} */
+
+/**
+ * @brief Enables the UART4 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableUART4(lp) crmEnableAPB1(CRM_APB1EN_USART4EN, lp)
+
+/**
+ * @brief Disables the UART4 peripheral clock.
+ *
+ * @api
+ */
+#define crmDisableUART4() crmDisableAPB1(CRM_APB1EN_USART4EN)
+
+/**
+ * @brief Resets the UART4 peripheral.
+ *
+ * @api
+ */
+#define crmResetUART4() crmResetAPB1(CRM_APB1RST_USART4RST)
+
+/**
+ * @brief Enables the UART5 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableUART5(lp) crmEnableAPB1(CRM_APB1EN_USART5EN, lp)
+
+/**
+ * @brief Disables the UART5 peripheral clock.
+ *
+ * @api
+ */
+#define crmDisableUART5() crmDisableAPB1(CRM_APB1EN_USART5EN)
+
+/**
+ * @brief Resets the UART5 peripheral.
+ *
+ * @api
+ */
+#define crmResetUART5() crmResetAPB1(CRM_APB1RST_USART5RST)
+
+/**
+ * @brief Enables the USART6 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableUSART6(lp) crmEnableAPB2(CRM_APB2EN_USART6EN, lp)
+
+/**
+ * @brief Disables the USART6 peripheral clock.
+ *
+ * @api
+ */
+#define crmDisableUSART6() crmDisableAPB2(CRM_APB2EN_USART6EN)
+
+/**
+ * @brief Resets the USART6 peripheral.
+ *
+ * @api
+ */
+#define crmResetUSART6() crmResetAPB2(CRM_APB2RST_USART6RST)
+
+/**
+ * @brief Enables the UART7 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableUART7(lp) crmEnableAPB1(CRM_APB1EN_UART7EN, lp)
+
+/**
+ * @brief Disables the UART7 peripheral clock.
+ *
+ * @api
+ */
+#define crmDisableUART7() crmDisableAPB1(CRM_APB1EN_UART7EN)
+
+/**
+ * @brief Resets the UART7 peripheral.
+ *
+ * @api
+ */
+#define crmResetUART7() crmResetAPB1(CRM_APB1RST_UART7RST)
+
+/**
+ * @brief Enables the UART8 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableUART8(lp) crmEnableAPB1(CRM_APB1EN_UART8EN, lp)
+
+/**
+ * @brief Disables the UART8 peripheral clock.
+ *
+ * @api
+ */
+#define crmDisableUART8() crmDisableAPB1(CRM_APB1EN_UART8EN)
+
+/**
+ * @brief Resets the UART8 peripheral.
+ *
+ * @api
+ */
+#define crmResetUART8() crmResetAPB1(CRM_APB1RST_UART8RST)
+/** @} */
+
+/**
+ * @name ACC peripherals specific CRM operations
+ * @{
+ */
+/**
+ * @brief Enables the ACC peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableACC(lp) crmEnableAPB2(CRM_APB2EN_ACCEN, lp)
+
+/**
+ * @brief Disables the ACC peripheral clock.
+ *
+ * @api
+ */
+#define crmDisableACC() crmDisableAPB2(CRM_APB2EN_ACCEN)
+
+/**
+ * @brief Resets the ACC peripheral.
+ *
+ * @api
+ */
+#define crmResetACC() crmResetAPB2(CRM_APB2RST_ACCRST)
+/** @} */
+
+/**
+ * @name SCFG peripherals specific CRM operations
+ * @{
+ */
+/**
+ * @brief Enables the SCFG peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define crmEnableSCFG(lp) crmEnableAPB2(CRM_APB2EN_SCFGEN, lp)
+
+/**
+ * @brief Disables the SCFG peripheral clock.
+ *
+ * @api
+ */
+#define crmDisableSCFG() crmDisableAPB2(CRM_APB2EN_SCFGEN)
+
+/**
+ * @brief Resets the SCFG peripheral.
+ *
+ * @api
+ */
+#define crmResetSCFG() crmResetAPB2(CRM_APB2RST_SCFGRST)
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AT32_CRM_H */
+
+/** @} */
diff --git a/os/hal/ports/AT32/AT32F405xx/at32_dmamux.h b/os/hal/ports/AT32/AT32F405xx/at32_dmamux.h
new file mode 100644
index 0000000000..d6d4e4847f
--- /dev/null
+++ b/os/hal/ports/AT32/AT32F405xx/at32_dmamux.h
@@ -0,0 +1,148 @@
+/*
+ ChibiOS - Copyright (C) 2023..2024 Zhaqian
+ ChibiOS - Copyright (C) 2024 Maxjta
+
+ Licensed 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.
+*/
+
+/**
+ * @file AT32F405xx/at32_dmamux.h
+ * @brief AT32F405xx DMAMUX handler header.
+ *
+ * @addtogroup AT32F405xx_DMAMUX
+ * @{
+ */
+
+#ifndef AT32_DMAMUX_H
+#define AT32_DMAMUX_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name DMAMUX request sources
+ * @{
+ */
+#define AT32_DMAMUX_MUXREQG1 1
+#define AT32_DMAMUX_MUXREQG2 2
+#define AT32_DMAMUX_MUXREQG3 3
+#define AT32_DMAMUX_MUXREQG4 4
+#define AT32_DMAMUX_ADC1 5
+#define AT32_DMAMUX_SPI1_RX 10
+#define AT32_DMAMUX_SPI1_TX 11
+#define AT32_DMAMUX_SPI2_RX 12
+#define AT32_DMAMUX_SPI2_TX 13
+#define AT32_DMAMUX_SPI3_RX 14
+#define AT32_DMAMUX_SPI3_TX 15
+#define AT32_DMAMUX_I2C1_RX 16
+#define AT32_DMAMUX_I2C1_TX 17
+#define AT32_DMAMUX_I2C2_RX 18
+#define AT32_DMAMUX_I2C2_TX 19
+#define AT32_DMAMUX_I2C3_RX 20
+#define AT32_DMAMUX_I2C3_TX 21
+#define AT32_DMAMUX_USART1_RX 24
+#define AT32_DMAMUX_USART1_TX 25
+#define AT32_DMAMUX_USART2_RX 26
+#define AT32_DMAMUX_USART2_TX 27
+#define AT32_DMAMUX_USART3_RX 28
+#define AT32_DMAMUX_USART3_TX 29
+#define AT32_DMAMUX_USART4_RX 30
+#define AT32_DMAMUX_USART4_TX 31
+#define AT32_DMAMUX_USART5_RX 32
+#define AT32_DMAMUX_USART5_TX 33
+#define AT32_DMAMUX_QSPI1 40
+#define AT32_DMAMUX_TMR1_CH1 42
+#define AT32_DMAMUX_TMR1_CH2 43
+#define AT32_DMAMUX_TMR1_CH3 44
+#define AT32_DMAMUX_TMR1_CH4 45
+#define AT32_DMAMUX_TMR1_OVERFLOW 46
+#define AT32_DMAMUX_TMR1_TRIG 47
+#define AT32_DMAMUX_TMR1_HALL 48
+#define AT32_DMAMUX_TMR2_CH1 56
+#define AT32_DMAMUX_TMR2_CH2 57
+#define AT32_DMAMUX_TMR2_CH3 58
+#define AT32_DMAMUX_TMR2_CH4 59
+#define AT32_DMAMUX_TMR2_OVERFLOW 60
+#define AT32_DMAMUX_TMR3_CH1 61
+#define AT32_DMAMUX_TMR3_CH2 62
+#define AT32_DMAMUX_TMR3_CH3 63
+#define AT32_DMAMUX_TMR3_CH4 64
+#define AT32_DMAMUX_TMR3_OVERFLOW 65
+#define AT32_DMAMUX_TMR3_TRIG 66
+#define AT32_DMAMUX_TMR4_CH1 67
+#define AT32_DMAMUX_TMR4_CH2 68
+#define AT32_DMAMUX_TMR4_CH3 69
+#define AT32_DMAMUX_TMR4_CH4 70
+#define AT32_DMAMUX_TMR4_OVERFLOW 71
+#define AT32_DMAMUX_TMR9_CH1 78
+#define AT32_DMAMUX_TMR9_OVERFLOW 79
+#define AT32_DMAMUX_TMR9_TRIG 80
+#define AT32_DMAMUX_TMR9_HALL 81
+#define AT32_DMAMUX_TMR10_CH1 82
+#define AT32_DMAMUX_TMR10_OVERFLOW 83
+#define AT32_DMAMUX_TMR11_CH1 84
+#define AT32_DMAMUX_TMR11_OVERFLOW 85
+#define AT32_DMAMUX_I2SF5_RX 108
+#define AT32_DMAMUX_I2S_TX 109
+#define AT32_DMAMUX_USART6_RX 114
+#define AT32_DMAMUX_USART6_TX 115
+#define AT32_DMAMUX_UART7_RX 116
+#define AT32_DMAMUX_UART7_TX 117
+#define AT32_DMAMUX_UART8_RX 118
+#define AT32_DMAMUX_UART8_TX 119
+#define AT32_DMAMUX_TMR13_CH1 120
+#define AT32_DMAMUX_TMR13_OVERFLOW 121
+#define AT32_DMAMUX_TMR14_CH1 122
+#define AT32_DMAMUX_TMR14_OVERFLOW 123
+#define AT32_DMAMUX_TMR9_CH2 124
+#define AT32_DMAMUX_TMR2_TRIG 126
+#define AT32_DMAMUX_TMR4_TRIG 127
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+#define AT32_DMAMUX_UART4_RX AT32_DMAMUX_USART4_RX
+#define AT32_DMAMUX_UART4_TX AT32_DMAMUX_USART4_TX
+#define AT32_DMAMUX_UART5_RX AT32_DMAMUX_USART5_RX
+#define AT32_DMAMUX_UART5_TX AT32_DMAMUX_USART5_TX
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AT32_DMAMUX_H */
+
+/** @} */
diff --git a/os/hal/ports/AT32/AT32F405xx/at32_isr.c b/os/hal/ports/AT32/AT32F405xx/at32_isr.c
new file mode 100644
index 0000000000..0678e5685d
--- /dev/null
+++ b/os/hal/ports/AT32/AT32F405xx/at32_isr.c
@@ -0,0 +1,173 @@
+/*
+ ChibiOS - Copyright (C) 2023..2024 Zhaqian
+ ChibiOS - Copyright (C) 2024 Maxjta
+
+ Licensed 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.
+*/
+
+/**
+ * @file AT32F405xx/at32_isr.c
+ * @brief AT32F405xx ISR handler code.
+ *
+ * @addtogroup AT32F405xx_ISR
+ * @{
+ */
+
+#include "hal.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+#define exint_serve_irq(intsts, channel) { \
+ \
+ if ((intsts) & (1U << (channel))) { \
+ _pal_isr_code(channel); \
+ } \
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+#include "at32_exint0.inc"
+#include "at32_exint1.inc"
+#include "at32_exint2.inc"
+#include "at32_exint3.inc"
+#include "at32_exint4.inc"
+#include "at32_exint5_9.inc"
+#include "at32_exint10_15.inc"
+#include "at32_exint16.inc"
+#include "at32_exint17.inc"
+#include "at32_exint18.inc"
+#include "at32_exint19.inc"
+#include "at32_exint20.inc"
+#include "at32_exint21.inc"
+#include "at32_exint22.inc"
+
+#include "at32_tmr1_9_10_11.inc"
+#include "at32_tmr2.inc"
+#include "at32_tmr3.inc"
+#include "at32_tmr4.inc"
+#include "at32_tmr6.inc"
+#include "at32_tmr7.inc"
+#include "at32_tmr13.inc"
+#include "at32_tmr14.inc"
+
+#include "at32_usart1.inc"
+#include "at32_usart2.inc"
+#include "at32_usart3.inc"
+#include "at32_uart4.inc"
+#include "at32_uart5.inc"
+#include "at32_usart6.inc"
+#include "at32_uart7.inc"
+#include "at32_uart8.inc"
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables IRQ sources.
+ *
+ * @notapi
+ */
+void irqInit(void) {
+
+ exint0_irq_init();
+ exint1_irq_init();
+ exint2_irq_init();
+ exint3_irq_init();
+ exint4_irq_init();
+ exint5_9_irq_init();
+ exint10_15_irq_init();
+ exint16_irq_init();
+ exint17_irq_init();
+ exint18_irq_init();
+ exint19_irq_init();
+ exint20_irq_init();
+ exint21_irq_init();
+ exint22_irq_init();
+
+ tmr1_tmr9_tmr10_tmr11_irq_init();
+ tmr2_irq_init();
+ tmr3_irq_init();
+ tmr4_irq_init();
+ tmr6_irq_init();
+ tmr7_irq_init();
+ tmr13_irq_init();
+ tmr14_irq_init();
+
+ usart1_irq_init();
+ usart2_irq_init();
+ usart3_irq_init();
+ uart4_irq_init();
+ uart5_irq_init();
+ usart6_irq_init();
+ uart7_irq_init();
+ uart8_irq_init();
+}
+
+/**
+ * @brief Disables IRQ sources.
+ *
+ * @notapi
+ */
+void irqDeinit(void) {
+
+ exint0_irq_deinit();
+ exint1_irq_deinit();
+ exint2_irq_deinit();
+ exint3_irq_deinit();
+ exint4_irq_deinit();
+ exint5_9_irq_deinit();
+ exint10_15_irq_deinit();
+ exint16_irq_deinit();
+ exint17_irq_deinit();
+ exint18_irq_deinit();
+ exint19_irq_deinit();
+ exint20_irq_deinit();
+ exint21_irq_deinit();
+ exint22_irq_deinit();
+
+ tmr1_tmr9_tmr10_tmr11_irq_deinit();
+ tmr2_irq_deinit();
+ tmr3_irq_deinit();
+ tmr4_irq_deinit();
+ tmr6_irq_deinit();
+ tmr7_irq_deinit();
+ tmr13_irq_deinit();
+ tmr14_irq_deinit();
+
+ usart1_irq_deinit();
+ usart2_irq_deinit();
+ usart3_irq_deinit();
+ uart4_irq_deinit();
+ uart5_irq_deinit();
+ usart6_irq_deinit();
+ uart7_irq_deinit();
+ uart8_irq_deinit();
+}
+
+/** @} */
diff --git a/os/hal/ports/AT32/AT32F405xx/at32_isr.h b/os/hal/ports/AT32/AT32F405xx/at32_isr.h
new file mode 100644
index 0000000000..92a8c614ff
--- /dev/null
+++ b/os/hal/ports/AT32/AT32F405xx/at32_isr.h
@@ -0,0 +1,285 @@
+/*
+ ChibiOS - Copyright (C) 2023..2024 Zhaqian
+ ChibiOS - Copyright (C) 2024 Maxjta
+
+ Licensed 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.
+*/
+
+/**
+ * @file AT32F405xx/at32_isr.h
+ * @brief AT32F405xx ISR handler header.
+ *
+ * @addtogroup AT32F405xx_ISR
+ * @{
+ */
+
+#ifndef AT32_ISR_H
+#define AT32_ISR_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name ISRs suppressed in standard drivers
+ * @{
+ */
+#define AT32_TMR1_SUPPRESS_ISR
+#define AT32_TMR2_SUPPRESS_ISR
+#define AT32_TMR3_SUPPRESS_ISR
+#define AT32_TMR4_SUPPRESS_ISR
+#define AT32_TMR6_SUPPRESS_ISR
+#define AT32_TMR7_SUPPRESS_ISR
+#define AT32_TMR9_SUPPRESS_ISR
+#define AT32_TMR10_SUPPRESS_ISR
+#define AT32_TMR11_SUPPRESS_ISR
+#define AT32_TMR13_SUPPRESS_ISR
+#define AT32_TMR14_SUPPRESS_ISR
+
+#define AT32_USART1_SUPPRESS_ISR
+#define AT32_USART2_SUPPRESS_ISR
+#define AT32_USART3_SUPPRESS_ISR
+#define AT32_UART4_SUPPRESS_ISR
+#define AT32_UART5_SUPPRESS_ISR
+#define AT32_USART6_SUPPRESS_ISR
+#define AT32_UART7_SUPPRESS_ISR
+#define AT32_UART8_SUPPRESS_ISR
+/** @} */
+
+/**
+ * @name ISR names and numbers
+ * @{
+ */
+/*
+ * ADC units.
+ */
+#define AT32_ADC_HANDLER Vector88
+#define AT32_ADC_NUMBER 18
+
+/*
+ * CAN units.
+ */
+#define AT32_CAN1_TX_HANDLER Vector8C
+#define AT32_CAN1_RX0_HANDLER Vector90
+#define AT32_CAN1_RX1_HANDLER Vector94
+#define AT32_CAN1_SCE_HANDLER Vector98
+
+#define AT32_CAN1_TX_NUMBER 19
+#define AT32_CAN1_RX0_NUMBER 20
+#define AT32_CAN1_RX1_NUMBER 21
+#define AT32_CAN1_SCE_NUMBER 22
+
+/*
+ * DMA units.
+ */
+#define AT32_DMA1_CH1_HANDLER Vector6C
+#define AT32_DMA1_CH2_HANDLER Vector70
+#define AT32_DMA1_CH3_HANDLER Vector74
+#define AT32_DMA1_CH4_HANDLER Vector78
+#define AT32_DMA1_CH5_HANDLER Vector7C
+#define AT32_DMA1_CH6_HANDLER Vector80
+#define AT32_DMA1_CH7_HANDLER Vector84
+#define AT32_DMA2_CH1_HANDLER Vector120
+#define AT32_DMA2_CH2_HANDLER Vector124
+#define AT32_DMA2_CH3_HANDLER Vector128
+#define AT32_DMA2_CH4_HANDLER Vector12C
+#define AT32_DMA2_CH5_HANDLER Vector130
+#define AT32_DMA2_CH6_HANDLER Vector150
+#define AT32_DMA2_CH7_HANDLER Vector154
+#define AT32_DMAMUX_HANDLER Vector1B8
+
+#define AT32_DMA1_CH1_NUMBER 11
+#define AT32_DMA1_CH2_NUMBER 12
+#define AT32_DMA1_CH3_NUMBER 13
+#define AT32_DMA1_CH4_NUMBER 14
+#define AT32_DMA1_CH5_NUMBER 15
+#define AT32_DMA1_CH6_NUMBER 16
+#define AT32_DMA1_CH7_NUMBER 17
+#define AT32_DMA2_CH1_NUMBER 56
+#define AT32_DMA2_CH2_NUMBER 57
+#define AT32_DMA2_CH3_NUMBER 58
+#define AT32_DMA2_CH4_NUMBER 59
+#define AT32_DMA2_CH5_NUMBER 60
+#define AT32_DMA2_CH6_NUMBER 68
+#define AT32_DMA2_CH7_NUMBER 69
+#define AT32_DMAMUX_NUMBER 94
+
+/*
+ * ERTC unit.
+ */
+#define AT32_ERTC_TAMP_STAMP_HANDLER Vector48
+#define AT32_ERTC_WKUP_HANDLER Vector4C
+#define AT32_ERTC_ALARM_HANDLER VectorE4
+
+#define AT32_ERTC_TAMP_STAMP_NUMBER 2
+#define AT32_ERTC_WKUP_NUMBER 3
+#define AT32_ERTC_ALARM_NUMBER 41
+
+#define AT32_ERTC_ALARM_EXINT 17
+#define AT32_ERTC_TAMP_STAMP_EXINT 21
+#define AT32_ERTC_WKUP_EXINT 22
+#define AT32_ERTC_IRQ_ENABLE() do { \
+ nvicEnableVector(AT32_ERTC_TAMP_STAMP_NUMBER, AT32_IRQ_EXINT21_PRIORITY); \
+ nvicEnableVector(AT32_ERTC_WKUP_NUMBER, AT32_IRQ_EXINT22_PRIORITY); \
+ nvicEnableVector(AT32_ERTC_ALARM_NUMBER, AT32_IRQ_EXINT17_PRIORITY); \
+} while (false)
+
+/*
+ * EXINT unit.
+ */
+#define AT32_EXINT0_HANDLER Vector58
+#define AT32_EXINT1_HANDLER Vector5C
+#define AT32_EXINT2_HANDLER Vector60
+#define AT32_EXINT3_HANDLER Vector64
+#define AT32_EXINT4_HANDLER Vector68
+#define AT32_EXINT5_9_HANDLER Vector9C
+#define AT32_EXINT10_15_HANDLER VectorE0
+#define AT32_EXINT16_HANDLER Vector44 /* PVM */
+#define AT32_EXINT17_HANDLER VectorE4 /* ERTC ALARM */
+#define AT32_EXINT18_HANDLER VectorE8 /* OTGFS1 WAKEUP */
+#define AT32_EXINT20_HANDLER Vector170 /* OTGHS WAKEUP */
+#define AT32_EXINT21_HANDLER Vector48 /* ERTC TAMP */
+#define AT32_EXINT22_HANDLER Vector4C /* ERTC WAKEUP */
+
+#define AT32_EXINT0_NUMBER 6
+#define AT32_EXINT1_NUMBER 7
+#define AT32_EXINT2_NUMBER 8
+#define AT32_EXINT3_NUMBER 9
+#define AT32_EXINT4_NUMBER 10
+#define AT32_EXINT5_9_NUMBER 23
+#define AT32_EXINT10_15_NUMBER 40
+#define AT32_EXINT16_NUMBER 1
+#define AT32_EXINT17_NUMBER 41
+#define AT32_EXINT18_NUMBER 42
+#define AT32_EXINT20_NUMBER 76
+#define AT32_EXINT21_NUMBER 2
+#define AT32_EXINT22_NUMBER 3
+
+/*
+ * I2C units.
+ */
+#define AT32_I2C1_EVENT_HANDLER VectorBC
+#define AT32_I2C1_ERROR_HANDLER VectorC0
+#define AT32_I2C2_EVENT_HANDLER VectorC4
+#define AT32_I2C2_ERROR_HANDLER VectorC8
+#define AT32_I2C3_EVENT_HANDLER Vector160
+#define AT32_I2C3_ERROR_HANDLER Vector164
+
+#define AT32_I2C1_EVENT_NUMBER 31
+#define AT32_I2C1_ERROR_NUMBER 32
+#define AT32_I2C2_EVENT_NUMBER 33
+#define AT32_I2C2_ERROR_NUMBER 34
+#define AT32_I2C3_EVENT_NUMBER 72
+#define AT32_I2C3_ERROR_NUMBER 73
+
+/*
+ * USB units.
+ */
+#define AT32_OTG1_HANDLER Vector14C
+#define AT32_OTG2_HANDLER Vector174
+#define AT32_OTG2_EP1OUT_HANDLER Vector168
+#define AT32_OTG2_EP1IN_HANDLER Vector16C
+
+#define AT32_OTG1_NUMBER 67
+#define AT32_OTG2_NUMBER 77
+#define AT32_OTG2_EP1OUT_NUMBER 74
+#define AT32_OTG2_EP1IN_NUMBER 75
+
+/*
+ * TMR units.
+ */
+#define AT32_TMR1_BRK_TMR9_HANDLER VectorA0
+#define AT32_TMR1_OVF_TMR10_HANDLER VectorA4
+#define AT32_TMR1_HALL_TMR11_HANDLER VectorA8
+#define AT32_TMR1_CH_HANDLER VectorAC
+#define AT32_TMR2_HANDLER VectorB0
+#define AT32_TMR3_HANDLER VectorB4
+#define AT32_TMR4_HANDLER VectorB8
+#define AT32_TMR6_HANDLER Vector118
+#define AT32_TMR7_HANDLER Vector11C
+#define AT32_TMR13_HANDLER VectorF0
+#define AT32_TMR14_HANDLER VectorF4
+
+#define AT32_TMR1_BRK_TMR9_NUMBER 24
+#define AT32_TMR1_OVF_TMR10_NUMBER 25
+#define AT32_TMR1_HALL_TMR11_NUMBER 26
+#define AT32_TMR1_CH_NUMBER 27
+#define AT32_TMR2_NUMBER 28
+#define AT32_TMR3_NUMBER 29
+#define AT32_TMR4_NUMBER 30
+#define AT32_TMR6_NUMBER 54
+#define AT32_TMR7_NUMBER 55
+#define AT32_TMR13_NUMBER 44
+#define AT32_TMR14_NUMBER 45
+
+/*
+ * USART units.
+ */
+#define AT32_USART1_HANDLER VectorD4
+#define AT32_USART2_HANDLER VectorD8
+#define AT32_USART3_HANDLER VectorDC
+#define AT32_UART4_HANDLER Vector110
+#define AT32_UART5_HANDLER Vector114
+#define AT32_USART6_HANDLER Vector15C
+#define AT32_UART7_HANDLER Vector188
+#define AT32_UART8_HANDLER Vector18C
+
+#define AT32_USART1_NUMBER 37
+#define AT32_USART2_NUMBER 38
+#define AT32_USART3_NUMBER 39
+#define AT32_UART4_NUMBER 52
+#define AT32_UART5_NUMBER 53
+#define AT32_USART6_NUMBER 71
+#define AT32_UART7_NUMBER 82
+#define AT32_UART8_NUMBER 83
+
+/*
+ * ACC units.
+ */
+#define AT32_ACC_HANDLER Vector1DC
+#define AT32_ACC_NUMBER 103
+
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void irqInit(void);
+ void irqDeinit(void);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AT32_ISR_H */
+
+/** @} */
diff --git a/os/hal/ports/AT32/AT32F405xx/at32_registry.h b/os/hal/ports/AT32/AT32F405xx/at32_registry.h
new file mode 100644
index 0000000000..6235b66030
--- /dev/null
+++ b/os/hal/ports/AT32/AT32F405xx/at32_registry.h
@@ -0,0 +1,579 @@
+/*
+ ChibiOS - Copyright (C) 2023..2024 Zhaqian
+ ChibiOS - Copyright (C) 2024 Maxjta
+
+ Licensed 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.
+*/
+
+/**
+ * @file AT32F405xx/at32_registry.h
+ * @brief AT32F405xx capabilities registry.
+ *
+ * @addtogroup HAL
+ * @{
+ */
+
+#ifndef AT32_REGISTRY_H
+#define AT32_REGISTRY_H
+
+/*===========================================================================*/
+/* Platform capabilities. */
+/*===========================================================================*/
+#if defined(AT32F402Kx) || defined(AT32F405Kx) || defined(__DOXYGEN__)
+/**
+ * @name AT32F402_5Kx capabilities
+ * @{
+ */
+/* ADC attributes.*/
+#define AT32_HAS_ADC1 TRUE
+#define AT32_HAS_ADC2 FALSE
+#define AT32_HAS_ADC3 FALSE
+
+/* CAN attributes.*/
+#define AT32_HAS_CAN1 TRUE
+#define AT32_HAS_CAN2 FALSE
+#define AT32_CAN_MAX_FILTERS 14
+
+/* DAC attributes.*/
+#define AT32_HAS_DAC1_CH1 FALSE
+#define AT32_HAS_DAC1_CH2 FALSE
+
+/* DMA attributes.*/
+#define AT32_ADVANCED_DMA TRUE
+#define AT32_DMA_SUPPORTS_DMAMUX TRUE
+#define AT32_DMA_SUPPORTS_CSELR FALSE
+
+#define AT32_DMA1_NUM_CHANNELS 7
+#define AT32_DMA2_NUM_CHANNELS 7
+
+/* ETH attributes.*/
+#define AT32_HAS_ETH FALSE
+
+/* EXINT attributes.*/
+#define AT32_EXINT_NUM_LINES 22
+#define AT32_EXINT_INTEN_MASK 0x00000000U
+
+/* Flash attributes.*/
+#define AT32_FLASH_NUMBER_OF_BANKS 1
+#if defined(AT32F402xB) || defined(AT32F405xB)
+#define AT32_FLASH_SECTOR_SIZE 1024U
+#elif defined(AT32F402xC) || defined(AT32F405xC)
+#define AT32_FLASH_SECTOR_SIZE 2048U
+#endif
+#if !defined(AT32_FLASH_SECTORS_PER_BANK) || defined(__DOXYGEN__)
+#define AT32_FLASH_SECTORS_PER_BANK 128 /* Maximum, can be redefined.*/
+#endif
+
+/* GPIO attributes.*/
+#define AT32_HAS_GPIOA TRUE
+#define AT32_HAS_GPIOB TRUE
+#define AT32_HAS_GPIOC FALSE
+#define AT32_HAS_GPIOD FALSE
+#define AT32_HAS_GPIOE FALSE
+#define AT32_HAS_GPIOF TRUE
+#define AT32_HAS_GPIOG FALSE
+#define AT32_HAS_GPIOH FALSE
+#define AT32_HAS_GPIOI FALSE
+#define AT32_HAS_GPIOJ FALSE
+#define AT32_HAS_GPIOK FALSE
+
+#define AT32_GPIO_EN_MASK (CRM_AHBEN1_GPIOAEN | \
+ CRM_AHBEN1_GPIOBEN | \
+ CRM_AHBEN1_GPIOFEN)
+
+/* I2C attributes.*/
+#define AT32_HAS_I2C1 TRUE
+#define AT32_HAS_I2C2 TRUE
+#define AT32_HAS_I2C3 TRUE
+
+/* RTC attributes.*/
+#define AT32_HAS_ERTC TRUE
+#define AT32_ERTC_HAS_SUBSECONDS TRUE
+#define AT32_ERTC_IS_CALENDAR TRUE
+#define AT32_ERTC_HAS_PERIODIC_WAKEUPS TRUE
+#define AT32_ERTC_NUM_ALARMS 2
+#define AT32_ERTC_STORAGE_SIZE 80
+
+/* SDIO attributes.*/
+#define AT32_HAS_SDIO FALSE
+
+/* SPI attributes.*/
+#define AT32_HAS_SPI1 TRUE
+#define AT32_SPI1_SUPPORTS_I2S TRUE
+#define AT32_SPI1_I2S_FULLDUPLEX FALSE
+
+#define AT32_HAS_SPI2 FALSE
+
+#define AT32_HAS_SPI3 TRUE
+#define AT32_SPI3_SUPPORTS_I2S TRUE
+#define AT32_SPI3_I2S_FULLDUPLEX FALSE
+
+/* TMR attributes.*/
+#define AT32_TMR_MAX_CHANNELS 4
+
+#define AT32_HAS_TMR1 TRUE
+#define AT32_TMR1_IS_32BITS FALSE
+#define AT32_TMR1_CHANNELS 4
+
+#define AT32_HAS_TMR2 TRUE
+#define AT32_TMR2_IS_32BITS TRUE
+#define AT32_TMR2_CHANNELS 4
+
+#define AT32_HAS_TMR3 TRUE
+#define AT32_TMR3_IS_32BITS FALSE
+#define AT32_TMR3_CHANNELS 4
+
+#define AT32_HAS_TMR4 TRUE
+#define AT32_TMR4_IS_32BITS FALSE
+#define AT32_TMR4_CHANNELS 4
+
+#define AT32_HAS_TMR5 FALSE
+
+#define AT32_HAS_TMR6 TRUE
+#define AT32_TMR6_IS_32BITS FALSE
+#define AT32_TMR6_CHANNELS 0
+
+#define AT32_HAS_TMR7 TRUE
+#define AT32_TMR7_IS_32BITS FALSE
+#define AT32_TMR7_CHANNELS 0
+
+#define AT32_HAS_TMR8 FALSE
+
+#define AT32_HAS_TMR9 TRUE
+#define AT32_TMR9_IS_32BITS FALSE
+#define AT32_TMR9_CHANNELS 2
+
+#define AT32_HAS_TMR10 TRUE
+#define AT32_TMR10_IS_32BITS FALSE
+#define AT32_TMR10_CHANNELS 1
+
+#define AT32_HAS_TMR11 TRUE
+#define AT32_TMR11_IS_32BITS FALSE
+#define AT32_TMR11_CHANNELS 1
+
+#define AT32_HAS_TMR12 FALSE
+
+#define AT32_HAS_TMR13 TRUE
+#define AT32_TMR13_IS_32BITS FALSE
+#define AT32_TMR13_CHANNELS 1
+
+#define AT32_HAS_TMR14 TRUE
+#define AT32_TMR14_IS_32BITS FALSE
+#define AT32_TMR14_CHANNELS 1
+
+/* USART attributes.*/
+#define AT32_HAS_USART1 TRUE
+#define AT32_HAS_USART2 TRUE
+#define AT32_HAS_USART3 TRUE
+#define AT32_HAS_UART4 TRUE
+#define AT32_HAS_UART5 TRUE
+#define AT32_HAS_USART6 TRUE
+#define AT32_HAS_UART7 TRUE
+#define AT32_HAS_UART8 FALSE
+
+/* USB attributes.*/
+#define AT32_OTG_STEPPING 2
+#define AT32_HAS_OTG1 TRUE
+#define AT32_OTG1_ENDPOINTS 8
+
+#if defined(AT32F405xx)
+#define AT32_HAS_OTG2 TRUE
+#define AT32_OTG2_ENDPOINTS 8
+#define AT32_OTG2_SUPPORTS_HS TRUE
+#else
+#define AT32_HAS_OTG2 FALSE
+#endif
+
+#define AT32_HAS_USB FALSE
+
+/* IWDG attributes.*/
+#define AT32_HAS_IWDG TRUE
+#define AT32_IWDG_IS_WINDOWED TRUE
+
+/* FSMC attributes.*/
+#define AT32_HAS_FSMC FALSE
+
+/* CRC attributes.*/
+#define AT32_HAS_CRC TRUE
+#define AT32_CRC_PROGRAMMABLE FALSE
+
+#endif /* defined(AT32F402Kx) || defined(AT32F405Kx) */
+
+#if defined(AT32F402Cx) || defined(AT32F405Cx)
+/**
+ * @name AT32F402_5Cx capabilities
+ * @{
+ */
+/* ADC attributes.*/
+#define AT32_HAS_ADC1 TRUE
+#define AT32_HAS_ADC2 FALSE
+#define AT32_HAS_ADC3 FALSE
+
+/* CAN attributes.*/
+#define AT32_HAS_CAN1 TRUE
+#define AT32_HAS_CAN2 FALSE
+#define AT32_CAN_MAX_FILTERS 14
+
+/* DAC attributes.*/
+#define AT32_HAS_DAC1_CH1 FALSE
+#define AT32_HAS_DAC1_CH2 FALSE
+
+/* DMA attributes.*/
+#define AT32_ADVANCED_DMA TRUE
+#define AT32_DMA_SUPPORTS_DMAMUX TRUE
+#define AT32_DMA_SUPPORTS_CSELR FALSE
+
+#define AT32_DMA1_NUM_CHANNELS 7
+#define AT32_DMA2_NUM_CHANNELS 7
+
+/* ETH attributes.*/
+#define AT32_HAS_ETH FALSE
+
+/* EXINT attributes.*/
+#define AT32_EXINT_NUM_LINES 22
+#define AT32_EXINT_INTEN_MASK 0x00000000U
+
+/* Flash attributes.*/
+#define AT32_FLASH_NUMBER_OF_BANKS 1
+#if defined(AT32F402xB) || defined(AT32F405xB)
+#define AT32_FLASH_SECTOR_SIZE 1024U
+#elif defined(AT32F402xC) || defined(AT32F405xC)
+#define AT32_FLASH_SECTOR_SIZE 2048U
+#endif
+#if !defined(AT32_FLASH_SECTORS_PER_BANK) || defined(__DOXYGEN__)
+#define AT32_FLASH_SECTORS_PER_BANK 128 /* Maximum, can be redefined.*/
+#endif
+
+/* GPIO attributes.*/
+#define AT32_HAS_GPIOA TRUE
+#define AT32_HAS_GPIOB TRUE
+#define AT32_HAS_GPIOC TRUE
+#define AT32_HAS_GPIOD FALSE
+#define AT32_HAS_GPIOE FALSE
+#define AT32_HAS_GPIOF TRUE
+#define AT32_HAS_GPIOG FALSE
+#define AT32_HAS_GPIOH FALSE
+#define AT32_HAS_GPIOI FALSE
+#define AT32_HAS_GPIOJ FALSE
+#define AT32_HAS_GPIOK FALSE
+
+#define AT32_GPIO_EN_MASK (CRM_AHBEN1_GPIOAEN | \
+ CRM_AHBEN1_GPIOBEN | \
+ CRM_AHBEN1_GPIOCEN | \
+ CRM_AHBEN1_GPIOFEN)
+
+/* I2C attributes.*/
+#define AT32_HAS_I2C1 TRUE
+#define AT32_HAS_I2C2 TRUE
+#define AT32_HAS_I2C3 TRUE
+
+/* RTC attributes.*/
+#define AT32_HAS_ERTC TRUE
+#define AT32_ERTC_HAS_SUBSECONDS TRUE
+#define AT32_ERTC_IS_CALENDAR TRUE
+#define AT32_ERTC_HAS_PERIODIC_WAKEUPS TRUE
+#define AT32_ERTC_NUM_ALARMS 2
+#define AT32_ERTC_STORAGE_SIZE 80
+
+/* SDIO attributes.*/
+#define AT32_HAS_SDIO FALSE
+
+/* SPI attributes.*/
+#define AT32_HAS_SPI1 TRUE
+#define AT32_SPI1_SUPPORTS_I2S TRUE
+#define AT32_SPI1_I2S_FULLDUPLEX FALSE
+
+#define AT32_HAS_SPI2 TRUE
+#define AT32_SPI2_SUPPORTS_I2S TRUE
+#define AT32_SPI2_I2S_FULLDUPLEX FALSE
+
+#define AT32_HAS_SPI3 TRUE
+#define AT32_SPI3_SUPPORTS_I2S TRUE
+#define AT32_SPI3_I2S_FULLDUPLEX FALSE
+
+/* TMR attributes.*/
+#define AT32_TMR_MAX_CHANNELS 4
+
+#define AT32_HAS_TMR1 TRUE
+#define AT32_TMR1_IS_32BITS FALSE
+#define AT32_TMR1_CHANNELS 4
+
+#define AT32_HAS_TMR2 TRUE
+#define AT32_TMR2_IS_32BITS TRUE
+#define AT32_TMR2_CHANNELS 4
+
+#define AT32_HAS_TMR3 TRUE
+#define AT32_TMR3_IS_32BITS FALSE
+#define AT32_TMR3_CHANNELS 4
+
+#define AT32_HAS_TMR4 TRUE
+#define AT32_TMR4_IS_32BITS FALSE
+#define AT32_TMR4_CHANNELS 4
+
+#define AT32_HAS_TMR5 FALSE
+
+#define AT32_HAS_TMR6 TRUE
+#define AT32_TMR6_IS_32BITS FALSE
+#define AT32_TMR6_CHANNELS 0
+
+#define AT32_HAS_TMR7 TRUE
+#define AT32_TMR7_IS_32BITS FALSE
+#define AT32_TMR7_CHANNELS 0
+
+#define AT32_HAS_TMR8 FALSE
+
+#define AT32_HAS_TMR9 TRUE
+#define AT32_TMR9_IS_32BITS FALSE
+#define AT32_TMR9_CHANNELS 2
+
+#define AT32_HAS_TMR10 TRUE
+#define AT32_TMR10_IS_32BITS FALSE
+#define AT32_TMR10_CHANNELS 1
+
+#define AT32_HAS_TMR11 TRUE
+#define AT32_TMR11_IS_32BITS FALSE
+#define AT32_TMR11_CHANNELS 1
+
+#define AT32_HAS_TMR12 FALSE
+
+#define AT32_HAS_TMR13 TRUE
+#define AT32_TMR13_IS_32BITS FALSE
+#define AT32_TMR13_CHANNELS 1
+
+#define AT32_HAS_TMR14 TRUE
+#define AT32_TMR14_IS_32BITS FALSE
+#define AT32_TMR14_CHANNELS 1
+
+/* USART attributes.*/
+#define AT32_HAS_USART1 TRUE
+#define AT32_HAS_USART2 TRUE
+#define AT32_HAS_USART3 TRUE
+#define AT32_HAS_UART4 TRUE
+#define AT32_HAS_UART5 TRUE
+#define AT32_HAS_USART6 TRUE
+#define AT32_HAS_UART7 TRUE
+#define AT32_HAS_UART8 FALSE
+
+/* USB attributes.*/
+#define AT32_OTG_STEPPING 2
+#define AT32_HAS_OTG1 TRUE
+#define AT32_OTG1_ENDPOINTS 8
+
+#if defined(AT32F405xx)
+#define AT32_HAS_OTG2 TRUE
+#define AT32_OTG2_ENDPOINTS 8
+#else
+#define AT32_HAS_OTG2 FALSE
+#endif
+
+#define AT32_HAS_USB FALSE
+
+/* IWDG attributes.*/
+#define AT32_HAS_IWDG TRUE
+#define AT32_IWDG_IS_WINDOWED TRUE
+
+/* FSMC attributes.*/
+#define AT32_HAS_FSMC FALSE
+
+/* CRC attributes.*/
+#define AT32_HAS_CRC TRUE
+#define AT32_CRC_PROGRAMMABLE FALSE
+
+#endif /* defined(AT32F402Cx) || defined(AT32F405Cx) */
+
+#if defined(AT32F402Rx) || defined(AT32F405Rx)
+/**
+ * @name AT32F402_405Rx capabilities
+ * @{
+ */
+/* ADC attributes.*/
+#define AT32_HAS_ADC1 TRUE
+#define AT32_HAS_ADC2 FALSE
+#define AT32_HAS_ADC3 FALSE
+
+/* CAN attributes.*/
+#define AT32_HAS_CAN1 TRUE
+#define AT32_HAS_CAN2 FALSE
+#define AT32_CAN_MAX_FILTERS 14
+
+/* DAC attributes.*/
+#define AT32_HAS_DAC1_CH1 FALSE
+#define AT32_HAS_DAC1_CH2 FALSE
+
+/* DMA attributes.*/
+#define AT32_ADVANCED_DMA TRUE
+#define AT32_DMA_SUPPORTS_DMAMUX TRUE
+#define AT32_DMA_SUPPORTS_CSELR FALSE
+
+#define AT32_DMA1_NUM_CHANNELS 7
+#define AT32_DMA2_NUM_CHANNELS 7
+
+/* ETH attributes.*/
+#define AT32_HAS_ETH FALSE
+
+/* EXINT attributes.*/
+#define AT32_EXINT_NUM_LINES 22
+#define AT32_EXINT_INTEN_MASK 0x00000000U
+
+/* Flash attributes.*/
+#define AT32_FLASH_NUMBER_OF_BANKS 1
+#if defined(AT32F402xB) || defined(AT32F405xB)
+#define AT32_FLASH_SECTOR_SIZE 1024U
+#elif defined(AT32F402xC) || defined(AT32F405xC)
+#define AT32_FLASH_SECTOR_SIZE 2048U
+#endif
+#if !defined(AT32_FLASH_SECTORS_PER_BANK) || defined(__DOXYGEN__)
+#define AT32_FLASH_SECTORS_PER_BANK 128 /* Maximum, can be redefined.*/
+#endif
+
+/* GPIO attributes.*/
+#define AT32_HAS_GPIOA TRUE
+#define AT32_HAS_GPIOB TRUE
+#define AT32_HAS_GPIOC TRUE
+#define AT32_HAS_GPIOD TRUE
+#define AT32_HAS_GPIOE FALSE
+#define AT32_HAS_GPIOF TRUE
+#define AT32_HAS_GPIOG FALSE
+#define AT32_HAS_GPIOH FALSE
+#define AT32_HAS_GPIOI FALSE
+#define AT32_HAS_GPIOJ FALSE
+#define AT32_HAS_GPIOK FALSE
+
+#define AT32_GPIO_EN_MASK (CRM_AHBEN1_GPIOAEN | \
+ CRM_AHBEN1_GPIOBEN | \
+ CRM_AHBEN1_GPIOCEN | \
+ CRM_AHBEN1_GPIODEN | \
+ CRM_AHBEN1_GPIOFEN)
+
+/* I2C attributes.*/
+#define AT32_HAS_I2C1 TRUE
+#define AT32_HAS_I2C2 TRUE
+#define AT32_HAS_I2C3 TRUE
+
+/* RTC attributes.*/
+#define AT32_HAS_ERTC TRUE
+#define AT32_ERTC_HAS_SUBSECONDS TRUE
+#define AT32_ERTC_IS_CALENDAR TRUE
+#define AT32_ERTC_HAS_PERIODIC_WAKEUPS TRUE
+#define AT32_ERTC_NUM_ALARMS 2
+#define AT32_ERTC_STORAGE_SIZE 80
+
+/* SDIO attributes.*/
+#define AT32_HAS_SDIO FALSE
+
+/* SPI attributes.*/
+#define AT32_HAS_SPI1 TRUE
+#define AT32_SPI1_SUPPORTS_I2S TRUE
+#define AT32_SPI1_I2S_FULLDUPLEX FALSE
+
+#define AT32_HAS_SPI2 TRUE
+#define AT32_SPI2_SUPPORTS_I2S TRUE
+#define AT32_SPI2_I2S_FULLDUPLEX FALSE
+
+#define AT32_HAS_SPI3 TRUE
+#define AT32_SPI3_SUPPORTS_I2S TRUE
+#define AT32_SPI3_I2S_FULLDUPLEX FALSE
+
+/* TMR attributes.*/
+#define AT32_TMR_MAX_CHANNELS 4
+
+#define AT32_HAS_TMR1 TRUE
+#define AT32_TMR1_IS_32BITS FALSE
+#define AT32_TMR1_CHANNELS 4
+
+#define AT32_HAS_TMR2 TRUE
+#define AT32_TMR2_IS_32BITS TRUE
+#define AT32_TMR2_CHANNELS 4
+
+#define AT32_HAS_TMR3 TRUE
+#define AT32_TMR3_IS_32BITS FALSE
+#define AT32_TMR3_CHANNELS 4
+
+#define AT32_HAS_TMR4 TRUE
+#define AT32_TMR4_IS_32BITS FALSE
+#define AT32_TMR4_CHANNELS 4
+
+#define AT32_HAS_TMR5 FALSE
+
+#define AT32_HAS_TMR6 TRUE
+#define AT32_TMR6_IS_32BITS FALSE
+#define AT32_TMR6_CHANNELS 0
+
+#define AT32_HAS_TMR7 TRUE
+#define AT32_TMR7_IS_32BITS FALSE
+#define AT32_TMR7_CHANNELS 0
+
+#define AT32_HAS_TMR8 FALSE
+
+#define AT32_HAS_TMR9 TRUE
+#define AT32_TMR9_IS_32BITS FALSE
+#define AT32_TMR9_CHANNELS 2
+
+#define AT32_HAS_TMR10 TRUE
+#define AT32_TMR10_IS_32BITS FALSE
+#define AT32_TMR10_CHANNELS 1
+
+#define AT32_HAS_TMR11 TRUE
+#define AT32_TMR11_IS_32BITS FALSE
+#define AT32_TMR11_CHANNELS 1
+
+#define AT32_HAS_TMR12 FALSE
+
+#define AT32_HAS_TMR13 TRUE
+#define AT32_TMR13_IS_32BITS FALSE
+#define AT32_TMR13_CHANNELS 1
+
+#define AT32_HAS_TMR14 TRUE
+#define AT32_TMR14_IS_32BITS FALSE
+#define AT32_TMR14_CHANNELS 1
+
+/* USART attributes.*/
+#define AT32_HAS_USART1 TRUE
+#define AT32_HAS_USART2 TRUE
+#define AT32_HAS_USART3 TRUE
+#define AT32_HAS_UART4 TRUE
+#define AT32_HAS_UART5 TRUE
+#define AT32_HAS_USART6 TRUE
+#define AT32_HAS_UART7 TRUE
+#define AT32_HAS_UART8 TRUE
+
+/* USB attributes.*/
+#define AT32_OTG_STEPPING 2
+#define AT32_HAS_OTG1 TRUE
+#define AT32_OTG1_ENDPOINTS 8
+
+#if defined(AT32F405xx)
+#define AT32_HAS_OTG2 TRUE
+#define AT32_OTG2_ENDPOINTS 8
+#else
+#define AT32_HAS_OTG2 FALSE
+#endif
+
+#define AT32_HAS_USB FALSE
+
+/* IWDG attributes.*/
+#define AT32_HAS_IWDG TRUE
+#define AT32_IWDG_IS_WINDOWED TRUE
+
+/* FSMC attributes.*/
+#define AT32_HAS_FSMC FALSE
+
+/* CRC attributes.*/
+#define AT32_HAS_CRC TRUE
+#define AT32_CRC_PROGRAMMABLE FALSE
+
+#endif /* defined(AT32F402Rx) || defined(AT32F405Rx) */
+
+#endif /* AT32_REGISTRY_H */
+
+/** @} */
diff --git a/os/hal/ports/AT32/AT32F405xx/hal_efl_lld.c b/os/hal/ports/AT32/AT32F405xx/hal_efl_lld.c
new file mode 100644
index 0000000000..8020eb3707
--- /dev/null
+++ b/os/hal/ports/AT32/AT32F405xx/hal_efl_lld.c
@@ -0,0 +1,486 @@
+/*
+ ChibiOS - Copyright (C) 2023..2024 Zhaqian
+ ChibiOS - Copyright (C) 2024 Maxjta
+
+ Licensed 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.
+*/
+
+/**
+ * @file AT32F405xx/hal_efl_lld.c
+ * @brief AT32F405xx Embedded Flash subsystem low level driver source.
+ *
+ * @addtogroup HAL_EFL
+ * @{
+ */
+
+#include
+
+#include "hal.h"
+
+#if (HAL_USE_EFL == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#define AT32_FLASH_LINE_SIZE 2U
+#define AT32_FLASH_LINE_MASK (AT32_FLASH_LINE_SIZE - 1U)
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief EFL1 driver identifier.
+ */
+EFlashDriver EFLD1;
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+static const flash_descriptor_t efl_lld_descriptor = {
+ .attributes = FLASH_ATTR_ERASED_IS_ONE |
+ FLASH_ATTR_MEMORY_MAPPED,
+ .page_size = AT32_FLASH_LINE_SIZE,
+ .sectors_count = AT32_FLASH_NUMBER_OF_BANKS *
+ AT32_FLASH_SECTORS_PER_BANK,
+ .sectors = NULL,
+ .sectors_size = AT32_FLASH_SECTOR_SIZE,
+ .address = (uint8_t *)FLASH_BASE,
+ .size = AT32_FLASH_NUMBER_OF_BANKS *
+ AT32_FLASH_SECTORS_PER_BANK *
+ AT32_FLASH_SECTOR_SIZE
+};
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void at32_flash_lock(EFlashDriver *eflp) {
+
+ eflp->flash->CTRL |= FLASH_CTRL_OPLK;
+}
+
+static inline void at32_flash_unlock(EFlashDriver *eflp) {
+
+ eflp->flash->UNLOCK = FLASH_UNLOCK_KEY1;
+ eflp->flash->UNLOCK = FLASH_UNLOCK_KEY2;
+}
+
+static inline void at32_flash_enable_pgm(EFlashDriver *eflp) {
+
+ eflp->flash->CTRL |= FLASH_CTRL_FPRGM;
+}
+
+static inline void at32_flash_disable_pgm(EFlashDriver *eflp) {
+
+ eflp->flash->CTRL &= ~FLASH_CTRL_FPRGM;
+}
+
+static inline void at32_flash_clear_status(EFlashDriver *eflp) {
+
+ eflp->flash->STS = FLASH_STS_PRGMERR | FLASH_STS_EPPERR;
+}
+
+static inline uint32_t at32_flash_is_busy(EFlashDriver *eflp) {
+
+ return (eflp->flash->STS & FLASH_STS_OBF);
+}
+
+static inline void at32_flash_wait_busy(EFlashDriver *eflp) {
+
+ /* Wait for busy bit clear.*/
+ while (at32_flash_is_busy(eflp) != 0U) {
+ }
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level Embedded Flash driver initialization.
+ *
+ * @notapi
+ */
+void efl_lld_init(void) {
+
+ /* Driver initialization.*/
+ eflObjectInit(&EFLD1);
+ EFLD1.flash = FLASH;
+}
+
+/**
+ * @brief Configures and activates the Embedded Flash peripheral.
+ *
+ * @param[in] eflp pointer to a @p EFlashDriver structure
+ *
+ * @notapi
+ */
+void efl_lld_start(EFlashDriver *eflp) {
+
+ at32_flash_unlock(eflp);
+ eflp->flash->CTRL = 0x00000000U;
+}
+
+/**
+ * @brief Deactivates the Embedded Flash peripheral.
+ *
+ * @param[in] eflp pointer to a @p EFlashDriver structure
+ *
+ * @notapi
+ */
+void efl_lld_stop(EFlashDriver *eflp) {
+
+ at32_flash_lock(eflp);
+}
+
+/**
+ * @brief Gets the flash descriptor structure.
+ *
+ * @param[in] ip pointer to a @p EFlashDriver instance
+ * @return A flash device descriptor.
+ *
+ * @notapi
+ */
+const flash_descriptor_t *efl_lld_get_descriptor(void *instance) {
+
+ (void)instance;
+
+ return &efl_lld_descriptor;
+}
+
+/**
+ * @brief Read operation.
+ *
+ * @param[in] ip pointer to a @p EFlashDriver instance
+ * @param[in] offset flash offset
+ * @param[in] n number of bytes to be read
+ * @param[out] rp pointer to the data buffer
+ * @return An error code.
+ * @retval FLASH_NO_ERROR if there is no erase operation in progress.
+ * @retval FLASH_BUSY_ERASING if there is an erase operation in progress.
+ * @retval FLASH_ERROR_READ if the read operation failed.
+ * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed.
+ *
+ * @notapi
+ */
+flash_error_t efl_lld_read(void *instance, flash_offset_t offset,
+ size_t n, uint8_t *rp) {
+ EFlashDriver *devp = (EFlashDriver *)instance;
+ flash_error_t err = FLASH_NO_ERROR;
+
+ osalDbgCheck((instance != NULL) && (rp != NULL) && (n > 0U));
+ osalDbgCheck((size_t)offset + n <= (size_t)efl_lld_descriptor.size);
+ osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE),
+ "invalid state");
+
+ /* No reading while erasing.*/
+ if (devp->state == FLASH_ERASE) {
+ return FLASH_BUSY_ERASING;
+ }
+
+ /* FLASH_READY state while the operation is performed.*/
+ devp->state = FLASH_READ;
+
+ /* Clearing error status bits.*/
+ at32_flash_clear_status(devp);
+
+ /* Actual read implementation.*/
+ memcpy((void *)rp, (const void *)(efl_lld_descriptor.address + offset), n);
+
+ /* Ready state again.*/
+ devp->state = FLASH_READY;
+
+ return err;
+}
+
+/**
+ * @brief Program operation.
+ * @note It is only possible to write erased pages once except
+ * when writing all zeroes.
+ *
+ * @param[in] ip pointer to a @p EFlashDriver instance
+ * @param[in] offset flash offset
+ * @param[in] n number of bytes to be programmed
+ * @param[in] pp pointer to the data buffer
+ * @return An error code.
+ * @retval FLASH_NO_ERROR if there is no erase operation in progress.
+ * @retval FLASH_BUSY_ERASING if there is an erase operation in progress.
+ * @retval FLASH_ERROR_PROGRAM if the program operation failed.
+ * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed.
+ *
+ * @notapi
+ */
+flash_error_t efl_lld_program(void *instance, flash_offset_t offset,
+ size_t n, const uint8_t *pp) {
+ EFlashDriver *devp = (EFlashDriver *)instance;
+ flash_error_t err = FLASH_NO_ERROR;
+
+ osalDbgCheck((instance != NULL) && (pp != NULL) && (n > 0U));
+ osalDbgCheck((size_t)offset + n <= (size_t)efl_lld_descriptor.size);
+
+ osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE),
+ "invalid state");
+
+ /* No programming while erasing.*/
+ if (devp->state == FLASH_ERASE) {
+ return FLASH_BUSY_ERASING;
+ }
+
+ /* FLASH_PGM state while the operation is performed.*/
+ devp->state = FLASH_PGM;
+
+ /* Clearing error status bits.*/
+ at32_flash_clear_status(devp);
+
+ /* Enabling PGM mode in the controller.*/
+ at32_flash_enable_pgm(devp);
+
+ /* Actual program implementation.*/
+ while (n > 0U) {
+ volatile uint16_t *address;
+
+ union {
+ uint16_t hw[AT32_FLASH_LINE_SIZE / sizeof (uint16_t)];
+ uint8_t b[AT32_FLASH_LINE_SIZE / sizeof (uint8_t)];
+ } line;
+
+ /* Unwritten bytes are initialized to all ones.*/
+ line.hw[0] = 0xFFFFU;
+
+ /* Programming address aligned to flash lines.*/
+ address = (volatile uint16_t *)(efl_lld_descriptor.address +
+ (offset & ~AT32_FLASH_LINE_MASK));
+
+ /* Copying data inside the prepared line.*/
+ do {
+ line.b[offset & AT32_FLASH_LINE_MASK] = *pp;
+ offset++;
+ n--;
+ pp++;
+ }
+ while ((n > 0U) & ((offset & AT32_FLASH_LINE_MASK) != 0U));
+ /* Programming line.*/
+ address[0] = line.hw[0];
+ at32_flash_wait_busy(devp);
+
+ uint32_t sts = devp->flash->STS;
+
+ /* Clearing error status bits.*/
+ at32_flash_clear_status(devp);
+
+ /* Decoding relevant errors.*/
+ if ((sts & FLASH_STS_EPPERR) != 0U) {
+ err = FLASH_ERROR_HW_FAILURE;
+ break;
+ }
+ else if ((sts & FLASH_STS_PRGMERR) != 0U) {
+ err = FLASH_ERROR_PROGRAM;
+ break;
+ }
+ else if ((sts & FLASH_STS_ODF) == 0U) {
+ err = FLASH_ERROR_PROGRAM;
+ break;
+ }
+
+ /* Check for flash error.*/
+ if (address[0] != line.hw[0]) {
+ err = FLASH_ERROR_PROGRAM;
+ break;
+ }
+ }
+
+ /* Disabling PGM mode in the controller.*/
+ at32_flash_disable_pgm(devp);
+
+ /* Ready state again.*/
+ devp->state = FLASH_READY;
+
+ return err;
+}
+
+/**
+ * @brief Starts a whole-device erase operation.
+ * @note This function does nothing, the flash memory is where the program
+ * is running on.
+ *
+ * @param[in] ip pointer to a @p EFlashDriver instance
+ * @return An error code.
+ * @retval FLASH_NO_ERROR if there is no erase operation in progress.
+ * @retval FLASH_BUSY_ERASING if there is an erase operation in progress.
+ * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed.
+ *
+ * @notapi
+ */
+flash_error_t efl_lld_start_erase_all(void *instance) {
+ (void) instance;
+
+ return FLASH_ERROR_UNIMPLEMENTED;
+}
+
+/**
+ * @brief Starts an sector erase operation.
+ *
+ * @param[in] ip pointer to a @p EFlashDriver instance
+ * @param[in] sector sector to be erased
+ * @return An error code.
+ * @retval FLASH_NO_ERROR if there is no erase operation in progress.
+ * @retval FLASH_BUSY_ERASING if there is an erase operation in progress.
+ * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed.
+ *
+ * @notapi
+ */
+flash_error_t efl_lld_start_erase_sector(void *instance,
+ flash_sector_t sector) {
+ EFlashDriver *devp = (EFlashDriver *)instance;
+
+ osalDbgCheck(instance != NULL);
+ osalDbgCheck(sector < efl_lld_descriptor.sectors_count);
+ osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE),
+ "invalid state");
+
+ /* No erasing while erasing.*/
+ if (devp->state == FLASH_ERASE) {
+ return FLASH_BUSY_ERASING;
+ }
+
+ /* FLASH_PGM state while the operation is performed.*/
+ devp->state = FLASH_ERASE;
+
+ /* Clearing error status bits.*/
+ at32_flash_clear_status(devp);
+
+ /* Enable page erase.*/
+ devp->flash->CTRL |= FLASH_CTRL_SECERS;
+
+ /* Set the page.*/
+ devp->flash->ADDR = (uint32_t)(efl_lld_descriptor.address +
+ flashGetSectorOffset(getBaseFlash(devp), sector));
+
+ /* Start the erase.*/
+ devp->flash->CTRL |= FLASH_CTRL_ERSTR;
+
+ return FLASH_NO_ERROR;
+}
+
+/**
+ * @brief Queries the driver for erase operation progress.
+ *
+ * @param[in] ip pointer to a @p EFlashDriver instance
+ * @param[out] wait_time recommended time, in milliseconds, that
+ * should be spent before calling this
+ * function again, can be @p NULL
+ * @return An error code.
+ * @retval FLASH_NO_ERROR if there is no erase operation in progress.
+ * @retval FLASH_BUSY_ERASING if there is an erase operation in progress.
+ * @retval FLASH_ERROR_ERASE if the erase operation failed.
+ * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed.
+ *
+ * @api
+ */
+flash_error_t efl_lld_query_erase(void *instance, uint32_t *wait_time) {
+ EFlashDriver *devp = (EFlashDriver *)instance;
+ flash_error_t err;
+
+ /* If there is an erase in progress then the device must be checked.*/
+ if (devp->state == FLASH_ERASE) {
+
+ /* Checking for operation in progress.*/
+ if (at32_flash_is_busy(devp) == 0U) {
+
+ /* Disabling the various erase control bits.*/
+ devp->flash->CTRL &= ~(FLASH_CTRL_USDERS | FLASH_CTRL_USDPRGM |
+ FLASH_CTRL_BANKERS | FLASH_CTRL_SECERS);
+
+ /* Back to ready state.*/
+ devp->state = FLASH_READY;
+
+ err = FLASH_NO_ERROR;
+ }
+ else {
+ /* Recommended time before polling again, this is a simplified
+ implementation.*/
+ if (wait_time != NULL) {
+ *wait_time = (uint32_t)AT32_FLASH_WAIT_TIME_MS;
+ }
+
+ err = FLASH_BUSY_ERASING;
+ }
+ }
+ else {
+ err = FLASH_NO_ERROR;
+ }
+
+ return err;
+}
+
+/**
+ * @brief Returns the erase state of a sector.
+ *
+ * @param[in] ip pointer to a @p EFlashDriver instance
+ * @param[in] sector sector to be verified
+ * @return An error code.
+ * @retval FLASH_NO_ERROR if the sector is erased.
+ * @retval FLASH_BUSY_ERASING if there is an erase operation in progress.
+ * @retval FLASH_ERROR_VERIFY if the verify operation failed.
+ * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed.
+ *
+ * @notapi
+ */
+flash_error_t efl_lld_verify_erase(void *instance, flash_sector_t sector) {
+ EFlashDriver *devp = (EFlashDriver *)instance;
+ uint32_t *address;
+ flash_error_t err = FLASH_NO_ERROR;
+ unsigned i;
+
+ osalDbgCheck(instance != NULL);
+ osalDbgCheck(sector < efl_lld_descriptor.sectors_count);
+ osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE),
+ "invalid state");
+
+ /* No verifying while erasing.*/
+ if (devp->state == FLASH_ERASE) {
+ return FLASH_BUSY_ERASING;
+ }
+
+ /* Address of the sector.*/
+ address = (uint32_t *)(efl_lld_descriptor.address +
+ flashGetSectorOffset(getBaseFlash(devp), sector));
+
+ /* FLASH_READY state while the operation is performed.*/
+ devp->state = FLASH_READ;
+
+ /* Scanning the sector space.*/
+ for (i = 0U; i < AT32_FLASH_SECTOR_SIZE / sizeof(uint32_t); i++) {
+ if (*address != 0xFFFFFFFFU) {
+ err = FLASH_ERROR_VERIFY;
+ break;
+ }
+ address++;
+ }
+
+ /* Ready state again.*/
+ devp->state = FLASH_READY;
+
+ return err;
+}
+
+#endif /* HAL_USE_EFL == TRUE */
+
+/** @} */
diff --git a/os/hal/ports/AT32/AT32F405xx/hal_efl_lld.h b/os/hal/ports/AT32/AT32F405xx/hal_efl_lld.h
new file mode 100644
index 0000000000..40cd178c6e
--- /dev/null
+++ b/os/hal/ports/AT32/AT32F405xx/hal_efl_lld.h
@@ -0,0 +1,121 @@
+/*
+ ChibiOS - Copyright (C) 2023..2024 Zhaqian
+ ChibiOS - Copyright (C) 2024 Maxjta
+
+ Licensed 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.
+*/
+
+/**
+ * @file AT32F405xx/hal_efl_lld.h
+ * @brief AT32F405xx Embedded Flash subsystem low level driver header.
+ *
+ * @addtogroup HAL_EFL
+ * @{
+ */
+
+#ifndef HAL_EFL_LLD_H
+#define HAL_EFL_LLD_H
+
+#if (HAL_USE_EFL == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name AT32F402_5xx configuration options
+ * @{
+ */
+/**
+ * @brief Suggested wait time during erase operations polling.
+ */
+#if !defined(AT32_FLASH_WAIT_TIME_MS) || defined(__DOXYGEN__)
+#define AT32_FLASH_WAIT_TIME_MS 10
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if !defined(AT32_FLASH_SECTOR_SIZE)
+#error "AT32_FLASH_SECTOR_SIZE not defined in registry"
+#endif
+
+#if !defined(AT32_FLASH_NUMBER_OF_BANKS)
+#error "AT32_FLASH_NUMBER_OF_BANKS not defined in registry"
+#endif
+
+#if !defined(AT32_FLASH_SECTORS_PER_BANK)
+#error "AT32_FLASH_SECTORS_PER_BANK not defined in registry"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level fields of the embedded flash driver structure.
+ */
+#define efl_lld_driver_fields \
+ /* Flash registers.*/ \
+ FLASH_TypeDef *flash
+
+/**
+ * @brief Low level fields of the embedded flash configuration structure.
+ */
+#define efl_lld_config_fields \
+ /* Dummy configuration, it is not needed.*/ \
+ uint32_t dummy
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(__DOXYGEN__)
+extern EFlashDriver EFLD1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void efl_lld_init(void);
+ void efl_lld_start(EFlashDriver *eflp);
+ void efl_lld_stop(EFlashDriver *eflp);
+ const flash_descriptor_t *efl_lld_get_descriptor(void *instance);
+ flash_error_t efl_lld_read(void *instance, flash_offset_t offset,
+ size_t n, uint8_t *rp);
+ flash_error_t efl_lld_program(void *instance, flash_offset_t offset,
+ size_t n, const uint8_t *pp);
+ flash_error_t efl_lld_start_erase_all(void *instance);
+ flash_error_t efl_lld_start_erase_sector(void *instance,
+ flash_sector_t sector);
+ flash_error_t efl_lld_query_erase(void *instance, uint32_t *wait_time);
+ flash_error_t efl_lld_verify_erase(void *instance, flash_sector_t sector);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_EFL == TRUE */
+
+#endif /* HAL_EFL_LLD_H */
+
+/** @} */
diff --git a/os/hal/ports/AT32/AT32F405xx/hal_lld.c b/os/hal/ports/AT32/AT32F405xx/hal_lld.c
new file mode 100644
index 0000000000..5fae394718
--- /dev/null
+++ b/os/hal/ports/AT32/AT32F405xx/hal_lld.c
@@ -0,0 +1,320 @@
+/*
+ ChibiOS - Copyright (C) 2023..2024 Zhaqian
+ ChibiOS - Copyright (C) 2024 Maxjta
+
+ Licensed 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.
+*/
+
+/**
+ * @file AT32F405xx/hal_lld.c
+ * @brief AT32F405xx HAL subsystem low level driver source.
+ *
+ * @addtogroup HAL
+ * @{
+ */
+
+#include "hal.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief CMSIS system core clock variable.
+ * @note It is declared in system_at32f405xx.h.
+ */
+uint32_t SystemCoreClock = AT32_HCLK;
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes the backup domain.
+ * @note WARNING! Changing clock source impossible without resetting
+ * of the whole BKP domain.
+ */
+static void hal_lld_backup_domain_init(void) {
+
+ /* Backup domain access enabled and left open.*/
+ PWC->CTRL |= PWC_CTRL_BPWEN;
+
+ /* Reset BKP domain if different clock source selected.*/
+ if ((CRM->BPDC & AT32_ERTCSEL_MASK) != AT32_ERTCSEL) {
+ /* Backup domain reset.*/
+ CRM->BPDC = CRM_BPDC_BPDRST;
+ CRM->BPDC = 0;
+ }
+
+ /* If enabled then the LEXT is started.*/
+#if AT32_LEXT_ENABLED
+#if defined(AT32_LEXT_BYPASS)
+ /* LEXT Bypass.*/
+ CRM->BPDC |= CRM_BPDC_LEXTEN | CRM_BPDC_LEXTBYPS;
+#else
+ /* No LEXT Bypass.*/
+ CRM->BPDC |= CRM_BPDC_LEXTEN;
+#endif
+ while ((CRM->BPDC & CRM_BPDC_LEXTSTBL) == 0); /* Waits until LEXT is stable. */
+#endif /* AT32_LEXT_ENABLED */
+
+#if AT32_ERTCSEL != AT32_ERTCSEL_NOCLOCK
+ /* If the backup domain hasn't been initialized yet then proceed with
+ initialization.*/
+ if ((CRM->BPDC & CRM_BPDC_ERTCEN) == 0) {
+ /* Selects clock source.*/
+ CRM->BPDC |= AT32_ERTCSEL;
+
+ /* ERTC clock enabled.*/
+ CRM->BPDC |= CRM_BPDC_ERTCEN;
+ }
+#endif /* AT32_ERTCSEL != AT32_ERTCSEL_NOCLOCK */
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level HAL driver initialization.
+ *
+ * @notapi
+ */
+void hal_lld_init(void) {
+
+ /* Reset of all peripherals. AHB3 is not reseted because it could have
+ been initialized in the board initialization file (board.c).
+ Note, GPIOs are not reset because initialized before this point in
+ board files.*/
+ crmResetAHB1(~AT32_GPIO_EN_MASK);
+ crmResetAHB2(~0);
+ crmResetAPB1(~CRM_APB1RST_PWCRST);
+ crmResetAPB2(~0);
+
+ /* Initializes the backup domain.*/
+ hal_lld_backup_domain_init();
+
+ /* DMA subsystems initialization.*/
+#if defined(AT32_DMA_REQUIRED)
+ dmaInit();
+#endif
+
+ /* IRQ subsystem initialization.*/
+ irqInit();
+
+ /* Programmable voltage detector enable.*/
+#if AT32_PVM_ENABLE
+ PWC->CTRL |= PWC_CTRL_PVMEN | (AT32_PVM & AT32_PVMSEL_MASK);
+#endif /* AT32_PVM_ENABLE */
+}
+
+/*
+ * hick divider selection for all sub-families.
+ */
+static void at32_hick_divider_select(uint32_t div)
+{
+ volatile uint32_t misc1 = CRM->MISC1;
+ volatile uint32_t misc2 = CRM->MISC2;
+
+ CRM->MISC2 &= ~AT32_HICK_TO_SCLK_DIV_MASK;
+ CRM->MISC2 |= AT32_HICK_TO_SCLK_DIV_DIV16;
+ /* delay */
+ {
+ __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
+ __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
+ __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
+ __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
+ }
+
+ CRM->MISC1 = (AT32_HICK_TO_SCLK_HICKOUT | div);
+ CRM->MISC1 &= ~AT32_HICK_TO_SCLK_MASK;
+ CRM->MISC1 |= (misc1 & AT32_HICK_TO_SCLK_MASK);
+
+ CRM->MISC2 &= ~AT32_HICK_TO_SCLK_DIV_MASK;
+ CRM->MISC2 |= (misc2 & AT32_HICK_TO_SCLK_DIV_MASK);
+}
+
+/*
+ * hick as system clock frequency selection for all sub-families.
+ */
+static void at32_hick_frequency_select(uint32_t value)
+{
+ volatile uint32_t misc1 = CRM->MISC1;
+ volatile uint32_t misc2 = CRM->MISC2;
+
+ CRM->MISC2 &= ~AT32_HICK_TO_SCLK_DIV_MASK;
+ CRM->MISC2 |= AT32_HICK_TO_SCLK_DIV_DIV16;
+ /* delay */
+ {
+ __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
+ __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
+ __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
+ __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
+ }
+
+ CRM->MISC1 = (AT32_HICK_TO_SCLK_HICKOUT | (misc1 & AT32_HICKDIV_MASK));
+ CRM->MISC1 &= ~AT32_HICK_TO_SCLK_MASK;
+ CRM->MISC1 |= value;
+
+ CRM->MISC2 &= ~AT32_HICK_TO_SCLK_DIV_MASK;
+ CRM->MISC2 |= (misc2 & AT32_HICK_TO_SCLK_DIV_MASK);
+}
+
+/*
+ * Clocks deinitialization for all sub-families.
+ */
+void at32_clock_reset(void)
+{
+ /* reset cfg register, include sclk switch, ahbdiv, apb1div, apb2div, adcdiv, clkout bits */
+ CRM->CFG = (0x40000000U);
+
+ /* reset hexten, hextbyps, cfden and pllen bits */
+ CRM->CTRL &= ~(0x010D0000U);
+
+ /* reset pllms pllns pllfr pllrcs bits */
+ CRM->PLLCFG = 0x000007C1U;
+
+ /* reset clkout_sel, clkoutdiv, pllclk_to_adc, hick_to_usb */
+ CRM->MISC1 &= 0x00005000U;
+ CRM->MISC1 |= 0x000F0000U;
+
+ /* disable all interrupts enable and clear pending bits */
+ CRM->CLKINT = 0x009F0000;
+}
+
+/*
+ * Clocks initialization for all sub-families.
+ */
+void at32_clock_init(void) {
+#if !AT32_NO_INIT
+ /* HICK setup, it enforces the reset situation in order to handle possible
+ problems with JTAG probes and re-initializations.*/
+
+ /* clock reset. */
+ at32_clock_reset();
+
+ CRM->MISC2 |= CRM_MISC2_AUTO_STEP_EN;
+
+ CRM->CTRL |= CRM_CTRL_HICKEN; /* Make sure HICK is ON. */
+ while((CRM->CTRL & CRM_CTRL_HICKSTBL) == 0); /* Wait until HICK is stable. */
+
+ CRM->CTRL &= CRM_CTRL_HICKTRIM | CRM_CTRL_HICKEN; /* CTRL Reset value. */
+
+ at32_hick_divider_select(AT32_HICKDIV);
+ at32_hick_frequency_select(AT32_HICK_TO_SCLK);
+ CRM->MISC2 |= AT32_HICK_TO_SCLK_DIV;
+ CRM->CFG |= CRM_CFG_SCLK_HICK; /* CFG reset value. */
+ while ((CRM->CFG & CRM_CFG_SCLKSTS) != CRM_CFG_SCLKSTS_HICK); /* Waits until HICK is selected.*/
+
+ CRM->MISC2 &= ~CRM_MISC2_AUTO_STEP_EN;
+
+ /* Flash setup and final clock selection.*/
+ FLASH->PSR = AT32_FLASHBITS;
+ CRM->APB1EN |= CRM_APB1EN_PWCEN;
+
+ /* PWR initialization.*/
+ PWC->LDOOV = AT32_LDOOVSEL;
+
+#if AT32_HEXT_ENABLED
+ /* HEXT activation.*/
+#if defined(AT32_HEXT_BYPASS)
+ /* HEXT Bypass.*/
+ CRM->CTRL |= CRM_CTRL_HEXTEN | CRM_CTRL_HEXTBYPS;
+#else
+ /* No HEXT Bypass.*/
+ CRM->CTRL |= CRM_CTRL_HEXTEN;
+#endif
+ while (!(CRM->CTRL & CRM_CTRL_HEXTSTBL)); /* Waits until HEXT is stable. */
+#endif
+
+#if AT32_LICK_ENABLED
+ /* LICK activation.*/
+ CRM->CTRLSTS |= CRM_CTRLSTS_LICKEN;
+ while ((CRM->CTRLSTS & CRM_CTRLSTS_LICKSTBL) == 0); /* Waits until LICK is stable. */
+#endif
+
+#if AT32_ACTIVATE_PLL
+ /* PLL activation.*/
+#if AT32_PLLRCS == AT32_PLLRCS_HICK
+ at32_hick_divider_select(AT32_HICKDIV_DIV1);
+#endif
+ CRM->PLLCFG = AT32_PLL_MS | AT32_PLL_NS | AT32_PLL_FP | AT32_PLL_FU |
+ AT32_PLLRCS;
+ CRM->CTRL |= CRM_CTRL_PLLEN;
+ while (!(CRM->CTRL & CRM_CTRL_PLLSTBL)); /* Waits until PLL is stable. */
+#if AT32_PLLU_ENABLED
+ CRM->PLLCFG |= CRM_PLLCFG_PLLUEN;
+ while (!(CRM->CTRL & CRM_CTRL_PLLUSTBL)); /* Waits until PLLU is stable. */
+#endif
+#endif
+
+ /* Clock settings.*/
+ CRM->CFG |= (AT32_CLKOUT_SEL & AT32_CLKOUT_SEL_CFG_MASK) | AT32_APB2DIV |
+ AT32_APB1DIV | AT32_AHBDIV | AT32_ETRCDIV | AT32_I2SF5CLKSEL |
+ AT32_CLKOUTDIV1;
+ CRM->MISC1 |= (AT32_CLKOUT_SEL & AT32_CLKOUT_SEL_MISC1_MASK) | AT32_CLKOUTDIV2;
+
+ /* PLL Auto Step activation.*/
+ CRM->MISC2 |= CRM_MISC2_AUTO_STEP_EN;
+
+ /* Switching to the configured clock source if it is different from HICK.*/
+#if AT32_SCLKSEL != AT32_SCLKSEL_HICK
+#if AT32_SCLKSEL == AT32_SCLKSEL_HEXT
+ CRM->MISC2 |= AT32_HEXT_TO_SCLK_DIV;
+#endif
+ /* Switches clock source.*/
+ CRM->CFG |= AT32_SCLKSEL;
+ while ((CRM->CFG & CRM_CFG_SCLKSTS) != (AT32_SCLKSEL << 2)); /* Waits selection complete. */
+#endif
+
+ /* PLL Auto Step inactivation.*/
+ CRM->MISC2 &= ~CRM_MISC2_AUTO_STEP_EN;
+
+#if !AT32_HICK_ENABLED
+ CRM->CTRL &= ~CRM_CTRL_HICKEN;
+#endif
+
+#if AT32_PLLU_USB48_SEL == AT32_PLLU_USB48_SEL_HICK
+ at32_hick_divider_select(AT32_HICKDIV_DIV1);
+ at32_hick_frequency_select(AT32_HICK_TO_SCLK_HICKOUT);
+#endif
+ CRM->MISC2 &= ~AT32_PLLU_USB48_SEL_MASK;
+ CRM->MISC2 |= AT32_PLLU_USB48_SEL;
+
+#if AT32_SYSTICK_CLKSRC == AT32_SYSTICK_CLKSRC_HCLKDIV1
+ SysTick->CTRL |= AT32_SYSTICK_CLKSRC_HCLKDIV1;
+#else
+ SysTick->CTRL &= ~AT32_SYSTICK_CLKSRC_HCLKDIV1;
+#endif
+
+#endif /* !AT32_NO_INIT */
+
+ /* SYSCFG clock enabled here because it is a multi-functional unit shared
+ among multiple drivers.*/
+ CRM->APB2EN |= CRM_APB2EN_SCFGEN;
+ CRM->APB2LPEN |= CRM_APB2LPEN_SCFGLPEN;
+}
+
+/** @} */
diff --git a/os/hal/ports/AT32/AT32F405xx/hal_lld.h b/os/hal/ports/AT32/AT32F405xx/hal_lld.h
new file mode 100644
index 0000000000..de7eebd51c
--- /dev/null
+++ b/os/hal/ports/AT32/AT32F405xx/hal_lld.h
@@ -0,0 +1,1203 @@
+/*
+ ChibiOS - Copyright (C) 2023..2024 Zhaqian
+ ChibiOS - Copyright (C) 2024 Maxjta
+
+ Licensed 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.
+*/
+
+/**
+ * @file AT32F405xx/hal_lld.h
+ * @brief AT32F405xx HAL subsystem low level driver header.
+ * @pre This module requires the following macros to be defined in the
+ * @p board.h file:
+ * - AT32_LEXTCLK.
+ * - AT32_LEXT_BYPASS (optionally).
+ * - AT32_HEXTCLK.
+ * - AT32_HEXT_BYPASS (optionally).
+ * .
+ *
+ * @addtogroup HAL
+ * @{
+ */
+
+#ifndef HAL_LLD_H
+#define HAL_LLD_H
+
+#include "at32_registry.h"
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @brief Requires use of SPIv2 driver model.
+ */
+#define HAL_LLD_SELECT_SPI_V2 TRUE
+
+/**
+ * @name Platform identification
+ * @{
+ */
+#define PLATFORM_NAME "AT32F405xx"
+
+/**
+ * @brief Sub-family identifier.
+ */
+#if !defined(AT32F405xx) || defined(__DOXYGEN__)
+#define AT32F405xx
+#endif
+/** @} */
+
+/**
+ * @name Absolute Maximum Ratings
+ * @{
+ */
+/**
+ * @brief Maximum system clock frequency.
+ */
+#define AT32_SYSCLK_MAX 216000000
+
+/**
+ * @brief Maximum HEXT clock frequency.
+ */
+#define AT32_HEXTCLK_MAX 25000000
+
+/**
+ * @brief Maximum HEXT clock frequency using an external source.
+ */
+#define AT32_HEXTCLK_BYP_MAX 25000000
+
+/**
+ * @brief Minimum HEXT clock frequency.
+ */
+#define AT32_HEXTCLK_MIN 4000000
+
+/**
+ * @brief Minimum HEXT clock frequency.
+ */
+#define AT32_HEXTCLK_BYP_MIN 4000000
+
+/**
+ * @brief Maximum LSE clock frequency.
+ */
+#define AT32_LEXTCLK_MAX 32768
+
+/**
+ * @brief Maximum LSE clock frequency.
+ */
+#define AT32_LEXTCLK_BYP_MAX 1000000
+
+/**
+ * @brief Minimum LEXT clock frequency.
+ */
+#define AT32_LEXTCLK_MIN 32768
+
+/**
+ * @brief Maximum PLLs input clock frequency.
+ */
+#define AT32_PLLIN_MAX 16000000
+
+/**
+ * @brief Minimum PLLs input clock frequency.
+ */
+#define AT32_PLLIN_MIN 2000000
+
+/**
+ * @brief Maximum PLLs VCO clock frequency.
+ */
+#define AT32_PLLVCO_MAX 1000000000
+
+/**
+ * @brief Minimum PLLs VCO clock frequency.
+ */
+#define AT32_PLLVCO_MIN 500000000
+
+/**
+ * @brief Maximum PLL output clock frequency.
+ */
+#define AT32_PLLOUT_MAX 216000000
+
+/**
+ * @brief Minimum PLL output clock frequency.
+ */
+#define AT32_PLLOUT_MIN 4000000
+
+/**
+ * @brief Maximum APB1 clock frequency.
+ */
+#define AT32_PCLK1_MAX 120000000
+
+/**
+ * @brief Maximum APB2 clock frequency.
+ */
+#define AT32_PCLK2_MAX 216000000
+
+/**
+ * @brief Maximum ADC clock frequency.
+ */
+#define AT32_ADCCLK_MAX 28000000
+/** @} */
+
+/**
+ * @name Internal clock sources
+ * @{
+ */
+#define AT32_HICKCLK 48000000 /**< High speed internal clock. */
+#define AT32_LICKCLK 40000 /**< Low speed internal clock. */
+/** @} */
+
+/**
+ * @name PWC_CTRL register bits definitions
+ * @{
+ */
+#define AT32_PVMSEL_MASK (7 << 5) /**< PVMSEL bits mask. */
+#define AT32_PVMSEL_LEV0 (0 << 5) /**< PVM level 0. */
+#define AT32_PVMSEL_LEV1 (1 << 5) /**< PVM level 1. */
+#define AT32_PVMSEL_LEV2 (2 << 5) /**< PVM level 2. */
+#define AT32_PVMSEL_LEV3 (3 << 5) /**< PVM level 3. */
+#define AT32_PVMSEL_LEV4 (4 << 5) /**< PVM level 4. */
+#define AT32_PVMSEL_LEV5 (5 << 5) /**< PVM level 5. */
+#define AT32_PVMSEL_LEV6 (6 << 5) /**< PVM level 6. */
+#define AT32_PVMSEL_LEV7 (7 << 5) /**< PVM level 7. */
+/** @} */
+
+/**
+ * @name PWC_LDOOV register bits definitions
+ * @{
+ */
+#define AT32_LDOOVSEL_MASK (3 << 0) /**< LDOOVSEL bits mask. */
+#define AT32_LDOOVSEL_1P0V (0 << 0) /**< LDOOVSEL 1.0V. */
+#define AT32_LDOOVSEL_1P1V (1 << 0) /**< LDOOVSEL 1.1V. */
+#define AT32_LDOOVSEL_1P2V (2 << 0) /**< LDOOVSEL 1.2V. */
+#define AT32_LDOOVSEL_1P3V (3 << 0) /**< LDOOVSEL 1.3V. */
+/** @} */
+
+/**
+ * @name CRM_PLLCFG register bits definitions
+ * @{
+ */
+#define AT32_PLL_FP_MASK (15 << 16) /**< PLL_FP mask. */
+#define AT32_PLL_FP_DIV1 (0 << 16) /**< PLL clock divided by 1. */
+#define AT32_PLL_FP_DIV2 (1 << 16) /**< PLL clock divided by 2. */
+#define AT32_PLL_FP_DIV4 (2 << 16) /**< PLL clock divided by 4. */
+#define AT32_PLL_FP_DIV6 (3 << 16) /**< PLL clock divided by 6. */
+#define AT32_PLL_FP_DIV8 (4 << 16) /**< PLL clock divided by 8. */
+#define AT32_PLL_FP_DIV10 (5 << 16) /**< PLL clock divided by 10. */
+#define AT32_PLL_FP_DIV12 (6 << 16) /**< PLL clock divided by 12. */
+#define AT32_PLL_FP_DIV14 (7 << 16) /**< PLL clock divided by 14. */
+#define AT32_PLL_FP_DIV16 (8 << 16) /**< PLL clock divided by 16. */
+#define AT32_PLL_FP_DIV18 (9 << 16) /**< PLL clock divided by 18. */
+#define AT32_PLL_FP_DIV20 (10 << 16) /**< PLL clock divided by 20. */
+#define AT32_PLL_FP_DIV22 (11 << 16) /**< PLL clock divided by 22. */
+#define AT32_PLL_FP_DIV24 (12 << 16) /**< PLL clock divided by 24. */
+#define AT32_PLL_FP_DIV26 (13 << 16) /**< PLL clock divided by 26. */
+#define AT32_PLL_FP_DIV28 (14 << 16) /**< PLL clock divided by 28. */
+#define AT32_PLL_FP_DIV30 (15 << 16) /**< PLL clock divided by 30. */
+
+#define AT32_PLL_FU_MASK (7 << 20) /**< PLL_FU mask. */
+#define AT32_PLL_FU_DIV11 (0 << 20) /**< PLLU clock divided by 11. */
+#define AT32_PLL_FU_DIV13 (1 << 20) /**< PLLU clock divided by 13. */
+#define AT32_PLL_FU_DIV12 (2 << 20) /**< PLLU clock divided by 12. */
+#define AT32_PLL_FU_DIV14 (3 << 20) /**< PLLU clock divided by 14. */
+#define AT32_PLL_FU_DIV16 (4 << 20) /**< PLLU clock divided by 16. */
+#define AT32_PLL_FU_DIV18 (5 << 20) /**< PLLU clock divided by 18. */
+#define AT32_PLL_FU_DIV20 (6 << 20) /**< PLLU clock divided by 20. */
+
+#define AT32_PLLRCS_HICK (0 << 30) /**< PLL clock source is HICK. */
+#define AT32_PLLRCS_HEXT (1 << 30) /**< PLL clock source is HEXT. */
+/** @} */
+
+/**
+ * @name CRM_CFG register bits definitions
+ * @{
+ */
+#define AT32_SCLKSEL_MASK (3 << 0) /**< SCLKSEL mask. */
+#define AT32_SCLKSEL_HICK (0 << 0) /**< SYSCLK source is HICK. */
+#define AT32_SCLKSEL_HEXT (1 << 0) /**< SYSCLK source is HEXT. */
+#define AT32_SCLKSEL_PLL (2 << 0) /**< SYSCLK source is PLL. */
+
+#define AT32_SCLKSTS_MASK (3 << 2) /**< SCLKSTS mask. */
+#define AT32_SCLKSTS_HICK (0 << 2) /**< SYSCLK use HICK. */
+#define AT32_SCLKSTS_HEXT (1 << 2) /**< SYSCLK use HEXT. */
+#define AT32_SCLKSTS_PLL (2 << 2) /**< SYSCLK use PLL. */
+
+#define AT32_AHBDIV_MASK (15 << 4) /**< AHBDIV mask. */
+#define AT32_AHBDIV_DIV1 (0 << 4) /**< SYSCLK divided by 1. */
+#define AT32_AHBDIV_DIV2 (8 << 4) /**< SYSCLK divided by 2. */
+#define AT32_AHBDIV_DIV4 (9 << 4) /**< SYSCLK divided by 4. */
+#define AT32_AHBDIV_DIV8 (10 << 4) /**< SYSCLK divided by 8. */
+#define AT32_AHBDIV_DIV16 (11 << 4) /**< SYSCLK divided by 16. */
+#define AT32_AHBDIV_DIV64 (12 << 4) /**< SYSCLK divided by 64. */
+#define AT32_AHBDIV_DIV128 (13 << 4) /**< SYSCLK divided by 128. */
+#define AT32_AHBDIV_DIV256 (14 << 4) /**< SYSCLK divided by 256. */
+#define AT32_AHBDIV_DIV512 (15 << 4) /**< SYSCLK divided by 512. */
+
+#define AT32_APB1DIV_MASK (7 << 10) /**< APB1DIV mask. */
+#define AT32_APB1DIV_DIV1 (0 << 10) /**< HCLK divided by 1. */
+#define AT32_APB1DIV_DIV2 (4 << 10) /**< HCLK divided by 2. */
+#define AT32_APB1DIV_DIV4 (5 << 10) /**< HCLK divided by 4. */
+#define AT32_APB1DIV_DIV8 (6 << 10) /**< HCLK divided by 8. */
+#define AT32_APB1DIV_DIV16 (7 << 10) /**< HCLK divided by 16. */
+
+#define AT32_APB2DIV_MASK (7 << 13) /**< APB2DIV mask. */
+#define AT32_APB2DIV_DIV1 (0 << 13) /**< HCLK divided by 1. */
+#define AT32_APB2DIV_DIV2 (4 << 13) /**< HCLK divided by 2. */
+#define AT32_APB2DIV_DIV4 (5 << 13) /**< HCLK divided by 4. */
+#define AT32_APB2DIV_DIV8 (6 << 13) /**< HCLK divided by 8. */
+#define AT32_APB2DIV_DIV16 (7 << 13) /**< HCLK divided by 16. */
+
+#define AT32_ERTCDIV_MASK (31 << 16) /**< ERTCDIV mask. */
+
+#define AT32_I2SF5CLKSEL_MASK (3 << 22) /**< I2SF5CLKSEL mask. */
+#define AT32_I2SF5CLKSEL_SCLK (0 << 22) /**< I2SF5CLKSEL is SYSCLK. */
+#define AT32_I2SF5CLKSEL_PLL (1 << 22) /**< I2SF5CLKSEL is PLL. */
+#define AT32_I2SF5CLKSEL_HICK (2 << 22) /**< I2SF5CLKSEL is HICK. */
+#define AT32_I2SF5CLKSEL_EXCLK (3 << 22) /**< I2SF5CLKSEL is EXCLK. */
+
+#define AT32_CLKOUTDIV1_MASK (7 << 27) /**< CLKOUTDIV1 mask. */
+#define AT32_CLKOUTDIV1_DIV1 (0 << 27) /**< CLKOUT divided by 1. */
+#define AT32_CLKOUTDIV1_DIV2 (4 << 27) /**< CLKOUT divided by 2. */
+#define AT32_CLKOUTDIV1_DIV3 (5 << 27) /**< CLKOUT divided by 3. */
+#define AT32_CLKOUTDIV1_DIV4 (6 << 27) /**< CLKOUT divided by 4. */
+#define AT32_CLKOUTDIV1_DIV5 (7 << 27) /**< CLKOUT divided by 5. */
+
+#define AT32_CLKOUT_SEL_CFG_MASK (3 << 30) /**< CLKOUT_SEL CFG mask. */
+#define AT32_CLKOUT_SEL_MISC1_MASK (15 << 16) /**< CLKOUT_SEL MISC1 mask. */
+#define AT32_CLKOUT_SEL_SCLK (0 << 30) /**< CLKOUT_SEL SYSCLK. */
+#define AT32_CLKOUT_SEL_HEXT (2 << 30) /**< CLKOUT_SEL HEXT. */
+#define AT32_CLKOUT_SEL_PLL (3 << 30) /**< CLKOUT_SEL PLL. */
+#define AT32_CLKOUT_SEL_USBFS ((1 << 30) | \
+ (0 << 16)) /**< CLKOUT_SEL USBFS. */
+#define AT32_CLKOUT_SEL_ADC ((1 << 30) | \
+ (1 << 16)) /**< CLKOUT_SEL ADC. */
+#define AT32_CLKOUT_SEL_HICK ((1 << 30) | \
+ (2 << 16)) /**< CLKOUT_SEL HICK. */
+#define AT32_CLKOUT_SEL_LICK ((1 << 30) | \
+ (3 << 16)) /**< CLKOUT_SEL LICK. */
+#define AT32_CLKOUT_SEL_LEXT ((1 << 30) | \
+ (4 << 16)) /**< CLKOUT_SEL LEXT. */
+#define AT32_CLKOUT_SEL_USBHS ((1 << 30) | \
+ (5 << 16)) /**< CLKOUT_SEL USBHS. */
+/** @} */
+
+/**
+ * @name CRM_BPDC register bits definitions
+ * @{
+ */
+#define AT32_ERTCSEL_MASK (3 << 8) /**< RTC clock source mask. */
+#define AT32_ERTCSEL_NOCLOCK (0 << 8) /**< No clock. */
+#define AT32_ERTCSEL_LEXT (1 << 8) /**< LEXT used as RTC clock. */
+#define AT32_ERTCSEL_LICK (2 << 8) /**< LICK used as RTC clock. */
+#define AT32_ERTCSEL_HEXTDIV (3 << 8) /**< HEXT divided used as
+ RTC clock. */
+/** @} */
+
+/**
+ * @name CRM_MISC1 register bits definitions
+ * @{
+ */
+#define AT32_HICKDIV_MASK (1 << 12) /**< HICKDIV mask. */
+#define AT32_HICKDIV_DIV6 (0 << 12) /**< HICK divided by 6. */
+#define AT32_HICKDIV_DIV1 (1 << 12) /**< HICK divided by 1. */
+
+#define AT32_HICK_TO_SCLK_MASK (1 << 14) /**< HICK_TO_SCLK mask. */
+#define AT32_HICK_TO_SCLK_8M (0 << 14) /**< SCLK is 8MHz if SCLK
+ is HICK. */
+#define AT32_HICK_TO_SCLK_HICKOUT (1 << 14) /**< SCLK is HICKOUT if SCLK
+ is HICK. */
+
+#define AT32_CLKOUTDIV2_MASK (15 << 28) /**< CLKOUTDIV2 mask. */
+#define AT32_CLKOUTDIV2_DIV1 (0 << 28) /**< CLKOUT divided by 1. */
+#define AT32_CLKOUTDIV2_DIV2 (8 << 28) /**< CLKOUT divided by 2. */
+#define AT32_CLKOUTDIV2_DIV4 (9 << 28) /**< CLKOUT divided by 4. */
+#define AT32_CLKOUTDIV2_DIV8 (10 << 28) /**< CLKOUT divided by 8. */
+#define AT32_CLKOUTDIV2_DIV16 (11 << 28) /**< CLKOUT divided by 16. */
+#define AT32_CLKOUTDIV2_DIV64 (12 << 28) /**< CLKOUT divided by 64. */
+#define AT32_CLKOUTDIV2_DIV128 (13 << 28) /**< CLKOUT divided by 128. */
+#define AT32_CLKOUTDIV2_DIV256 (14 << 28) /**< CLKOUT divided by 256. */
+#define AT32_CLKOUTDIV2_DIV512 (15 << 28) /**< CLKOUT divided by 512. */
+/** @} */
+
+/**
+ * @name CRM_MISC2 register bits definitions
+ * @{
+ */
+#define AT32_PLLU_USB48_SEL_MASK (1 << 10) /**< PLLU_USB48_SEL mask. */
+#define AT32_PLLU_USB48_SEL_PLLU (0 << 10) /**< PLLU_USB48_SEL PLLU. */
+#define AT32_PLLU_USB48_SEL_HICK (1 << 10) /**< PLLU_USB48_SEL HICK. */
+
+#define AT32_HICK_TO_SCLK_DIV_MASK (7 << 16) /**< HICK_TO_SCLK_DIV mask. */
+#define AT32_HICK_TO_SCLK_DIV_DIV1 (0 << 16) /**< HICK divided by 1. */
+#define AT32_HICK_TO_SCLK_DIV_DIV2 (1 << 16) /**< HICK divided by 2. */
+#define AT32_HICK_TO_SCLK_DIV_DIV4 (2 << 16) /**< HICK divided by 4. */
+#define AT32_HICK_TO_SCLK_DIV_DIV8 (3 << 16) /**< HICK divided by 8. */
+#define AT32_HICK_TO_SCLK_DIV_DIV16 (4 << 16) /**< HICK divided by 16. */
+
+#define AT32_HEXT_TO_SCLK_DIV_MASK (7 << 19) /**< HEXT_TO_SCLK_DIV mask. */
+#define AT32_HEXT_TO_SCLK_DIV_DIV1 (0 << 19) /**< HEXT divided by 1. */
+#define AT32_HEXT_TO_SCLK_DIV_DIV2 (1 << 19) /**< HEXT divided by 2. */
+#define AT32_HEXT_TO_SCLK_DIV_DIV4 (2 << 19) /**< HEXT divided by 4. */
+#define AT32_HEXT_TO_SCLK_DIV_DIV8 (3 << 19) /**< HEXT divided by 8. */
+#define AT32_HEXT_TO_SCLK_DIV_DIV16 (4 << 19) /**< HEXT divided by 16. */
+#define AT32_HEXT_TO_SCLK_DIV_DIV32 (5 << 19) /**< HEXT divided by 32. */
+/** @} */
+
+/**
+ * @name SYSTICK_CTRL register bits definitions
+ * @{
+ */
+#define AT32_SYSTICK_CLKSRC_HCLKDIV8 (0 << 0) /**< Systick clk is hclk/8 */
+#define AT32_SYSTICK_CLKSRC_HCLKDIV1 (4 << 0) /**< Systick clk is hclk. */
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief Disables the PWR/CRM initialization in the HAL.
+ */
+#if !defined(AT32_NO_INIT) || defined(__DOXYGEN__)
+#define AT32_NO_INIT FALSE
+#endif
+
+/**
+ * @brief Enables or disables the programmable voltage detector.
+ */
+#if !defined(AT32_PVM_ENABLE) || defined(__DOXYGEN__)
+#define AT32_PVM_ENABLE FALSE
+#endif
+
+/**
+ * @brief Sets voltage level for programmable voltage detector.
+ */
+#if !defined(AT32_PVM) || defined(__DOXYGEN__)
+#define AT32_PVM AT32_PVMSEL_LEV0
+#endif
+
+/**
+ * @brief Enables or disables the HICK clock source.
+ */
+#if !defined(AT32_HICK_ENABLED) || defined(__DOXYGEN__)
+#define AT32_HICK_ENABLED TRUE
+#endif
+
+/**
+ * @brief Enables or disables the LICK clock source.
+ */
+#if !defined(AT32_LICK_ENABLED) || defined(__DOXYGEN__)
+#define AT32_LICK_ENABLED FALSE
+#endif
+
+/**
+ * @brief Enables or disables the HEXT clock source.
+ */
+#if !defined(AT32_HEXT_ENABLED) || defined(__DOXYGEN__)
+#define AT32_HEXT_ENABLED TRUE
+#endif
+
+/**
+ * @brief Enables or disables the LEXT clock source.
+ */
+#if !defined(AT32_LEXT_ENABLED) || defined(__DOXYGEN__)
+#define AT32_LEXT_ENABLED FALSE
+#endif
+
+/**
+ * @brief Enables or disables the PLLU clock source.
+ */
+#if !defined(AT32_PLLU_ENABLED) || defined(__DOXYGEN__)
+#define AT32_PLLU_ENABLED TRUE
+#endif
+
+/**
+ * @brief USB clock setting.
+ */
+#if !defined(AT32_CLOCK48_REQUIRED) || defined(__DOXYGEN__)
+#define AT32_CLOCK48_REQUIRED TRUE
+#endif
+
+/**
+ * @brief USB clock source selection.
+ */
+#if !defined(AT32_PLLU_USB48_SEL) || defined(__DOXYGEN__)
+#define AT32_PLLU_USB48_SEL AT32_PLLU_USB48_SEL_PLLU
+#endif
+
+/**
+ * @brief Main clock source selection.
+ * @note If the selected clock source is not the PLL then the PLL is not
+ * initialized and started.
+ * @note The default value is calculated for a 216MHz system clock from
+ * a 12MHz crystal using the PLL.
+ */
+#if !defined(AT32_SCLKSEL) || defined(__DOXYGEN__)
+#define AT32_SCLKSEL AT32_SCLKSEL_PLL
+#endif
+
+/**
+ * @brief Clock source for the PLL.
+ * @note This setting has only effect if the PLL is selected as the
+ * system clock source.
+ * @note The default value is calculated for a 216MHz system clock from
+ * a 12MHz crystal using the PLL.
+ */
+#if !defined(AT32_PLLRCS) || defined(__DOXYGEN__)
+#define AT32_PLLRCS AT32_PLLRCS_HEXT
+#endif
+
+/**
+ * @brief PLL_MS divider value.
+ * @note The allowed values are 1..15.
+ * @note The default value is calculated for a 216MHz system clock from
+ * a 12MHz crystal using the PLL.
+ */
+#if !defined(AT32_PLL_MS_VALUE) || defined(__DOXYGEN__)
+#define AT32_PLL_MS_VALUE 1
+#endif
+
+/**
+ * @brief PLL_NS multiplier value.
+ * @note The allowed values are 31..500.
+ * @note The default value is calculated for a 216MHz system clock from
+ * a 12MHz crystal using the PLL.
+ */
+#if !defined(AT32_PLL_NS_VALUE) || defined(__DOXYGEN__)
+#define AT32_PLL_NS_VALUE 72
+#endif
+
+/**
+ * @brief PLL_FP divider value.
+ * @note The allowed values are 1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20,
+ * 22, 24, 26, 28, 30.
+ * @note The default value is calculated for a 216MHz system clock from
+ * a 12MHz crystal using the PLL.
+ */
+#if !defined(AT32_PLL_FP_VALUE) || defined(__DOXYGEN__)
+#define AT32_PLL_FP_VALUE 4
+#endif
+
+/**
+ * @brief PLL_FU divider value.
+ * @note The allowed values are 11, 12, 13, 14, 16, 18, 20.
+ * @note The default value is calculated for a 216MHz system clock from
+ * a 12MHz crystal using the PLL.
+ */
+#if !defined(AT32_PLL_FU_VALUE) || defined(__DOXYGEN__)
+#define AT32_PLL_FU_VALUE 18
+#endif
+
+/**
+ * @brief AHB prescaler value.
+ * @note The default value is calculated for a 216MHz system clock from
+ * a 12MHz crystal using the PLL.
+ */
+#if !defined(AT32_AHBDIV) || defined(__DOXYGEN__)
+#define AT32_AHBDIV AT32_AHBDIV_DIV1
+#endif
+
+/**
+ * @brief APB1 prescaler value.
+ */
+#if !defined(AT32_APB1DIV) || defined(__DOXYGEN__)
+#define AT32_APB1DIV AT32_APB1DIV_DIV2
+#endif
+
+/**
+ * @brief APB2 prescaler value.
+ */
+#if !defined(AT32_APB2DIV) || defined(__DOXYGEN__)
+#define AT32_APB2DIV AT32_APB2DIV_DIV1
+#endif
+
+/**
+ * @brief HICK source selection if SCLK is HICK.
+ */
+#if !defined(AT32_HICK_TO_SCLK) || defined(__DOXYGEN__)
+#define AT32_HICK_TO_SCLK AT32_HICK_TO_SCLK_HICKOUT
+#endif
+
+/**
+ * @brief HICK prescaler selection.
+ */
+#if !defined(AT32_HICKDIV) || defined(__DOXYGEN__)
+#define AT32_HICKDIV AT32_HICKDIV_DIV1
+#endif
+
+/**
+ * @brief HICK prescaler value when SCLK is HICK.
+ */
+#if !defined(AT32_HICK_TO_SCLK_DIV) || defined(__DOXYGEN__)
+#define AT32_HICK_TO_SCLK_DIV AT32_HICK_TO_SCLK_DIV_DIV1
+#endif
+
+/**
+ * @brief HEXT prescaler value when SCLK is HEXT.
+ */
+#if !defined(AT32_HEXT_TO_SCLK_DIV) || defined(__DOXYGEN__)
+#define AT32_HEXT_TO_SCLK_DIV AT32_HEXT_TO_SCLK_DIV_DIV1
+#endif
+
+/**
+ * @brief ERTC clock source.
+ */
+#if !defined(AT32_ERTCSEL) || defined(__DOXYGEN__)
+#define AT32_ERTCSEL AT32_ERTCSEL_NOCLOCK
+#endif
+
+/**
+ * @brief ERTC HEXT prescaler value.
+ * @note The allowed values are 2..31.
+ */
+#if !defined(AT32_ERTCDIV_VALUE) || defined(__DOXYGEN__)
+#define AT32_ERTCDIV_VALUE 12
+#endif
+
+/**
+ * @brief I2SF5 clock source.
+ */
+#if !defined(AT32_I2SF5CLKSEL) || defined(__DOXYGEN__)
+#define AT32_I2SF5CLKSEL AT32_I2SF5CLKSEL_SCLK
+#endif
+
+/**
+ * @brief CLKOUT pin setting.
+ */
+#if !defined(AT32_CLKOUT_SEL) || defined(__DOXYGEN__)
+#define AT32_CLKOUT_SEL AT32_CLKOUT_SEL_HICK
+#endif
+
+/**
+ * @brief CLKOUT prescaler value 1.
+ */
+#if !defined(AT32_CLKOUTDIV1) || defined(__DOXYGEN__)
+#define AT32_CLKOUTDIV1 AT32_CLKOUTDIV1_DIV1
+#endif
+
+/**
+ * @brief CLKOUT prescaler value 2.
+ */
+#if !defined(AT32_CLKOUTDIV2) || defined(__DOXYGEN__)
+#define AT32_CLKOUTDIV2 AT32_CLKOUTDIV2_DIV1
+#endif
+
+/**
+ * @brief LDOOVSEL setting.
+ */
+#if !defined(AT32_LDOOVSEL) || defined(__DOXYGEN__)
+#define AT32_LDOOVSEL AT32_LDOOVSEL_1P3V
+#endif
+
+/**
+ * @brief Systick clock source setting.
+ */
+#if !defined(AT32_SYSTICK_CLKSRC) || defined(__DOXYGEN__)
+#define AT32_SYSTICK_CLKSRC AT32_SYSTICK_CLKSRC_HCLKDIV1
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*
+ * Configuration-related checks.
+ */
+#if !defined(AT32F405xx_MCUCONF)
+#error "Using a wrong mcuconf.h file, AT32F405xx_MCUCONF not defined"
+#endif
+
+/*
+ * Board files sanity checks.
+ */
+#if !defined(AT32_LEXTCLK)
+#error "AT32_LEXTCLK not defined in board.h"
+#endif
+
+#if !defined(AT32_HEXTCLK)
+#error "AT32_HEXTCLK not defined in board.h"
+#endif
+
+/*
+ * HICK related checks.
+ */
+#if AT32_HICK_ENABLED
+#else /* !AT32_HICK_ENABLED */
+
+#if AT32_SCLKSEL == AT32_SCLKSEL_HICK
+#error "HICK not enabled, required by AT32_SCLKSEL"
+#endif
+
+#if ((AT32_SCLKSEL == AT32_SCLKSEL_HICK) && \
+ (AT32_PLLRCS == AT32_PLLRCS_HICK))
+#error "HICK not enabled, required by AT32_SCLKSEL and AT32_PLLRCS"
+#endif
+
+#if (AT32_CLKOUT_SEL == AT32_CLKOUT_SEL_HICK) || \
+ ((AT32_CLKOUT_SEL == AT32_CLKOUT_SEL_PLL) && \
+ (AT32_PLLRCS == AT32_PLLRCS_HICK))
+#error "HICK not enabled, required by AT32_CLKOUT_SEL"
+#endif
+
+#if (AT32_PLLU_USB48_SEL == AT32_PLLU_USB48_SEL_HICK) || \
+ ((AT32_PLLU_USB48_SEL == AT32_PLLU_USB48_SEL_PLLU) && \
+ (AT32_PLLRCS == AT32_PLLRCS_HICK))
+#error "HICK not enabled, required by AT32_PLLU_USB48_SEL"
+#endif
+
+#if (AT32_I2SF5CLKSEL == AT32_I2SF5CLKSEL_HICK) || \
+ ((AT32_I2SF5CLKSEL == AT32_I2SF5CLKSEL_PLL) && \
+ (AT32_PLLRCS == AT32_PLLRCS_HICK)) || \
+ ((AT32_I2SF5CLKSEL == AT32_I2SF5CLKSEL_SCLK) && \
+ (AT32_SCLKSEL == AT32_SCLKSEL_HICK)) || \
+ ((AT32_I2SF5CLKSEL == AT32_I2SF5CLKSEL_SCLK) && \
+ (AT32_SCLKSEL == AT32_SCLKSEL_PLL) && \
+ (AT32_PLLRCS == AT32_PLLRCS_HICK))
+#error "HICK not enabled, required by AT32_I2SF5CLKSEL"
+#endif
+
+#endif /* !AT32_HICK_ENABLED */
+
+/*
+ * HEXT related checks.
+ */
+#if AT32_HEXT_ENABLED
+
+#if AT32_HEXTCLK == 0
+#error "HEXT frequency not defined"
+#else /* AT32_HEXTCLK != 0 */
+#if defined(AT32_HEXT_BYPASS)
+#if (AT32_HEXTCLK < AT32_HEXTCLK_BYP_MIN) || (AT32_HEXTCLK > AT32_HEXTCLK_BYP_MAX)
+#error "AT32_HEXTCLK outside acceptable range (AT32_HEXTCLK_MIN...AT32_HEXTCLK_BYP_MAX)"
+#endif
+#else /* !defined(AT32_HEXT_BYPASS) */
+#if (AT32_HEXTCLK < AT32_HEXTCLK_MIN) || (AT32_HEXTCLK > AT32_HEXTCLK_MAX)
+#error "AT32_HEXTCLK outside acceptable range (AT32_HEXTCLK_MIN...AT32_HEXTCLK_MAX)"
+#endif
+#endif /* !defined(AT32_HEXT_BYPASS) */
+#endif /* AT32_HEXTCLK != 0 */
+
+#else /* !AT32_HEXT_ENABLED */
+
+#if AT32_SCLKSEL == AT32_SCLKSEL_HEXT
+#error "HEXT not enabled, required by AT32_SCLKSEL"
+#endif
+
+#if (AT32_SCLKSEL == AT32_SCLKSEL_PLL) && (AT32_PLLRCS == AT32_PLLRCS_HEXT)
+#error "HEXT not enabled, required by AT32_SCLKSEL and AT32_PLLRCS"
+#endif
+
+#if (AT32_CLKOUT_SEL == AT32_CLKOUT_SEL_HEXT) || \
+ ((AT32_CLKOUT_SEL == AT32_CLKOUT_SEL_PLL) && \
+ (AT32_PLLRCS == AT32_PLLRCS_HEXT))
+#error "HEXT not enabled, required by AT32_CLKOUT_SEL"
+#endif
+
+#if AT32_ERTCSEL == AT32_ERTCSEL_HEXTDIV
+#error "HEXT not enabled, required by AT32_ERTCSEL"
+#endif
+
+#if ((AT32_I2SF5CLKSEL == AT32_I2SF5CLKSEL_PLL) && \
+ (AT32_PLLRCS == AT32_PLLRCS_HEXT)) || \
+ ((AT32_I2SF5CLKSEL == AT32_I2SF5CLKSEL_SCLK) && \
+ (AT32_SCLKSEL == AT32_SCLKSEL_HEXT)) || \
+ ((AT32_I2SF5CLKSEL == AT32_I2SF5CLKSEL_SCLK) && \
+ (AT32_SCLKSEL == AT32_SCLKSEL_PLL) && \
+ (AT32_PLLRCS == AT32_PLLRCS_HEXT))
+#error "HICK not enabled, required by AT32_I2SF5CLKSEL"
+#endif
+
+#endif /* !AT32_HEXT_ENABLED */
+
+#if AT32_LICK_ENABLED
+#else /* !AT32_LICK_ENABLED */
+
+#if AT32_CLKOUT_SEL == AT32_CLKOUT_SEL_LICK
+#error "LICK not enabled, required by AT32_CLKOUT_SEL"
+#endif
+#if HAL_USE_RTC && (AT32_ERTCSEL == AT32_ERTCSEL_LICK)
+#error "LICK not enabled, required by AT32_ERTCSEL"
+#endif
+#endif /* !AT32_LICK_ENABLED */
+
+/* LEXT related checks.*/
+#if AT32_LEXT_ENABLED
+#if (AT32_LEXTCLK == 0)
+#error "impossible to activate LEXT, frequency is zero"
+#endif
+
+#if (AT32_LEXTCLK < AT32_LEXTCLK_MIN) || (AT32_LEXTCLK > AT32_LEXTCLK_MAX)
+#error "AT32_LEXTCLK outside acceptable range (AT32_LEXTCLK_MIN...AT32_LEXTCLK_MAX)"
+#endif
+
+#else /* !AT32_LEXT_ENABLED */
+
+#if AT32_CLKOUT_SEL == AT32_CLKOUT_SEL_LEXT
+#error "LEXT not enabled, required by AT32_CLKOUT_SEL"
+#endif
+#if AT32_ERTCSEL == AT32_ERTCSEL_LEXT
+#error "LEXT not enabled, required by AT32_ERTCSEL"
+#endif
+#endif /* !AT32_LEXT_ENABLED */
+
+#if AT32_PLLU_ENABLED
+#else /* !AT32_PLLU_ENABLED */
+
+#if AT32_PLLU_USB48_SEL == AT32_PLLU_USB48_SEL_PLLU
+#error "PLLU not enabled, required by AT32_PLLU_USB48_SEL"
+#endif
+#endif /* !AT32_PLLU_ENABLED */
+
+/**
+ * @brief AT32_PLL_MS field.
+ */
+#if ((AT32_PLL_MS_VALUE >= 1) && (AT32_PLL_MS_VALUE <= 15)) || \
+ defined(__DOXYGEN__)
+#define AT32_PLL_MS (AT32_PLL_MS_VALUE << 0)
+#else
+#error "invalid AT32_PLL_MS_VALUE value specified"
+#endif
+
+/**
+ * @brief HICK output clock frequency.
+ */
+#if (AT32_HICKDIV == AT32_HICKDIV_DIV1) || defined(__DOXYGEN__)
+#define AT32_HICKCLKOUT (AT32_HICKCLK / 1)
+#elif (AT32_HICKDIV == AT32_HICKDIV_DIV6)
+#define AT32_HICKCLKOUT (AT32_HICKCLK / 6)
+#else
+#error "invalid AT32_HICKDIV value specified"
+#endif
+
+/**
+ * @brief PLLs input clock frequency.
+ */
+#if (AT32_PLLRCS == AT32_PLLRCS_HEXT) || defined(__DOXYGEN__)
+#define AT32_PLLCLKIN (AT32_HEXTCLK / AT32_PLL_MS_VALUE)
+#elif AT32_PLLRCS == AT32_PLLRCS_HICK
+#define AT32_PLLCLKIN ((AT32_HICKCLK / 6) / AT32_PLL_MS_VALUE)
+#else
+#error "invalid AT32_PLLRCS value specified"
+#endif
+
+/*
+ * PLLs input frequency range check.
+ */
+#if (AT32_PLLCLKIN < AT32_PLLIN_MIN) || (AT32_PLLCLKIN > AT32_PLLIN_MAX)
+#error "AT32_PLLCLKIN outside acceptable range (AT32_PLLIN_MIN...AT32_PLLIN_MAX)"
+#endif
+
+/*
+ * PLL enable check.
+ */
+#if (AT32_CLOCK48_REQUIRED && (AT32_PLLU_USB48_SEL == AT32_PLLU_USB48_SEL_PLLU)) || \
+ (AT32_SCLKSEL == AT32_SCLKSEL_PLL) || \
+ (AT32_I2SF5CLKSEL == AT32_I2SF5CLKSEL_PLL) || \
+ (AT32_CLKOUT_SEL == AT32_CLKOUT_SEL_PLL) || \
+ (AT32_PLLU_ENABLED) || defined(__DOXYGEN__)
+/**
+ * @brief PLL activation flag.
+ */
+#define AT32_ACTIVATE_PLL TRUE
+#else
+#define AT32_ACTIVATE_PLL FALSE
+#endif
+
+/**
+ * @brief AT32_PLL_NS field.
+ */
+#if ((AT32_PLL_NS_VALUE >= 31) && (AT32_PLL_NS_VALUE <= 500)) || \
+ defined(__DOXYGEN__)
+#define AT32_PLL_NS (AT32_PLL_NS_VALUE << 6)
+#else
+#error "invalid AT32_PLL_NS_VALUE value specified"
+#endif
+
+/**
+ * @brief AT32_PLL_FP field.
+ */
+#if (AT32_PLL_FP_VALUE == 1) || defined(__DOXYGEN__)
+#define AT32_PLL_FP AT32_PLL_FP_DIV1
+#elif AT32_PLL_FP_VALUE == 2
+#define AT32_PLL_FP AT32_PLL_FP_DIV2
+#elif AT32_PLL_FP_VALUE == 4
+#define AT32_PLL_FP AT32_PLL_FP_DIV4
+#elif AT32_PLL_FP_VALUE == 6
+#define AT32_PLL_FP AT32_PLL_FP_DIV6
+#elif AT32_PLL_FP_VALUE == 8
+#define AT32_PLL_FP AT32_PLL_FP_DIV8
+#elif AT32_PLL_FP_VALUE == 10
+#define AT32_PLL_FP AT32_PLL_FP_DIV10
+#elif AT32_PLL_FP_VALUE == 12
+#define AT32_PLL_FP AT32_PLL_FP_DIV12
+#elif AT32_PLL_FP_VALUE == 14
+#define AT32_PLL_FP AT32_PLL_FP_DIV14
+#elif AT32_PLL_FP_VALUE == 16
+#define AT32_PLL_FP AT32_PLL_FP_DIV16
+#elif AT32_PLL_FP_VALUE == 18
+#define AT32_PLL_FP AT32_PLL_FP_DIV18
+#elif AT32_PLL_FP_VALUE == 20
+#define AT32_PLL_FP AT32_PLL_FP_DIV20
+#else
+#error "invalid AT32_PLL_FP_VALUE value specified"
+#endif
+
+/**
+ * @brief AT32_PLL_FU field.
+ */
+#if (AT32_PLL_FU_VALUE == 11) || defined(__DOXYGEN__)
+#define AT32_PLL_FU AT32_PLL_FU_DIV11
+#elif AT32_PLL_FU_VALUE == 12
+#define AT32_PLL_FU AT32_PLL_FU_DIV12
+#elif AT32_PLL_FU_VALUE == 13
+#define AT32_PLL_FU AT32_PLL_FU_DIV13
+#elif AT32_PLL_FU_VALUE == 14
+#define AT32_PLL_FU AT32_PLL_FU_DIV14
+#elif AT32_PLL_FU_VALUE == 16
+#define AT32_PLL_FU AT32_PLL_FU_DIV16
+#elif AT32_PLL_FU_VALUE == 18
+#define AT32_PLL_FU AT32_PLL_FU_DIV18
+#elif AT32_PLL_FU_VALUE == 20
+#define AT32_PLL_FU AT32_PLL_FU_DIV20
+#else
+#error "invalid AT32_PLL_FU_VALUE value specified"
+#endif
+
+/**
+ * @brief PLL VCO frequency.
+ */
+#define AT32_PLLVCO (AT32_PLLCLKIN * AT32_PLL_NS_VALUE)
+
+/*
+ * PLL VCO frequency range check.
+ */
+#if (AT32_PLLVCO < AT32_PLLVCO_MIN) || (AT32_PLLVCO > AT32_PLLVCO_MAX)
+#error "AT32_PLLVCO outside acceptable range (AT32_PLLVCO_MIN...AT32_PLLVCO_MAX)"
+#endif
+
+/**
+ * @brief PLL PCLK output clock frequency.
+ */
+#define AT32_PLLPCLK (AT32_PLLVCO / AT32_PLL_FP_VALUE)
+
+/*
+ * PLL PCLK frequency range check.
+ */
+#if (AT32_PLLPCLK < AT32_PLLOUT_MIN) || (AT32_PLLPCLK > AT32_PLLOUT_MAX)
+#error "AT32_PLLPCLK outside acceptable range (AT32_PLLOUT_MIN...AT32_PLLOUT_MAX)"
+#endif
+
+/**
+ * @brief PLL UCLK output clock frequency.
+ */
+#define AT32_PLLUCLK (AT32_PLLVCO / AT32_PLL_FU_VALUE)
+
+/*
+ * PLL UCLK frequency range check.
+ */
+#if (AT32_PLLUCLK < AT32_PLLOUT_MIN) || (AT32_PLLUCLK > AT32_PLLOUT_MAX)
+#error "AT32_PLLUCLK outside acceptable range (AT32_PLLOUT_MIN...AT32_PLLOUT_MAX)"
+#endif
+
+/**
+ * @brief System clock source.
+ */
+#if AT32_NO_INIT || (AT32_SCLKSEL == AT32_SCLKSEL_HICK) || \
+ defined(__DOXYGEN__)
+
+#if (AT32_HICK_TO_SCLK == AT32_HICK_TO_SCLK_8M) || defined(__DOXYGEN__)
+#define AT32_SYSCLKIN (8000000)
+#elif (AT32_HICK_TO_SCLK == AT32_HICK_TO_SCLK_HICKOUT)
+#define AT32_SYSCLKIN (AT32_HICKCLKOUT)
+#else
+#error "invalid AT32_HICK_TO_SCLK value specified"
+#endif
+
+#if (AT32_HICK_TO_SCLK_DIV == AT32_HICK_TO_SCLK_DIV_DIV1) || defined(__DOXYGEN__)
+#define AT32_SYSCLK (AT32_SYSCLKIN / 1)
+#elif (AT32_HICK_TO_SCLK_DIV == AT32_HICK_TO_SCLK_DIV_DIV2)
+#define AT32_SYSCLK (AT32_SYSCLKIN / 2)
+#elif (AT32_HICK_TO_SCLK_DIV == AT32_HICK_TO_SCLK_DIV_DIV4)
+#define AT32_SYSCLK (AT32_SYSCLKIN / 4)
+#elif (AT32_HICK_TO_SCLK_DIV == AT32_HICK_TO_SCLK_DIV_DIV8)
+#define AT32_SYSCLK (AT32_SYSCLKIN / 8)
+#elif (AT32_HICK_TO_SCLK_DIV == AT32_HICK_TO_SCLK_DIV_DIV16)
+#define AT32_SYSCLK (AT32_SYSCLKIN / 16)
+#else
+#error "invalid AT32_HICK_TO_SCLK_DIV value specified"
+#endif
+
+#elif AT32_SCLKSEL == AT32_SCLKSEL_HEXT
+
+#if (AT32_HEXT_TO_SCLK_DIV == AT32_HEXT_TO_SCLK_DIV_DIV1)
+#define AT32_SYSCLK (AT32_HEXTCLK / 1)
+#elif (AT32_HEXT_TO_SCLK_DIV == AT32_HEXT_TO_SCLK_DIV_DIV2)
+#define AT32_SYSCLK (AT32_HEXTCLK / 2)
+#elif (AT32_HEXT_TO_SCLK_DIV == AT32_HEXT_TO_SCLK_DIV_DIV4)
+#define AT32_SYSCLK (AT32_HEXTCLK / 4)
+#elif (AT32_HEXT_TO_SCLK_DIV == AT32_HEXT_TO_SCLK_DIV_DIV8)
+#define AT32_SYSCLK (AT32_HEXTCLK / 8)
+#elif (AT32_HEXT_TO_SCLK_DIV == AT32_HEXT_TO_SCLK_DIV_DIV16)
+#define AT32_SYSCLK (AT32_HEXTCLK / 16)
+#elif (AT32_HEXT_TO_SCLK_DIV == AT32_HEXT_TO_SCLK_DIV_DIV32)
+#define AT32_SYSCLK (AT32_HEXTCLK / 32)
+#else
+#error "invalid AT32_HEXT_TO_SCLK_DIV value specified"
+#endif
+
+#elif AT32_SCLKSEL == AT32_SCLKSEL_PLL
+
+#define AT32_SYSCLK AT32_PLLPCLK
+
+#else
+#error "invalid AT32_SCLKSEL value specified"
+#endif
+
+/* Check on the system clock.*/
+#if AT32_SYSCLK > AT32_SYSCLK_MAX
+#error "AT32_SYSCLK above maximum rated frequency (AT32_SYSCLK_MAX)"
+#endif
+
+/**
+ * @brief AHB frequency.
+ */
+#if (AT32_AHBDIV == AT32_AHBDIV_DIV1) || defined(__DOXYGEN__)
+#define AT32_HCLK (AT32_SYSCLK / 1)
+#elif AT32_AHBDIV == AT32_AHBDIV_DIV2
+#define AT32_HCLK (AT32_SYSCLK / 2)
+#elif AT32_AHBDIV == AT32_AHBDIV_DIV4
+#define AT32_HCLK (AT32_SYSCLK / 4)
+#elif AT32_AHBDIV == AT32_AHBDIV_DIV8
+#define AT32_HCLK (AT32_SYSCLK / 8)
+#elif AT32_AHBDIV == AT32_AHBDIV_DIV16
+#define AT32_HCLK (AT32_SYSCLK / 16)
+#elif AT32_AHBDIV == AT32_AHBDIV_DIV64
+#define AT32_HCLK (AT32_SYSCLK / 64)
+#elif AT32_AHBDIV == AT32_AHBDIV_DIV128
+#define AT32_HCLK (AT32_SYSCLK / 128)
+#elif AT32_AHBDIV == AT32_AHBDIV_DIV256
+#define AT32_HCLK (AT32_SYSCLK / 256)
+#elif AT32_AHBDIV == AT32_AHBDIV_DIV512
+#define AT32_HCLK (AT32_SYSCLK / 512)
+#else
+#error "invalid AT32_AHBDIV value specified"
+#endif
+
+/* AHB frequency check.*/
+#if AT32_HCLK > AT32_SYSCLK_MAX
+#error "AT32_HCLK exceeding maximum frequency (AT32_SYSCLK_MAX)"
+#endif
+
+/**
+ * @brief APB1 frequency.
+ */
+#if (AT32_APB1DIV == AT32_APB1DIV_DIV1) || defined(__DOXYGEN__)
+#define AT32_PCLK1 (AT32_HCLK / 1)
+#elif AT32_APB1DIV == AT32_APB1DIV_DIV2
+#define AT32_PCLK1 (AT32_HCLK / 2)
+#elif AT32_APB1DIV == AT32_APB1DIV_DIV4
+#define AT32_PCLK1 (AT32_HCLK / 4)
+#elif AT32_APB1DIV == AT32_APB1DIV_DIV8
+#define AT32_PCLK1 (AT32_HCLK / 8)
+#elif AT32_APB1DIV == AT32_APB1DIV_DIV16
+#define AT32_PCLK1 (AT32_HCLK / 16)
+#else
+#error "invalid AT32_APB1DIV value specified"
+#endif
+
+/* APB1 frequency check.*/
+#if AT32_PCLK1 > AT32_PCLK1_MAX
+#error "AT32_PCLK1 exceeding maximum frequency (AT32_PCLK1_MAX)"
+#endif
+
+/**
+ * @brief APB2 frequency.
+ */
+#if (AT32_APB2DIV == AT32_APB2DIV_DIV1) || defined(__DOXYGEN__)
+#define AT32_PCLK2 (AT32_HCLK / 1)
+#elif AT32_APB2DIV == AT32_APB2DIV_DIV2
+#define AT32_PCLK2 (AT32_HCLK / 2)
+#elif AT32_APB2DIV == AT32_APB2DIV_DIV4
+#define AT32_PCLK2 (AT32_HCLK / 4)
+#elif AT32_APB2DIV == AT32_APB2DIV_DIV8
+#define AT32_PCLK2 (AT32_HCLK / 8)
+#elif AT32_APB2DIV == AT32_APB2DIV_DIV16
+#define AT32_PCLK2 (AT32_HCLK / 16)
+#else
+#error "invalid AT32_APB2DIV value specified"
+#endif
+
+/* APB2 frequency check.*/
+#if AT32_PCLK2 > AT32_PCLK2_MAX
+#error "AT32_PCLK2 exceeding maximum frequency (AT32_PCLK2_MAX)"
+#endif
+
+/* Check on LDOOVSEL value.*/
+#if AT32_LDOOVSEL == AT32_LDOOVSEL_1P3V
+
+#if (AT32_HCLK > 216000000) || \
+ (AT32_PCLK1 > 120000000) || \
+ (AT32_PCLK2 > AT32_HCLK)
+#error "AT32 bus clock exceeding maximum frequency when LDO is 1.3V"
+#endif
+
+#elif AT32_LDOOVSEL == AT32_LDOOVSEL_1P2V
+
+#if (AT32_HCLK > 168000000) || \
+ (AT32_PCLK1 > 120000000) || \
+ (AT32_PCLK2 > AT32_HCLK)
+#error "AT32 bus clock exceeding maximum frequency when LDO is 1.2V"
+#endif
+
+#elif ((AT32_LDOOVSEL == AT32_LDOOVSEL_1P1V) || \
+ (AT32_LDOOVSEL == AT32_LDOOVSEL_1P0V))
+
+#if (AT32_HCLK > 108000000) || \
+ (AT32_PCLK1 > AT32_HCLK) || \
+ (AT32_PCLK2 > AT32_HCLK)
+#error "AT32 bus clock exceeding maximum frequency when LDO is 1.0V"
+#endif
+
+#else
+#error "invalid AT32_LDOOVSEL value specified"
+#endif
+
+/**
+ * @brief USB clock.
+ */
+#if AT32_PLLU_USB48_SEL == AT32_PLLU_USB48_SEL_PLLU
+#define AT32_USBCLK AT32_PLLUCLK
+#elif AT32_PLLU_USB48_SEL == AT32_PLLU_USB48_SEL_HICK
+#define AT32_USBCLK AT32_HICKCLKOUT
+#else
+#error "invalid AT32_PLLU_USB48_SEL value specified"
+#endif
+
+/**
+ * @brief HEXT divider toward ERTC clock.
+ */
+#if ((AT32_ERTCDIV_VALUE >= 2) && (AT32_ERTCDIV_VALUE <= 31)) || \
+ defined(__DOXYGEN__)
+#define AT32_HEXTDIVCLK (AT32_HEXTCLK / AT32_ERTCDIV_VALUE)
+#define AT32_ETRCDIV (AT32_ERTCDIV_VALUE << 16)
+#else
+#error "invalid AT32_ERTCDIV value specified"
+#endif
+
+/**
+ * @brief ERTC clock.
+ */
+#if (AT32_ERTCSEL == AT32_ERTCSEL_NOCLOCK) || defined(__DOXYGEN__)
+#define AT32_ERTCCLK 0
+#elif AT32_ERTCSEL == AT32_ERTCSEL_LEXT
+#define AT32_ERTCCLK AT32_LEXTCLK
+#elif AT32_ERTCSEL == AT32_ERTCSEL_LICK
+#define AT32_ERTCCLK AT32_LICKCLK
+#elif AT32_ERTCSEL == AT32_ERTCSEL_HEXTDIV
+#define AT32_ERTCCLK AT32_HEXTDIVCLK
+#else
+#error "invalid AT32_ERTCSEL value specified"
+#endif
+
+/**
+ * @brief I2SF5 clock.
+ */
+#if (AT32_I2SF5CLKSEL == AT32_I2SF5CLKSEL_SCLK) || defined(__DOXYGEN__)
+#define AT32_I2SF5CLK AT32_SYSCLK
+#elif AT32_I2SF5CLKSEL == AT32_I2SF5CLKSEL_PLL
+#define AT32_I2SF5CLK AT32_PLLPCLK
+#elif AT32_I2SF5CLKSEL == AT32_I2SF5CLKSEL_HICK
+#define AT32_I2SF5CLK AT32_HICKCLKOUT
+#elif AT32_I2SF5CLKSEL == AT32_I2SF5CLKSEL_EXCLK
+#define AT32_I2SF5CLK 0
+#else
+#error "invalid AT32_I2SF5CLKSEL value specified"
+#endif
+
+
+/**
+ * @brief Systick clock.
+ */
+#if (AT32_SYSTICK_CLKSRC == AT32_SYSTICK_CLKSRC_HCLKDIV1) || defined(__DOXYGEN__)
+#define AT32_SYSTICK_CLK AT32_HCLK
+#elif AT32_SYSTICK_CLKSRC == AT32_SYSTICK_CLKSRC_HCLKDIV8
+#define AT32_SYSTICK_CLK (AT32_HCLK / 8)
+#else
+#error "invalid AT32_SYSTICK_CLKSRC value specified"
+#endif
+
+/**
+ * @brief Timers 2, 3, 4, 6, 7, 13, 14 clock.
+ */
+#if (AT32_APB1DIV == AT32_APB1DIV_DIV1) || defined(__DOXYGEN__)
+#define AT32_TMRCLK1 (AT32_PCLK1 * 1)
+#else
+#define AT32_TMRCLK1 (AT32_PCLK1 * 2)
+#endif
+
+/**
+ * @brief Timers 1, 9, 10, 11 clock.
+ */
+#if (AT32_APB2DIV == AT32_APB2DIV_DIV1) || defined(__DOXYGEN__)
+#define AT32_TMRCLK2 (AT32_PCLK2 * 1)
+#else
+#define AT32_TMRCLK2 (AT32_PCLK2 * 2)
+#endif
+
+/**
+ * @brief Flash settings.
+ */
+#if (AT32_HCLK <= 32000000) || defined(__DOXYGEN__)
+#define AT32_FLASHBITS 0x00000150
+#elif (AT32_HCLK <= 64000000)
+#define AT32_FLASHBITS 0x00000151
+#elif (AT32_HCLK <= 96000000)
+#define AT32_FLASHBITS 0x00000152
+#elif (AT32_HCLK <= 128000000)
+#define AT32_FLASHBITS 0x00000153
+#elif (AT32_HCLK <= 160000000)
+#define AT32_FLASHBITS 0x00000154
+#elif (AT32_HCLK <= 192000000)
+#define AT32_FLASHBITS 0x00000155
+#elif (AT32_HCLK <= 216000000)
+#define AT32_FLASHBITS 0x00000156
+#endif
+
+#define DEBUG_CTRL_TMR2_PAUSE DEBUG_APB1_PAUSE_TMR2_PAUSE
+/* Various helpers.*/
+#include "nvic.h"
+#include "cache.h"
+#include "mpu_v7m.h"
+#include "at32_crm.h"
+#include "at32_dma.h"
+#include "at32_exint.h"
+#include "at32_isr.h"
+#include "at32_tmr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void hal_lld_init(void);
+ void at32_clock_init(void);
+ void at32_clock_reset(void);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_LLD_H */
+/** @} */
diff --git a/os/hal/ports/AT32/AT32F405xx/platform.mk b/os/hal/ports/AT32/AT32F405xx/platform.mk
new file mode 100644
index 0000000000..c1d78a6be9
--- /dev/null
+++ b/os/hal/ports/AT32/AT32F405xx/platform.mk
@@ -0,0 +1,42 @@
+# Required platform files.
+PLATFORMSRC_CONTRIB += $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \
+ $(CHIBIOS_CONTRIB)/os/hal/ports/AT32/AT32F405xx/hal_lld.c \
+ $(CHIBIOS_CONTRIB)/os/hal/ports/AT32/AT32F405xx/at32_isr.c \
+ $(CHIBIOS_CONTRIB)/os/hal/ports/AT32/AT32F405xx/hal_efl_lld.c
+
+# Required include directories.
+PLATFORMINC_CONTRIB += $(CHIBIOS)/os/hal/ports/common/ARMCMx \
+ $(CHIBIOS_CONTRIB)/os/hal/ports/AT32/AT32F405xx
+
+
+ifeq ($(USE_SMART_BUILD),yes)
+
+# Configuration files directory
+ifeq ($(HALCONFDIR),)
+ ifeq ($(CONFDIR),)
+ HALCONFDIR = .
+ else
+ HALCONFDIR := $(CONFDIR)
+ endif
+endif
+
+HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define"))
+endif #ifeq ($(USE_SMART_BUILD), yes)
+
+# Drivers compatible with the platform.
+include $(CHIBIOS_CONTRIB)/os/hal/ports/AT32/LLD/EXINTv1/driver.mk
+include ${CHIBIOS_CONTRIB}/os/hal/ports/AT32/LLD/GPIOv2/driver.mk
+include $(CHIBIOS_CONTRIB)/os/hal/ports/AT32/LLD/DMAv2/driver.mk
+include $(CHIBIOS_CONTRIB)/os/hal/ports/AT32/LLD/RTCv2/driver.mk
+include $(CHIBIOS_CONTRIB)/os/hal/ports/AT32/LLD/TMRv1/driver.mk
+include $(CHIBIOS_CONTRIB)/os/hal/ports/AT32/LLD/SYSTICKv1/driver.mk
+include $(CHIBIOS_CONTRIB)/os/hal/ports/AT32/LLD/OTGv1/driver.mk
+include $(CHIBIOS_CONTRIB)/os/hal/ports/AT32/LLD/ADCv2/driver.mk
+include $(CHIBIOS_CONTRIB)/os/hal/ports/AT32/LLD/I2Cv2/driver.mk
+include $(CHIBIOS_CONTRIB)/os/hal/ports/AT32/LLD/USARTv2/driver.mk
+include $(CHIBIOS_CONTRIB)/os/hal/ports/AT32/LLD/SPIv2/driver.mk
+
+
+# Shared variables
+ALLCSRC += $(PLATFORMSRC_CONTRIB)
+ALLINC += $(PLATFORMINC_CONTRIB)
diff --git a/os/hal/ports/AT32/LLD/ADCv2/driver.mk b/os/hal/ports/AT32/LLD/ADCv2/driver.mk
new file mode 100644
index 0000000000..de1d275a89
--- /dev/null
+++ b/os/hal/ports/AT32/LLD/ADCv2/driver.mk
@@ -0,0 +1,9 @@
+ifeq ($(USE_SMART_BUILD),yes)
+ifneq ($(findstring HAL_USE_ADC TRUE,$(HALCONF)),)
+PLATFORMSRC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/AT32/LLD/ADCv2/hal_adc_lld.c
+endif
+else
+PLATFORMSRC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/AT32/LLD/ADCv2/hal_adc_lld.c
+endif
+
+PLATFORMINC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/AT32/LLD/ADCv2
\ No newline at end of file
diff --git a/os/hal/ports/AT32/LLD/ADCv2/hal_adc_lld.c b/os/hal/ports/AT32/LLD/ADCv2/hal_adc_lld.c
new file mode 100644
index 0000000000..7f5568e9f6
--- /dev/null
+++ b/os/hal/ports/AT32/LLD/ADCv2/hal_adc_lld.c
@@ -0,0 +1,538 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+ ChibiOS - Copyright (C) 2023..2024 Maxjta
+
+ Licensed 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.
+*/
+
+/**
+ * @file ADCv2/hal_adc_lld.c
+ * @brief AT32 ADC subsystem low level driver source.
+ *
+ * @addtogroup ADC
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_ADC || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#define ADC1_DMA_CHANNEL \
+ AT32_DMA_GETCHANNEL(AT32_ADC_ADC1_DMA_STREAM, AT32_ADC1_DMA_CHN)
+
+#define ADC2_DMA_CHANNEL \
+ AT32_DMA_GETCHANNEL(AT32_ADC_ADC2_DMA_STREAM, AT32_ADC2_DMA_CHN)
+
+#define ADC3_DMA_CHANNEL \
+ AT32_DMA_GETCHANNEL(AT32_ADC_ADC3_DMA_STREAM, AT32_ADC3_DMA_CHN)
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief ADC1 driver identifier.*/
+#if AT32_ADC_USE_ADC1 || defined(__DOXYGEN__)
+ADCDriver ADCD1;
+#endif
+
+/** @brief ADC2 driver identifier.*/
+#if AT32_ADC_USE_ADC2 || defined(__DOXYGEN__)
+ADCDriver ADCD2;
+#endif
+
+/** @brief ADC3 driver identifier.*/
+#if AT32_ADC_USE_ADC3 || defined(__DOXYGEN__)
+ADCDriver ADCD3;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief ADC DMA service routine.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void adc_lld_serve_rx_interrupt(ADCDriver *adcp, uint32_t flags) {
+
+ /* DMA errors handling.*/
+ if ((flags & (AT32_DMA_STS_DTERRF | AT32_DMA_STS_DMERRF)) != 0) {
+ /* DMA, this could help only if the DMA tries to access an unmapped
+ address space or violates alignment rules.*/
+ _adc_isr_error_code(adcp, ADC_ERR_DMAFAILURE);
+ }
+ else {
+ /* It is possible that the conversion group has already be reset by the
+ ADC error handler, in this case this interrupt is spurious.*/
+ if (adcp->grpp != NULL) {
+
+ if ((flags & AT32_DMA_STS_FDTF) != 0) {
+ /* Transfer complete processing.*/
+ _adc_isr_full_code(adcp);
+ }
+ else if ((flags & AT32_DMA_STS_HDTF) != 0) {
+ /* Half transfer processing.*/
+ _adc_isr_half_code(adcp);
+ }
+ }
+ }
+}
+
+/**
+ * @brief ADC IRQ service routine.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ * @param[in] sts content of the STS register
+ */
+static void adc_lld_serve_interrupt(ADCDriver *adcp, uint32_t sts) {
+
+ /* It could be a spurious interrupt caused by overflows after DMA disabling,
+ just ignore it in this case.*/
+ if (adcp->grpp != NULL) {
+ adcerror_t emask = 0U;
+
+ /* Note, an overflow may occur after the conversion ended before the driver
+ is able to stop the ADC, this is why the state is checked too.*/
+ if ((sts & ADC_STS_OCCS) && (adcp->state == ADC_ACTIVE)) {
+ /* ADC overflow condition, this could happen only if the DMA is unable
+ to read data fast enough.*/
+ emask |= ADC_ERR_OVERFLOW;
+ }
+ if (sts & ADC_STS_VMOR) {
+ /* Analog watchdog 1 error.*/
+ emask |= ADC_ERR_VM;
+ }
+ if (emask != 0U) {
+ _adc_isr_error_code(adcp, emask);
+ }
+ }
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if AT32_ADC_USE_ADC1 || AT32_ADC_USE_ADC2 || AT32_ADC_USE_ADC3 || \
+ defined(__DOXYGEN__)
+/**
+ * @brief ADC interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_ADC_HANDLER) {
+ uint32_t sts;
+
+ OSAL_IRQ_PROLOGUE();
+
+#if AT32_ADC_USE_ADC1
+ sts = ADC1->STS;
+ ADC1->STS = 0;
+#if defined(AT32_ADC_ADC1_IRQ_HOOK)
+ AT32_ADC_ADC1_IRQ_HOOK
+#endif
+ adc_lld_serve_interrupt(&ADCD1, sts);
+#endif /* AT32_ADC_USE_ADC1 */
+
+#if AT32_ADC_USE_ADC2
+ sts = ADC2->STS;
+ ADC2->STS = 0;
+#if defined(AT32_ADC_ADC2_IRQ_HOOK)
+ AT32_ADC_ADC2_IRQ_HOOK
+#endif
+ adc_lld_serve_interrupt(&ADCD2, sts);
+#endif /* AT32_ADC_USE_ADC2 */
+
+#if AT32_ADC_USE_ADC3
+ sts = ADC3->STS;
+ ADC3->STS = 0;
+#if defined(AT32_ADC_ADC3_IRQ_HOOK)
+ AT32_ADC_ADC3_IRQ_HOOK
+#endif
+ adc_lld_serve_interrupt(&ADCD3, sts);
+#endif /* AT32_ADC_USE_ADC3 */
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level ADC driver initialization.
+ *
+ * @notapi
+ */
+void adc_lld_init(void) {
+
+#if AT32_ADC_USE_ADC1
+ /* Driver initialization.*/
+ adcObjectInit(&ADCD1);
+ ADCD1.adc = ADC1;
+ ADCD1.dmastp = NULL;
+ ADCD1.dmamode = AT32_DMA_CTRL_CHSEL(ADC1_DMA_CHANNEL) |
+ AT32_DMA_CTRL_CHPL(AT32_ADC_ADC1_DMA_PRIORITY) |
+ AT32_DMA_CTRL_DTD_P2M |
+ AT32_DMA_CTRL_MWIDTH_HWORD | AT32_DMA_CTRL_PWIDTH_HWORD |
+ AT32_DMA_CTRL_MINCM | AT32_DMA_CTRL_FDTIEN |
+ AT32_DMA_CTRL_DMERRIEN | AT32_DMA_CTRL_DTERRIEN;
+ crmEnableADC1(true);
+ ADC1->CTRL1 = 0;
+ ADC1->CTRL2 = ADC_CTRL2_ADCEN;
+
+ /* Reset calibration just to be safe.*/
+ ADC1->CTRL2 = ADC_CTRL2_ADCEN | ADC_CTRL2_ADCALINIT;
+ while ((ADC1->CTRL2 & ADC_CTRL2_ADCALINIT) != 0);
+
+ /* Calibration.*/
+ ADC1->CTRL2 = ADC_CTRL2_ADCEN | ADC_CTRL2_ADCAL;
+ while ((ADC1->CTRL2 & ADC_CTRL2_ADCAL) != 0);
+
+ /* Return the ADC in low power mode.*/
+ ADC1->CTRL2 = 0;
+ crmDisableADC1();
+#endif
+
+#if AT32_ADC_USE_ADC2
+ /* Driver initialization.*/
+ adcObjectInit(&ADCD2);
+ ADCD2.adc = ADC2;
+ ADCD2.dmastp = NULL;
+ ADCD2.dmamode = AT32_DMA_CTRL_CHSEL(ADC2_DMA_CHANNEL) |
+ AT32_DMA_CTRL_CHPL(AT32_ADC_ADC2_DMA_PRIORITY) |
+ AT32_DMA_CTRL_DTD_P2M |
+ AT32_DMA_CTRL_MWIDTH_HWORD | AT32_DMA_CTRL_PWIDTH_HWORD |
+ AT32_DMA_CTRL_MINCM | AT32_DMA_CTRL_FDTIEN |
+ AT32_DMA_CTRL_DMERRIEN | AT32_DMA_CTRL_DTERRIEN;
+ crmEnableADC2(true);
+ ADC2->CTRL1 = 0;
+ ADC2->CTRL2 = ADC_CTRL2_ADCEN;
+
+ /* Reset calibration just to be safe.*/
+ ADC2->CTRL2 = ADC_CTRL2_ADCEN | ADC_CTRL2_ADCALINIT;
+ while ((ADC2->CTRL2 & ADC_CTRL2_ADCALINIT) != 0);
+
+ /* Calibration.*/
+ ADC2->CTRL2 = ADC_CTRL2_ADCEN | ADC_CTRL2_ADCAL;
+ while ((ADC2->CTRL2 & ADC_CTRL2_ADCAL) != 0);
+
+ /* Return the ADC in low power mode.*/
+ ADC2->CTRL2 = 0;
+ crmDisableADC2();
+#endif
+
+#if AT32_ADC_USE_ADC3
+ /* Driver initialization.*/
+ adcObjectInit(&ADCD3);
+ ADCD3.adc = ADC3;
+ ADCD3.dmastp = NULL;
+ ADCD3.dmamode = AT32_DMA_CTRL_CHSEL(ADC3_DMA_CHANNEL) |
+ AT32_DMA_CTRL_CHPL(AT32_ADC_ADC3_DMA_PRIORITY) |
+ AT32_DMA_CTRL_DTD_P2M |
+ AT32_DMA_CTRL_MWIDTH_HWORD | AT32_DMA_CTRL_PWIDTH_HWORD |
+ AT32_DMA_CTRL_MINCM | AT32_DMA_CTRL_FDTIEN |
+ AT32_DMA_CTRL_DMERRIEN | AT32_DMA_CTRL_DTERRIEN;
+ crmEnableADC3(true);
+ ADC3->CTRL1 = 0;
+ ADC3->CTRL2 = ADC_CTRL2_ADCEN;
+
+ /* Reset calibration just to be safe.*/
+ ADC3->CTRL2 = ADC_CTRL2_ADCEN | ADC_CTRL2_ADCALINIT;
+ while ((ADC3->CTRL2 & ADC_CTRL2_ADCALINIT) != 0);
+
+ /* Calibration.*/
+ ADC3->CTRL2 = ADC_CTRL2_ADCEN | ADC_CTRL2_ADCAL;
+ while ((ADC3->CTRL2 & ADC_CTRL2_ADCAL) != 0);
+
+ /* Return the ADC in low power mode.*/
+ ADC3->CTRL2 = 0;
+ crmDisableADC3();
+#endif
+
+ /* The shared vector is initialized on driver initialization and never
+ disabled because sharing.*/
+ nvicEnableVector(AT32_ADC_NUMBER, AT32_ADC_IRQ_PRIORITY);
+}
+
+/**
+ * @brief Configures and activates the ADC peripheral.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_start(ADCDriver *adcp) {
+
+ /* If in stopped state then enables the ADC and DMA clocks.*/
+ if (adcp->state == ADC_STOP) {
+#if AT32_ADC_USE_ADC1
+ if (&ADCD1 == adcp) {
+ adcp->dmastp = dmaStreamAllocI(AT32_ADC_ADC1_DMA_STREAM,
+ AT32_ADC_ADC1_DMA_IRQ_PRIORITY,
+ (at32_dmasts_t)adc_lld_serve_rx_interrupt,
+ (void *)adcp);
+ osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream");
+ dmaStreamSetPeripheral(adcp->dmastp, &ADC1->ODT);
+#if AT32_USE_DMA_V1 && AT32_DMA_USE_DMAMUX
+ dmaSetRequestSource(adcp->dmastp, AT32_ADC_ADC1_DMAMUX_CHANNEL, AT32_DMAMUX_ADC1);
+#elif AT32_USE_DMA_V2 || AT32_USE_DMA_V3
+ dmaSetRequestSource(adcp->dmastp, AT32_DMAMUX_ADC1);
+#endif
+ crmEnableADC1(true);
+ }
+#endif /* AT32_ADC_USE_ADC1 */
+
+#if AT32_ADC_USE_ADC2
+ if (&ADCD2 == adcp) {
+ adcp->dmastp = dmaStreamAllocI(AT32_ADC_ADC2_DMA_STREAM,
+ AT32_ADC_ADC2_DMA_IRQ_PRIORITY,
+ (at32_dmasts_t)adc_lld_serve_rx_interrupt,
+ (void *)adcp);
+ osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream");
+ dmaStreamSetPeripheral(adcp->dmastp, &ADC2->ODT);
+#if AT32_USE_DMA_V1 && AT32_DMA_USE_DMAMUX
+ dmaSetRequestSource(adcp->dmastp, AT32_ADC_ADC2_DMAMUX_CHANNEL, AT32_DMAMUX_ADC2);
+#elif AT32_USE_DMA_V2 || AT32_USE_DMA_V3
+ dmaSetRequestSource(adcp->dmastp, AT32_DMAMUX_ADC2);
+#endif
+ crmEnableADC2(true);
+ }
+#endif /* AT32_ADC_USE_ADC2 */
+
+#if AT32_ADC_USE_ADC3
+ if (&ADCD3 == adcp) {
+ adcp->dmastp = dmaStreamAllocI(AT32_ADC_ADC3_DMA_STREAM,
+ AT32_ADC_ADC3_DMA_IRQ_PRIORITY,
+ (at32_dmasts_t)adc_lld_serve_rx_interrupt,
+ (void *)adcp);
+ osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream");
+ dmaStreamSetPeripheral(adcp->dmastp, &ADC3->ODT);
+#if AT32_USE_DMA_V1 && AT32_DMA_USE_DMAMUX
+ dmaSetRequestSource(adcp->dmastp, AT32_ADC_ADC3_DMAMUX_CHANNEL, AT32_DMAMUX_ADC3);
+#elif AT32_USE_DMA_V2 || AT32_USE_DMA_V3
+ dmaSetRequestSource(adcp->dmastp, AT32_DMAMUX_ADC3);
+#endif
+ crmEnableADC3(true);
+ }
+#endif /* AT32_ADC_USE_ADC3 */
+
+ /* This is a common register but apparently it requires that at least one
+ of the ADCs is clocked in order to allow writing, see bug 3575297.*/
+#if defined(AT32F435_437xx)
+ ADCCOM->CCTRL = (ADCCOM->CCTRL & (ADC_CCTRL_ITSRVEN | ADC_CCTRL_VBATEN)) |
+ ((AT32_ADC_ADCDIV - 2) << 16);
+#elif defined(AT32F423xx)
+ ADCCOM->CCTRL = (ADCCOM->CCTRL & ADC_CCTRL_ITSRVEN) |
+ ((AT32_ADC_ADCDIV - 2) << 16);
+#else
+ adcp->adc->CTRL2 = ADC_CTRL2_ITSRVEN;
+ ADCCOM->CCTRL = ((AT32_ADC_ADCDIV - 2) << 16);
+#endif
+
+ /* ADC initial setup, starting the analog part here in order to reduce
+ the latency when starting a conversion.*/
+ adcp->adc->CTRL1 = 0;
+#if defined(AT32F435_437xx) || defined(AT32F423xx)
+ adcp->adc->CTRL2 = 0;
+#endif
+ adcp->adc->CTRL2 = ADC_CTRL2_ADCEN;
+ }
+}
+
+/**
+ * @brief Deactivates the ADC peripheral.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_stop(ADCDriver *adcp) {
+
+ /* If in ready state then disables the ADC clock.*/
+ if (adcp->state == ADC_READY) {
+
+ dmaStreamFreeI(adcp->dmastp);
+ adcp->dmastp = NULL;
+
+ adcp->adc->CTRL1 = 0;
+ adcp->adc->CTRL2 = 0;
+
+#if AT32_ADC_USE_ADC1
+ if (&ADCD1 == adcp)
+ crmDisableADC1();
+#endif
+
+#if AT32_ADC_USE_ADC2
+ if (&ADCD2 == adcp)
+ crmDisableADC2();
+#endif
+
+#if AT32_ADC_USE_ADC3
+ if (&ADCD3 == adcp)
+ crmDisableADC3();
+#endif
+ }
+}
+
+/**
+ * @brief Starts an ADC conversion.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_start_conversion(ADCDriver *adcp) {
+ uint32_t mode;
+ uint32_t ctrl2;
+ const ADCConversionGroup *grpp = adcp->grpp;
+
+ /* DMA setup.*/
+ mode = adcp->dmamode;
+ if (grpp->circular) {
+ mode |= AT32_DMA_CTRL_LM;
+ if (adcp->depth > 1) {
+ /* If circular buffer depth > 1, then the half transfer interrupt
+ is enabled in order to allow streaming processing.*/
+ mode |= AT32_DMA_CTRL_HDTIEN;
+ }
+ }
+ dmaStreamSetMemory0(adcp->dmastp, adcp->samples);
+ dmaStreamSetTransactionSize(adcp->dmastp, (uint32_t)grpp->num_channels *
+ (uint32_t)adcp->depth);
+ dmaStreamSetMode(adcp->dmastp, mode);
+ dmaStreamEnable(adcp->dmastp);
+
+ /* ADC setup.*/
+ adcp->adc->STS = 0;
+ adcp->adc->SPT1 = grpp->spt1;
+ adcp->adc->SPT2 = grpp->spt2;
+ adcp->adc->VMHB = grpp->vmhb;
+ adcp->adc->VMLB = grpp->vmlb;
+ adcp->adc->OSQ1 = grpp->osq1 | ADC_OSQ1_NUM_CH(grpp->num_channels);
+ adcp->adc->OSQ2 = grpp->osq2;
+ adcp->adc->OSQ3 = grpp->osq3;
+#if AT32_ADC_MAX_CHANNELS >= 20
+ adcp->adc->SPT3 = grpp->spt3;
+ adcp->adc->OSQ4 = grpp->osq4;
+ adcp->adc->OSQ4 = grpp->osq5;
+ adcp->adc->OSQ4 = grpp->osq6;
+#endif
+
+ /* ADC configuration and start.*/
+#if defined(AT32F435_437xx) || defined(AT32F423xx)
+ adcp->adc->CTRL1 = grpp->ctrl1 | ADC_CTRL1_OCCOIE | ADC_CTRL1_SQEN;
+ ctrl2 = grpp->ctrl2 | ADC_CTRL2_OCDMAEN | ADC_CTRL2_OCDRCEN | ADC_CTRL2_ADCEN;
+#else
+ adcp->adc->CTRL1 = grpp->ctrl1 | ADC_CTRL1_OCCOIE | ADC_CTRL1_SQEN;
+ ctrl2 = grpp->ctrl2 | ADC_CTRL2_OCDMAEN | ADC_CTRL2_ADCEN;
+#endif
+
+ /* The start method is different dependign if HW or SW triggered, the
+ start is performed using the method specified in the CTRL2 configuration.*/
+ if ((ctrl2 & ADC_CTRL2_OCSWTRG) != 0) {
+ /* Initializing CTRL2 while keeping ADC_CTRL2_OCSWTRG at zero.*/
+ adcp->adc->CTRL2 = (ctrl2 | ADC_CTRL2_RPEN) & ~ADC_CTRL2_OCSWTRG;
+
+ /* Finally enabling ADC_CTRL2_OCSWTRG.*/
+ adcp->adc->CTRL2 = (ctrl2 | ADC_CTRL2_RPEN);
+ }
+ else
+ adcp->adc->CTRL2 = ctrl2;
+}
+
+/**
+ * @brief Stops an ongoing conversion.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_stop_conversion(ADCDriver *adcp) {
+
+ dmaStreamDisable(adcp->dmastp);
+ adcp->adc->CTRL1 = 0;
+ /* Because ticket #822, preserving injected conversions.*/
+ adcp->adc->CTRL2 &= ~(ADC_CTRL2_OCSWTRG);
+ adcp->adc->CTRL2 = ADC_CTRL2_ADCEN;
+}
+
+/**
+ * @brief Enables the TSVREFE bit.
+ * @details The TSVREFE bit is required in order to sample the internal
+ * temperature sensor and internal reference voltage.
+ * @note This is an AT32-only functionality.
+ */
+void adcAT32EnableITSRVEN(void) {
+
+#if defined(AT32F435_437xx) || defined(AT32F423xx)
+ ADCCOM->CCTRL |= ADC_CCTRL_ITSRVEN;
+#else
+ ADC1->CTRL2 |= ADC_CTRL2_ITSRVEN;
+#endif
+}
+
+/**
+ * @brief Disables the TSVREFE bit.
+ * @details The TSVREFE bit is required in order to sample the internal
+ * temperature sensor and internal reference voltage.
+ * @note This is an AT32-only functionality.
+ */
+void adcAT32DisableITSRVEN(void) {
+
+#if defined(AT32F435_437xx) || defined(AT32F423xx)
+ ADCCOM->CCTRL &= ~ADC_CCTRL_ITSRVEN;
+#else
+ ADC1->CTRL2 &= ~ADC_CTRL2_ITSRVEN;
+#endif
+}
+
+/**
+ * @brief Enables the VBATE bit.
+ * @details The VBATE bit is required in order to sample the VBAT channel.
+ * @note This is an AT32-only functionality.
+ * @note This function is meant to be called after @p adcStart().
+ */
+void adcAT32EnableVBATEN(void) {
+
+#if defined(AT32F435_437xx)
+ ADCCOM->CCTRL |= ADC_CCTRL_VBATEN;
+#endif
+}
+
+/**
+ * @brief Disables the VBATE bit.
+ * @details The VBATE bit is required in order to sample the VBAT channel.
+ * @note This is an AT32-only functionality.
+ * @note This function is meant to be called after @p adcStart().
+ */
+void adcAT32DisableVBATEN(void) {
+
+#if defined(AT32F435_437xx)
+ ADCCOM->CCTRL &= ~ADC_CCTRL_VBATEN;
+#endif
+}
+
+#endif /* HAL_USE_ADC */
+
+/** @} */
diff --git a/os/hal/ports/AT32/LLD/ADCv2/hal_adc_lld.h b/os/hal/ports/AT32/LLD/ADCv2/hal_adc_lld.h
new file mode 100644
index 0000000000..1143ce59a2
--- /dev/null
+++ b/os/hal/ports/AT32/LLD/ADCv2/hal_adc_lld.h
@@ -0,0 +1,576 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+ ChibiOS - Copyright (C) 2023..2024 Maxjta
+
+ Licensed 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.
+*/
+
+/**
+ * @file ADCv2/hal_adc_lld.h
+ * @brief AT32 ADC subsystem low level driver header.
+ *
+ * @addtogroup ADC
+ * @{
+ */
+
+#ifndef HAL_ADC_LLD_H
+#define HAL_ADC_LLD_H
+
+#if HAL_USE_ADC || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Possible ADC errors mask bits.
+ * @{
+ */
+#define ADC_ERR_DMAFAILURE 1U /**< DMA operations failure. */
+#define ADC_ERR_OVERFLOW 2U /**< ADC overflow condition. */
+#define ADC_ERR_VM 4U /**< Watchdog triggered. */
+/** @} */
+
+/**
+ * @name Absolute Maximum Ratings
+ * @{
+ */
+/**
+ * @brief Minimum ADC clock frequency.
+ */
+#define AT32_ADCCLK_MIN 600000
+
+/**
+ * @brief Maximum ADC clock frequency.
+ */
+#if !defined(AT32_ADCCLK_MAX)
+#if defined(AT32F435_7xx) || defined(AT32F423xx)
+#define AT32_ADCCLK_MAX 80000000
+#else
+#define AT32_ADCCLK_MAX 28000000
+#endif
+#endif
+/** @} */
+
+/**
+ * @name Triggers selection
+ * @{
+ */
+#define ADC_CTRL2_OCETE_MASK (3U << 28U)
+#define ADC_CTRL2_OCETE_DISABLED (0U << 28U)
+#define ADC_CTRL2_OCETE_RISING (1U << 28U)
+#define ADC_CTRL2_OCETE_FALLING (2U << 28U)
+#define ADC_CTRL2_OCETE_BOTH (3U << 28U)
+
+#define ADC_CTRL2_OCTESEL_MASK ((15U << 24U) | (1U << 31))
+#define ADC_CTRL2_OCTESEL_SRC(n) (((n) << 24U) | \
+ (((n) >> 4) << 31))
+/** @} */
+
+/**
+ * @name Available analog channels nums
+ * @{
+ */
+#if !defined(AT32_ADC_MAX_CHANNELS)
+#define AT32_ADC_MAX_CHANNELS 18
+#endif
+/** @} */
+
+/**
+ * @name Available analog channels
+ * @{
+ */
+#define ADC_CHANNEL_IN0 0 /**< @brief External analog input 0. */
+#define ADC_CHANNEL_IN1 1 /**< @brief External analog input 1. */
+#define ADC_CHANNEL_IN2 2 /**< @brief External analog input 2. */
+#define ADC_CHANNEL_IN3 3 /**< @brief External analog input 3. */
+#define ADC_CHANNEL_IN4 4 /**< @brief External analog input 4. */
+#define ADC_CHANNEL_IN5 5 /**< @brief External analog input 5. */
+#define ADC_CHANNEL_IN6 6 /**< @brief External analog input 6. */
+#define ADC_CHANNEL_IN7 7 /**< @brief External analog input 7. */
+#define ADC_CHANNEL_IN8 8 /**< @brief External analog input 8. */
+#define ADC_CHANNEL_IN9 9 /**< @brief External analog input 9. */
+#define ADC_CHANNEL_IN10 10 /**< @brief External analog input 10. */
+#define ADC_CHANNEL_IN11 11 /**< @brief External analog input 11. */
+#define ADC_CHANNEL_IN12 12 /**< @brief External analog input 12. */
+#define ADC_CHANNEL_IN13 13 /**< @brief External analog input 13. */
+#define ADC_CHANNEL_IN14 14 /**< @brief External analog input 14. */
+#define ADC_CHANNEL_IN15 15 /**< @brief External analog input 15. */
+#define ADC_CHANNEL_SENSOR 16 /**< @brief Internal temperature sensor.
+ @note Available onADC1 only. */
+#define ADC_CHANNEL_VINTRV 17 /**< @brief Internal reference.
+ @note Available onADC1 only. */
+#define ADC_CHANNEL_VBAT 18 /**< @brief VBAT.
+ @note Available onADC1 only. */
+#define ADC_CHANNEL_IN20 20 /**< @brief External analog input 20. */
+#define ADC_CHANNEL_IN21 21 /**< @brief External analog input 21. */
+#define ADC_CHANNEL_IN22 22 /**< @brief External analog input 22. */
+#define ADC_CHANNEL_IN23 23 /**< @brief External analog input 23. */
+#define ADC_CHANNEL_IN24 24 /**< @brief External analog input 24. */
+#define ADC_CHANNEL_IN25 25 /**< @brief External analog input 25. */
+#define ADC_CHANNEL_IN26 26 /**< @brief External analog input 26. */
+#define ADC_CHANNEL_IN27 27 /**< @brief External analog input 27. */
+/** @} */
+
+/**
+ * @name Sampling rates
+ * @{
+ */
+#if defined(AT32F435_437xx) || defined(AT32F423xx) || defined(__DOXYGEN__)
+#define ADC_SAMPLE_2P5 0 /**< @brief 2.5 cycles sampling time. */
+#define ADC_SAMPLE_6P5 1 /**< @brief 6.5 cycles sampling time. */
+#define ADC_SAMPLE_12P5 2 /**< @brief 12.5 cycles sampling time. */
+#define ADC_SAMPLE_24P5 3 /**< @brief 24.5 cycles sampling time. */
+#define ADC_SAMPLE_47P5 4 /**< @brief 47.5 cycles sampling time. */
+#define ADC_SAMPLE_92P5 5 /**< @brief 92.5 cycles sampling time. */
+#define ADC_SAMPLE_247P5 6 /**< @brief 247.5 cycles sampling time. */
+#define ADC_SAMPLE_640P5 7 /**< @brief 640.5 cycles sampling time. */
+#else
+#define ADC_SAMPLE_1P5 0 /**< @brief 1.5 cycles sampling time. */
+#define ADC_SAMPLE_7P5 1 /**< @brief 7.5 cycles sampling time. */
+#define ADC_SAMPLE_13P5 2 /**< @brief 13.5 cycles sampling time. */
+#define ADC_SAMPLE_28P5 3 /**< @brief 28.5 cycles sampling time. */
+#define ADC_SAMPLE_41P5 4 /**< @brief 41.5 cycles sampling time. */
+#define ADC_SAMPLE_55P5 5 /**< @brief 55.5 cycles sampling time. */
+#define ADC_SAMPLE_71P5 6 /**< @brief 71.5 cycles sampling time. */
+#define ADC_SAMPLE_239P5 7 /**< @brief 239.5 cycles sampling time. */
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief ADC common clock divider.
+ * @note This setting is influenced by the VDDA voltage and other
+ * external conditions, please refer to the datasheet for more
+ * info.
+ */
+#if !defined(AT32_ADC_ADCDIV) || defined(__DOXYGEN__)
+#define AT32_ADC_ADCDIV 16
+#endif
+
+/**
+ * @brief ADC1 driver enable switch.
+ * @details If set to @p TRUE the support for ADC1 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(AT32_ADC_USE_ADC1) || defined(__DOXYGEN__)
+#define AT32_ADC_USE_ADC1 FALSE
+#endif
+
+/**
+ * @brief ADC2 driver enable switch.
+ * @details If set to @p TRUE the support for ADC2 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(AT32_ADC_USE_ADC2) || defined(__DOXYGEN__)
+#define AT32_ADC_USE_ADC2 FALSE
+#endif
+
+/**
+ * @brief ADC3 driver enable switch.
+ * @details If set to @p TRUE the support for ADC3 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(AT32_ADC_USE_ADC3) || defined(__DOXYGEN__)
+#define AT32_ADC_USE_ADC3 FALSE
+#endif
+
+/**
+ * @brief DMA stream used for ADC1 operations.
+ */
+#if !defined(AT32_ADC_ADC1_DMA_STREAM) || defined(__DOXYGEN__)
+#define AT32_ADC_ADC1_DMA_STREAM AT32_DMA_STREAM_ID_ANY
+#endif
+
+/**
+ * @brief DMA stream used for ADC2 operations.
+ */
+#if !defined(AT32_ADC_ADC2_DMA_STREAM) || defined(__DOXYGEN__)
+#define AT32_ADC_ADC2_DMA_STREAM AT32_DMA_STREAM_ID_ANY
+#endif
+
+/**
+ * @brief DMA stream used for ADC3 operations.
+ */
+#if !defined(AT32_ADC_ADC3_DMA_STREAM) || defined(__DOXYGEN__)
+#define AT32_ADC_ADC3_DMA_STREAM AT32_DMA_STREAM_ID_ANY
+#endif
+
+/**
+ * @brief ADC1 DMA priority (0..3|lowest..highest).
+ */
+#if !defined(AT32_ADC_ADC1_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_ADC_ADC1_DMA_PRIORITY 2
+#endif
+
+/**
+ * @brief ADC2 DMA priority (0..3|lowest..highest).
+ */
+#if !defined(AT32_ADC_ADC2_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_ADC_ADC2_DMA_PRIORITY 2
+#endif
+
+/**
+ * @brief ADC3 DMA priority (0..3|lowest..highest).
+ */
+#if !defined(AT32_ADC_ADC3_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_ADC_ADC3_DMA_PRIORITY 2
+#endif
+
+/**
+ * @brief ADC interrupt priority level setting.
+ * @note This setting is shared among ADC1, ADC2 and ADC3 because
+ * all ADCs share the same vector.
+ */
+#if !defined(AT32_ADC_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_ADC_IRQ_PRIORITY 5
+#endif
+
+/**
+ * @brief ADC1 DMA interrupt priority level setting.
+ */
+#if !defined(AT32_ADC_ADC1_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_ADC_ADC1_DMA_IRQ_PRIORITY 5
+#endif
+
+/**
+ * @brief ADC2 DMA interrupt priority level setting.
+ */
+#if !defined(AT32_ADC_ADC2_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_ADC_ADC2_DMA_IRQ_PRIORITY 5
+#endif
+
+/**
+ * @brief ADC3 DMA interrupt priority level setting.
+ */
+#if !defined(AT32_ADC_ADC3_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_ADC_ADC3_DMA_IRQ_PRIORITY 5
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks.*/
+#if !defined(AT32_HAS_ADC1) || !defined(AT32_HAS_ADC2) || \
+ !defined(AT32_HAS_ADC3)
+#error "AT32_HAS_ADCx not defined in registry"
+#endif
+
+#if !AT32_DMA_SUPPORTS_DMAMUX
+#if (AT32_ADC_USE_ADC1 && !defined(AT32_ADC1_DMA_MSK)) || \
+ (AT32_ADC_USE_ADC2 && !defined(AT32_ADC2_DMA_MSK)) || \
+ (AT32_ADC_USE_ADC3 && !defined(AT32_ADC3_DMA_MSK))
+#error "AT32_ADCx_DMA_MSK not defined in registry"
+#endif
+
+#if (AT32_ADC_USE_ADC1 && !defined(AT32_ADC1_DMA_CHN)) || \
+ (AT32_ADC_USE_ADC2 && !defined(AT32_ADC2_DMA_CHN)) || \
+ (AT32_ADC_USE_ADC3 && !defined(AT32_ADC3_DMA_CHN))
+#error "AT32_ADCx_DMA_CHN not defined in registry"
+#endif
+#endif /* !AT32_DMA_SUPPORTS_DMAMUX */
+
+#if AT32_ADC_USE_ADC1 && !AT32_HAS_ADC1
+#error "ADC1 not present in the selected device"
+#endif
+
+#if AT32_ADC_USE_ADC2 && !AT32_HAS_ADC2
+#error "ADC2 not present in the selected device"
+#endif
+
+#if AT32_ADC_USE_ADC3 && !AT32_HAS_ADC3
+#error "ADC3 not present in the selected device"
+#endif
+
+#if !AT32_ADC_USE_ADC1 && !AT32_ADC_USE_ADC2 && !AT32_ADC_USE_ADC3
+#error "ADC driver activated but no ADC peripheral assigned"
+#endif
+
+#if !AT32_DMA_SUPPORTS_DMAMUX
+
+/* Check on the validity of the assigned DMA channels.*/
+#if AT32_ADC_USE_ADC1 && \
+ !AT32_DMA_IS_VALID_ID(AT32_ADC_ADC1_DMA_STREAM, AT32_ADC1_DMA_MSK)
+#error "invalid DMA stream associated to ADC1"
+#endif
+
+#if AT32_ADC_USE_ADC2 && \
+ !AT32_DMA_IS_VALID_ID(AT32_ADC_ADC2_DMA_STREAM, AT32_ADC2_DMA_MSK)
+#error "invalid DMA stream associated to ADC2"
+#endif
+
+#if AT32_ADC_USE_ADC3 && \
+ !AT32_DMA_IS_VALID_ID(AT32_ADC_ADC3_DMA_STREAM, AT32_ADC3_DMA_MSK)
+#error "invalid DMA stream associated to ADC3"
+#endif
+
+#endif /* !AT32_DMA_SUPPORTS_DMAMUX */
+
+#if !defined(AT32_ADCCLKIN)
+#define AT32_ADCCLKIN AT32_HCLK
+#endif
+
+#if (AT32_ADC_ADCDIV >= 2) || (AT32_ADC_ADCDIV <= 17)
+#define AT32_ADCCLK (AT32_ADCCLKIN / AT32_ADC_ADCDIV)
+#else
+#error "invalid AT32_ADC_ADCDIV value specified"
+#endif
+
+#if (AT32_ADCCLK < AT32_ADCCLK_MIN) || (AT32_ADCCLK > AT32_ADCCLK_MAX) || (AT32_ADCCLK > AT32_PCLK2)
+#error "AT32_ADCCLK outside acceptable range (AT32_ADCCLK_MIN...AT32_ADCCLK_MAX)"
+#endif
+
+#if !defined(AT32_DMA_REQUIRED)
+#define AT32_DMA_REQUIRED
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief ADC sample data type.
+ */
+typedef uint16_t adcsample_t;
+
+/**
+ * @brief Channels number in a conversion group.
+ */
+typedef uint16_t adc_channels_num_t;
+
+/**
+ * @brief Type of an ADC error mask.
+ */
+typedef uint32_t adcerror_t;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level fields of the ADC driver structure.
+ */
+#define adc_lld_driver_fields \
+ /* Pointer to the ADCx registers block.*/ \
+ ADC_TypeDef *adc; \
+ /* Pointer to associated DMA channel.*/ \
+ const at32_dma_stream_t *dmastp; \
+ /* DMA mode bit mask.*/ \
+ uint32_t dmamode
+
+/**
+ * @brief Low level fields of the ADC configuration structure.
+ */
+#define adc_lld_config_fields \
+ /* Dummy configuration, it is not needed.*/ \
+ uint32_t dummy
+
+/**
+ * @brief Low level fields of the ADC configuration structure.
+ */
+#if AT32_ADC_MAX_CHANNELS < 20
+#define adc_lld_configuration_group_fields \
+ /* ADC CTRL1 register initialization data.*/ \
+ uint32_t ctrl1; \
+ /* ADC CTRL2 register initialization data.*/ \
+ uint32_t ctrl2; \
+ /* ADC SPT1 register initialization data.*/ \
+ uint32_t spt1; \
+ /* ADC SPT2 register initialization data.*/ \
+ uint32_t spt2; \
+ /* ADC voltage monitoring high boundary.*/ \
+ uint16_t vmhb; \
+ /* ADC voltage monitoring low boundary.*/ \
+ uint16_t vmlb; \
+ /* ADC OSQ1 register initialization data.*/ \
+ uint32_t osq1; \
+ /* ADC OSQ2 register initialization data.*/ \
+ uint32_t osq2; \
+ /* ADC OSQ3 register initialization data.*/ \
+ uint32_t osq3
+#else
+#define adc_lld_configuration_group_fields \
+ /* ADC CTRL1 register initialization data.*/ \
+ uint32_t ctrl1; \
+ /* ADC CTRL2 register initialization data.*/ \
+ uint32_t ctrl2; \
+ /* ADC SPT1 register initialization data.*/ \
+ uint32_t spt1; \
+ /* ADC SPT2 register initialization data.*/ \
+ uint32_t spt2; \
+ /* ADC voltage monitoring high boundary.*/ \
+ uint16_t vmhb; \
+ /* ADC voltage monitoring low boundary.*/ \
+ uint16_t vmlb; \
+ /* ADC OSQ1 register initialization data.*/ \
+ uint32_t osq1; \
+ /* ADC OSQ2 register initialization data.*/ \
+ uint32_t osq2; \
+ /* ADC OSQ3 register initialization data.*/ \
+ uint32_t osq3; \
+ /* ADC SPT3 register initialization data.*/ \
+ uint32_t spt3; \
+ /* ADC OSQ4 register initialization data.*/ \
+ uint32_t osq4; \
+ /* ADC OSQ5 register initialization data.*/ \
+ uint32_t osq5; \
+ /* ADC OSQ6 register initialization data.*/ \
+ uint32_t osq6
+#endif
+
+/**
+ * @name Sequences building helper macros
+ * @{
+ */
+/**
+ * @brief Number of channels in a conversion sequence.
+ */
+#define ADC_OSQ1_NUM_CH(n) (((n) - 1) << 20)
+
+#define ADC_OSQ3_OSN1_N(n) ((n) << 0) /**< @brief 1st channel in seq. */
+#define ADC_OSQ3_OSN2_N(n) ((n) << 5) /**< @brief 2nd channel in seq. */
+#define ADC_OSQ3_OSN3_N(n) ((n) << 10) /**< @brief 3rd channel in seq. */
+#define ADC_OSQ3_OSN4_N(n) ((n) << 15) /**< @brief 4th channel in seq. */
+#define ADC_OSQ3_OSN5_N(n) ((n) << 20) /**< @brief 5th channel in seq. */
+#define ADC_OSQ3_OSN6_N(n) ((n) << 25) /**< @brief 6th channel in seq. */
+
+#define ADC_OSQ2_OSN7_N(n) ((n) << 0) /**< @brief 7th channel in seq. */
+#define ADC_OSQ2_OSN8_N(n) ((n) << 5) /**< @brief 8th channel in seq. */
+#define ADC_OSQ2_OSN9_N(n) ((n) << 10) /**< @brief 9th channel in seq. */
+#define ADC_OSQ2_OSN10_N(n) ((n) << 15) /**< @brief 10th channel in seq.*/
+#define ADC_OSQ2_OSN11_N(n) ((n) << 20) /**< @brief 11th channel in seq.*/
+#define ADC_OSQ2_OSN12_N(n) ((n) << 25) /**< @brief 12th channel in seq.*/
+
+#define ADC_OSQ1_OSN13_N(n) ((n) << 0) /**< @brief 13th channel in seq.*/
+#define ADC_OSQ1_OSN14_N(n) ((n) << 5) /**< @brief 14th channel in seq.*/
+#define ADC_OSQ1_OSN15_N(n) ((n) << 10) /**< @brief 15th channel in seq.*/
+#define ADC_OSQ1_OSN16_N(n) ((n) << 15) /**< @brief 16th channel in seq.*/
+
+#define ADC_OSQ4_OSN17_N(n) ((n) << 0) /**< @brief 17th channel in seq.*/
+#define ADC_OSQ4_OSN18_N(n) ((n) << 5) /**< @brief 18th channel in seq.*/
+#define ADC_OSQ4_OSN19_N(n) ((n) << 10) /**< @brief 19th channel in seq.*/
+#define ADC_OSQ4_OSN20_N(n) ((n) << 15) /**< @brief 20th channel in seq.*/
+#define ADC_OSQ4_OSN21_N(n) ((n) << 20) /**< @brief 21th channel in seq.*/
+#define ADC_OSQ4_OSN22_N(n) ((n) << 25) /**< @brief 22th channel in seq.*/
+
+#define ADC_OSQ5_OSN23_N(n) ((n) << 0) /**< @brief 23th channel in seq.*/
+#define ADC_OSQ5_OSN24_N(n) ((n) << 5) /**< @brief 24th channel in seq.*/
+#define ADC_OSQ5_OSN25_N(n) ((n) << 10) /**< @brief 25th channel in seq.*/
+#define ADC_OSQ5_OSN26_N(n) ((n) << 15) /**< @brief 26th channel in seq.*/
+#define ADC_OSQ5_OSN27_N(n) ((n) << 20) /**< @brief 27th channel in seq.*/
+#define ADC_OSQ5_OSN28_N(n) ((n) << 25) /**< @brief 28th channel in seq.*/
+
+#define ADC_OSQ6_OSN29_N(n) ((n) << 0) /**< @brief 29th channel in seq.*/
+#define ADC_OSQ6_OSN30_N(n) ((n) << 5) /**< @brief 30th channel in seq.*/
+#define ADC_OSQ6_OSN31_N(n) ((n) << 10) /**< @brief 31th channel in seq.*/
+#define ADC_OSQ6_OSN32_N(n) ((n) << 15) /**< @brief 32th channel in seq.*/
+/** @} */
+
+/**
+ * @name Sampling rate settings helper macros
+ * @{
+ */
+#define ADC_SPT2_CSPT0(n) ((n) << 0) /**< @brief AN0 sampling time. */
+#define ADC_SPT2_CSPT1(n) ((n) << 3) /**< @brief AN1 sampling time. */
+#define ADC_SPT2_CSPT2(n) ((n) << 6) /**< @brief AN2 sampling time. */
+#define ADC_SPT2_CSPT3(n) ((n) << 9) /**< @brief AN3 sampling time. */
+#define ADC_SPT2_CSPT4(n) ((n) << 12) /**< @brief AN4 sampling time. */
+#define ADC_SPT2_CSPT5(n) ((n) << 15) /**< @brief AN5 sampling time. */
+#define ADC_SPT2_CSPT6(n) ((n) << 18) /**< @brief AN6 sampling time. */
+#define ADC_SPT2_CSPT7(n) ((n) << 21) /**< @brief AN7 sampling time. */
+#define ADC_SPT2_CSPT8(n) ((n) << 24) /**< @brief AN8 sampling time. */
+#define ADC_SPT2_CSPT9(n) ((n) << 27) /**< @brief AN9 sampling time. */
+
+#define ADC_SPT1_CSPT10(n) ((n) << 0) /**< @brief AN10 sampling time. */
+#define ADC_SPT1_CSPT11(n) ((n) << 3) /**< @brief AN11 sampling time. */
+#define ADC_SPT1_CSPT12(n) ((n) << 6) /**< @brief AN12 sampling time. */
+#define ADC_SPT1_CSPT13(n) ((n) << 9) /**< @brief AN13 sampling time. */
+#define ADC_SPT1_CSPT14(n) ((n) << 12) /**< @brief AN14 sampling time. */
+#define ADC_SPT1_CSPT15(n) ((n) << 15) /**< @brief AN15 sampling time. */
+#define ADC_SPT1_CSPT16(n) ((n) << 18) /**< @brief Temperature Sensor
+ sampling time. */
+#define ADC_SPT1_CSPT17(n) ((n) << 21) /**< @brief Voltage Reference
+ sampling time. */
+#define ADC_SPT1_CSPT18(n) ((n) << 24) /**< @brief VBAT sampling time. */
+
+#define ADC_SPT3_CSPT20(n) ((n) << 0) /**< @brief AN20 sampling time. */
+#define ADC_SPT3_CSPT21(n) ((n) << 3) /**< @brief AN21 sampling time. */
+#define ADC_SPT3_CSPT22(n) ((n) << 6) /**< @brief AN22 sampling time. */
+#define ADC_SPT3_CSPT23(n) ((n) << 9) /**< @brief AN23 sampling time. */
+#define ADC_SPT3_CSPT24(n) ((n) << 12) /**< @brief AN24 sampling time. */
+#define ADC_SPT3_CSPT25(n) ((n) << 15) /**< @brief AN25 sampling time. */
+#define ADC_SPT3_CSPT26(n) ((n) << 18) /**< @brief AN26 sampling time. */
+#define ADC_SPT3_CSPT27(n) ((n) << 21) /**< @brief AN27 sampling time. */
+/** @} */
+
+/**
+ * @name Threshold settings helper macros
+ * @{
+ */
+/**
+ * @brief High voltage monitoring boundary.
+ */
+#define ADC_VMHB(n) ((n > ADC_VMHB_HB) ? ADC_VMHB_HB : n)
+/**
+ * @brief Low voltage monitoring boundary.
+ */
+#define ADC_VMHL(n) ((n > ADC_VMHL_LB) ? ADC_VMHL_LB : n)
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if AT32_ADC_USE_ADC1 && !defined(__DOXYGEN__)
+extern ADCDriver ADCD1;
+#endif
+
+#if AT32_ADC_USE_ADC2 && !defined(__DOXYGEN__)
+extern ADCDriver ADCD2;
+#endif
+
+#if AT32_ADC_USE_ADC3 && !defined(__DOXYGEN__)
+extern ADCDriver ADCD3;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void adc_lld_init(void);
+ void adc_lld_start(ADCDriver *adcp);
+ void adc_lld_stop(ADCDriver *adcp);
+ void adc_lld_start_conversion(ADCDriver *adcp);
+ void adc_lld_stop_conversion(ADCDriver *adcp);
+ void adcAT32EnableITSRVEN(void);
+ void adcAT32DisableITSRVEN(void);
+ void adcAT32EnableVBATEN(void);
+ void adcAT32DisableVBATEN(void);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_ADC */
+
+#endif /* HAL_ADC_LLD_H */
+
+/** @} */
diff --git a/os/hal/ports/AT32/LLD/DMAv2/at32_dma.c b/os/hal/ports/AT32/LLD/DMAv2/at32_dma.c
new file mode 100644
index 0000000000..99fbb52a3a
--- /dev/null
+++ b/os/hal/ports/AT32/LLD/DMAv2/at32_dma.c
@@ -0,0 +1,823 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+ ChibiOS - Copyright (C) 2023..2024 Maxjta
+
+ Licensed 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.
+*/
+
+/**
+ * @file DMAv1/at32_dma.c
+ * @brief DMA helper driver code.
+ *
+ * @addtogroup AT32_DMA
+ * @details DMA sharing helper driver. In the AT32 the DMA streams are a
+ * shared resource, this driver allows to allocate and free DMA
+ * streams at runtime in order to allow all the other device
+ * drivers to coordinate the access to the resource.
+ * @note The DMA ISR handlers are all declared into this module because
+ * sharing, the various device drivers can associate a callback to
+ * ISRs when allocating streams.
+ * @{
+ */
+
+#include "hal.h"
+
+/* The following macro is only defined if some driver requiring DMA services
+ has been enabled.*/
+#if defined(AT32_DMA_REQUIRED) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/**
+ * @brief Mask of the DMA1 streams in @p dma_streams_mask.
+ */
+#define AT32_DMA1_STREAMS_MASK ((1U << AT32_DMA1_NUM_CHANNELS) - 1U)
+
+/**
+ * @brief Mask of the DMA2 streams in @p dma_streams_mask.
+ */
+#define AT32_DMA2_STREAMS_MASK (((1U << AT32_DMA2_NUM_CHANNELS) - \
+ 1U) << AT32_DMA1_NUM_CHANNELS)
+
+#if AT32_DMA_SUPPORTS_CSELR == TRUE
+
+#if defined(DMA1_CSELR)
+#define __DMA1_CSELR &DMA1_CSELR->CSELR
+#else
+#define __DMA1_CSELR &DMA1->CSELR
+#endif
+
+#if defined(DMA2_CSELR)
+#define __DMA2_CSELR &DMA2_CSELR->CSELR
+#else
+#define __DMA2_CSELR &DMA2->CSELR
+#endif
+
+#define DMA1_CH1_VARIANT __DMA1_CSELR
+#define DMA1_CH2_VARIANT __DMA1_CSELR
+#define DMA1_CH3_VARIANT __DMA1_CSELR
+#define DMA1_CH4_VARIANT __DMA1_CSELR
+#define DMA1_CH5_VARIANT __DMA1_CSELR
+#define DMA1_CH6_VARIANT __DMA1_CSELR
+#define DMA1_CH7_VARIANT __DMA1_CSELR
+#define DMA1_CH8_VARIANT __DMA1_CSELR
+#define DMA2_CH1_VARIANT __DMA2_CSELR
+#define DMA2_CH2_VARIANT __DMA2_CSELR
+#define DMA2_CH3_VARIANT __DMA2_CSELR
+#define DMA2_CH4_VARIANT __DMA2_CSELR
+#define DMA2_CH5_VARIANT __DMA2_CSELR
+#define DMA2_CH6_VARIANT __DMA2_CSELR
+#define DMA2_CH7_VARIANT __DMA2_CSELR
+#define DMA2_CH8_VARIANT __DMA2_CSELR
+
+#elif AT32_DMA_SUPPORTS_DMAMUX == TRUE
+
+#define DMA1MUX_CHANNEL(id) (DMA1MUX_BASE + ((id) * 4U))
+#define DMA2MUX_CHANNEL(id) (DMA2MUX_BASE + ((id) * 4U))
+
+#define DMA1_CH1_VARIANT ((DMAMUX_Channel_TypeDef *)DMA1MUX_CHANNEL(0))
+#define DMA1_CH2_VARIANT ((DMAMUX_Channel_TypeDef *)DMA1MUX_CHANNEL(1))
+#define DMA1_CH3_VARIANT ((DMAMUX_Channel_TypeDef *)DMA1MUX_CHANNEL(2))
+#define DMA1_CH4_VARIANT ((DMAMUX_Channel_TypeDef *)DMA1MUX_CHANNEL(3))
+#define DMA1_CH5_VARIANT ((DMAMUX_Channel_TypeDef *)DMA1MUX_CHANNEL(4))
+#define DMA1_CH6_VARIANT ((DMAMUX_Channel_TypeDef *)DMA1MUX_CHANNEL(5))
+#define DMA1_CH7_VARIANT ((DMAMUX_Channel_TypeDef *)DMA1MUX_CHANNEL(6))
+#define DMA1_CH8_VARIANT ((DMAMUX_Channel_TypeDef *)DMA1MUX_CHANNEL(7))
+#define DMA2_CH1_VARIANT ((DMAMUX_Channel_TypeDef *)DMA2MUX_CHANNEL(0))
+#define DMA2_CH2_VARIANT ((DMAMUX_Channel_TypeDef *)DMA2MUX_CHANNEL(1))
+#define DMA2_CH3_VARIANT ((DMAMUX_Channel_TypeDef *)DMA2MUX_CHANNEL(2))
+#define DMA2_CH4_VARIANT ((DMAMUX_Channel_TypeDef *)DMA2MUX_CHANNEL(3))
+#define DMA2_CH5_VARIANT ((DMAMUX_Channel_TypeDef *)DMA2MUX_CHANNEL(4))
+#define DMA2_CH6_VARIANT ((DMAMUX_Channel_TypeDef *)DMA2MUX_CHANNEL(5))
+#define DMA2_CH7_VARIANT ((DMAMUX_Channel_TypeDef *)DMA2MUX_CHANNEL(6))
+#define DMA2_CH8_VARIANT ((DMAMUX_Channel_TypeDef *)DMA2MUX_CHANNEL(7))
+
+#else /* !(AT32_DMA_SUPPORTS_DMAMUX == TRUE) */
+
+#define DMA1_CH1_VARIANT 0
+#define DMA1_CH2_VARIANT 0
+#define DMA1_CH3_VARIANT 0
+#define DMA1_CH4_VARIANT 0
+#define DMA1_CH5_VARIANT 0
+#define DMA1_CH6_VARIANT 0
+#define DMA1_CH7_VARIANT 0
+#define DMA2_CH1_VARIANT 0
+#define DMA2_CH2_VARIANT 0
+#define DMA2_CH3_VARIANT 0
+#define DMA2_CH4_VARIANT 0
+#define DMA2_CH5_VARIANT 0
+#define DMA2_CH6_VARIANT 0
+#define DMA2_CH7_VARIANT 0
+
+#endif
+
+/*
+ * Default ISR collision masks.
+ */
+#if !defined(AT32_DMA1_CH1_CMASK)
+#define AT32_DMA1_CH1_CMASK (1U << 0U)
+#endif
+
+#if !defined(AT32_DMA1_CH2_CMASK)
+#define AT32_DMA1_CH2_CMASK (1U << 1U)
+#endif
+
+#if !defined(AT32_DMA1_CH3_CMASK)
+#define AT32_DMA1_CH3_CMASK (1U << 2U)
+#endif
+
+#if !defined(AT32_DMA1_CH4_CMASK)
+#define AT32_DMA1_CH4_CMASK (1U << 3U)
+#endif
+
+#if !defined(AT32_DMA1_CH5_CMASK)
+#define AT32_DMA1_CH5_CMASK (1U << 4U)
+#endif
+
+#if !defined(AT32_DMA1_CH6_CMASK)
+#define AT32_DMA1_CH6_CMASK (1U << 5U)
+#endif
+
+#if !defined(AT32_DMA1_CH7_CMASK)
+#define AT32_DMA1_CH7_CMASK (1U << 6U)
+#endif
+
+#if !defined(AT32_DMA1_CH8_CMASK)
+#define AT32_DMA1_CH8_CMASK (1U << 7U)
+#endif
+
+#if !defined(AT32_DMA2_CH1_CMASK)
+#define AT32_DMA2_CH1_CMASK (1U << (AT32_DMA1_NUM_CHANNELS + 0U))
+#endif
+
+#if !defined(AT32_DMA2_CH2_CMASK)
+#define AT32_DMA2_CH2_CMASK (1U << (AT32_DMA1_NUM_CHANNELS + 1U))
+#endif
+
+#if !defined(AT32_DMA2_CH3_CMASK)
+#define AT32_DMA2_CH3_CMASK (1U << (AT32_DMA1_NUM_CHANNELS + 2U))
+#endif
+
+#if !defined(AT32_DMA2_CH4_CMASK)
+#define AT32_DMA2_CH4_CMASK (1U << (AT32_DMA1_NUM_CHANNELS + 3U))
+#endif
+
+#if !defined(AT32_DMA2_CH5_CMASK)
+#define AT32_DMA2_CH5_CMASK (1U << (AT32_DMA1_NUM_CHANNELS + 4U))
+#endif
+
+#if !defined(AT32_DMA2_CH6_CMASK)
+#define AT32_DMA2_CH6_CMASK (1U << (AT32_DMA1_NUM_CHANNELS + 5U))
+#endif
+
+#if !defined(AT32_DMA2_CH7_CMASK)
+#define AT32_DMA2_CH7_CMASK (1U << (AT32_DMA1_NUM_CHANNELS + 6U))
+#endif
+
+#if !defined(AT32_DMA2_CH8_CMASK)
+#define AT32_DMA2_CH8_CMASK (1U << (AT32_DMA1_NUM_CHANNELS + 7U))
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief DMA streams descriptors.
+ * @details This table keeps the association between an unique stream
+ * identifier and the involved physical registers.
+ * @note Don't use this array directly, use the appropriate wrapper macros
+ * instead: @p AT32_DMA1_STREAM1, @p AT32_DMA1_STREAM2 etc.
+ */
+const at32_dma_stream_t _at32_dma_streams[AT32_DMA_STREAMS] = {
+#if AT32_DMA1_NUM_CHANNELS > 0
+ {DMA1, DMA1_CHANNEL1, AT32_DMA1_CH1_CMASK, DMA1_CH1_VARIANT, 0, 0, AT32_DMA1_CH1_NUMBER},
+#endif
+#if AT32_DMA1_NUM_CHANNELS > 1
+ {DMA1, DMA1_CHANNEL2, AT32_DMA1_CH2_CMASK, DMA1_CH2_VARIANT, 4, 1, AT32_DMA1_CH2_NUMBER},
+#endif
+#if AT32_DMA1_NUM_CHANNELS > 2
+ {DMA1, DMA1_CHANNEL3, AT32_DMA1_CH3_CMASK, DMA1_CH3_VARIANT, 8, 2, AT32_DMA1_CH3_NUMBER},
+#endif
+#if AT32_DMA1_NUM_CHANNELS > 3
+ {DMA1, DMA1_CHANNEL4, AT32_DMA1_CH4_CMASK, DMA1_CH4_VARIANT, 12, 3, AT32_DMA1_CH4_NUMBER},
+#endif
+#if AT32_DMA1_NUM_CHANNELS > 4
+ {DMA1, DMA1_CHANNEL5, AT32_DMA1_CH5_CMASK, DMA1_CH5_VARIANT, 16, 4, AT32_DMA1_CH5_NUMBER},
+#endif
+#if AT32_DMA1_NUM_CHANNELS > 5
+ {DMA1, DMA1_CHANNEL6, AT32_DMA1_CH6_CMASK, DMA1_CH6_VARIANT, 20, 5, AT32_DMA1_CH6_NUMBER},
+#endif
+#if AT32_DMA1_NUM_CHANNELS > 6
+ {DMA1, DMA1_CHANNEL7, AT32_DMA1_CH7_CMASK, DMA1_CH7_VARIANT, 24, 6, AT32_DMA1_CH7_NUMBER},
+#endif
+#if AT32_DMA1_NUM_CHANNELS > 7
+ {DMA1, DMA1_CHANNEL8, AT32_DMA1_CH8_CMASK, DMA1_CH8_VARIANT, 28, 7, AT32_DMA1_CH8_NUMBER},
+#endif
+#if AT32_DMA2_NUM_CHANNELS > 0
+ {DMA2, DMA2_CHANNEL1, AT32_DMA2_CH1_CMASK, DMA2_CH1_VARIANT, 0, 0 + AT32_DMA1_NUM_CHANNELS, AT32_DMA2_CH1_NUMBER},
+#endif
+#if AT32_DMA2_NUM_CHANNELS > 1
+ {DMA2, DMA2_CHANNEL2, AT32_DMA2_CH2_CMASK, DMA2_CH2_VARIANT, 4, 1 + AT32_DMA1_NUM_CHANNELS, AT32_DMA2_CH2_NUMBER},
+#endif
+#if AT32_DMA2_NUM_CHANNELS > 2
+ {DMA2, DMA2_CHANNEL3, AT32_DMA2_CH3_CMASK, DMA2_CH3_VARIANT, 8, 2 + AT32_DMA1_NUM_CHANNELS, AT32_DMA2_CH3_NUMBER},
+#endif
+#if AT32_DMA2_NUM_CHANNELS > 3
+ {DMA2, DMA2_CHANNEL4, AT32_DMA2_CH4_CMASK, DMA2_CH4_VARIANT, 12, 3 + AT32_DMA1_NUM_CHANNELS, AT32_DMA2_CH4_NUMBER},
+#endif
+#if AT32_DMA2_NUM_CHANNELS > 4
+ {DMA2, DMA2_CHANNEL5, AT32_DMA2_CH5_CMASK, DMA2_CH5_VARIANT, 16, 4 + AT32_DMA1_NUM_CHANNELS, AT32_DMA2_CH5_NUMBER},
+#endif
+#if AT32_DMA2_NUM_CHANNELS > 5
+ {DMA2, DMA2_CHANNEL6, AT32_DMA2_CH6_CMASK, DMA2_CH6_VARIANT, 20, 5 + AT32_DMA1_NUM_CHANNELS, AT32_DMA2_CH6_NUMBER},
+#endif
+#if AT32_DMA2_NUM_CHANNELS > 6
+ {DMA2, DMA2_CHANNEL7, AT32_DMA2_CH7_CMASK, DMA2_CH7_VARIANT, 24, 6 + AT32_DMA1_NUM_CHANNELS, AT32_DMA2_CH7_NUMBER},
+#endif
+#if AT32_DMA2_NUM_CHANNELS > 7
+ {DMA2, DMA2_CHANNEL8, AT32_DMA2_CH8_CMASK, DMA2_CH8_VARIANT, 28, 7 + AT32_DMA1_NUM_CHANNELS, AT32_DMA2_CH8_NUMBER},
+#endif
+};
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Global DMA-related data structures.
+ */
+static struct {
+ /**
+ * @brief Mask of the allocated streams.
+ */
+ uint32_t allocated_mask;
+ /**
+ * @brief Mask of the enabled streams ISRs.
+ */
+ uint32_t sts_mask;
+ /**
+ * @brief DMA IRQ redirectors.
+ */
+ struct {
+ /**
+ * @brief DMA callback function.
+ */
+ at32_dmasts_t func;
+ /**
+ * @brief DMA callback parameter.
+ */
+ void *param;
+ } streams[AT32_DMA_STREAMS];
+} dma;
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(AT32_DMA1_CH1_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief DMA1 stream 1 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_DMA1_CH1_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ dmaServeInterrupt(AT32_DMA1_STREAM1);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(AT32_DMA1_CH2_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief DMA1 stream 2 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_DMA1_CH2_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ dmaServeInterrupt(AT32_DMA1_STREAM2);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(AT32_DMA1_CH3_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief DMA1 stream 3 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_DMA1_CH3_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ dmaServeInterrupt(AT32_DMA1_STREAM3);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(AT32_DMA1_CH4_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief DMA1 stream 4 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_DMA1_CH4_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ dmaServeInterrupt(AT32_DMA1_STREAM4);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(AT32_DMA1_CH5_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief DMA1 stream 5 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_DMA1_CH5_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ dmaServeInterrupt(AT32_DMA1_STREAM5);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(AT32_DMA1_CH6_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief DMA1 stream 6 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_DMA1_CH6_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ dmaServeInterrupt(AT32_DMA1_STREAM6);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(AT32_DMA1_CH7_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief DMA1 stream 7 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_DMA1_CH7_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ dmaServeInterrupt(AT32_DMA1_STREAM7);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(AT32_DMA1_CH8_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief DMA1 stream 8 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_DMA1_CH8_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ dmaServeInterrupt(AT32_DMA1_STREAM8);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(AT32_DMA2_CH1_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief DMA2 stream 1 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_DMA2_CH1_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ dmaServeInterrupt(AT32_DMA2_STREAM1);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(AT32_DMA2_CH2_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief DMA2 stream 2 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_DMA2_CH2_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ dmaServeInterrupt(AT32_DMA2_STREAM2);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(AT32_DMA2_CH3_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief DMA2 stream 3 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_DMA2_CH3_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ dmaServeInterrupt(AT32_DMA2_STREAM3);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(AT32_DMA2_CH4_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief DMA2 stream 4 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_DMA2_CH4_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ dmaServeInterrupt(AT32_DMA2_STREAM4);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(AT32_DMA2_CH5_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief DMA2 stream 5 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_DMA2_CH5_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ dmaServeInterrupt(AT32_DMA2_STREAM5);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(AT32_DMA2_CH6_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief DMA2 stream 6 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_DMA2_CH6_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ dmaServeInterrupt(AT32_DMA2_STREAM6);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(AT32_DMA2_CH7_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief DMA2 stream 7 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_DMA2_CH7_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ dmaServeInterrupt(AT32_DMA2_STREAM7);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(AT32_DMA2_CH8_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief DMA2 stream 8 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_DMA2_CH8_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ dmaServeInterrupt(AT32_DMA2_STREAM8);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief AT32 DMA helper initialization.
+ *
+ * @init
+ */
+void dmaInit(void) {
+ int i;
+
+ dma.allocated_mask = 0U;
+ dma.sts_mask = 0U;
+ for (i = 0; i < AT32_DMA_STREAMS; i++) {
+ _at32_dma_streams[i].channel->CTRL = AT32_DMA_CCTRL_RESET_VALUE;
+ dma.streams[i].func = NULL;
+ }
+ DMA1->CLR = 0xFFFFFFFFU;
+#if AT32_DMA2_NUM_CHANNELS > 0
+ DMA2->CLR = 0xFFFFFFFFU;
+#endif
+}
+
+/**
+ * @brief Allocates a DMA stream.
+ * @details The stream is allocated and, if required, the DMA clock enabled.
+ * The function also enables the IRQ vector associated to the stream
+ * and initializes its priority.
+ *
+ * @param[in] id numeric identifiers of a specific stream or:
+ * - @p AT32_DMA_STREAM_ID_ANY for any stream.
+ * - @p AT32_DMA_STREAM_ID_ANY_DMA1 for any stream
+ * on DMA1.
+ * - @p AT32_DMA_STREAM_ID_ANY_DMA2 for any stream
+ * on DMA2.
+ * .
+ * @param[in] priority IRQ priority for the DMA stream
+ * @param[in] func handling function pointer, can be @p NULL
+ * @param[in] param a parameter to be passed to the handling function
+ * @return Pointer to the allocated @p at32_dma_stream_t
+ * structure.
+ * @retval NULL if a/the stream is not available.
+ *
+ * @iclass
+ */
+const at32_dma_stream_t *dmaStreamAllocI(uint32_t id,
+ uint32_t priority,
+ at32_dmasts_t func,
+ void *param) {
+ uint32_t i, startid, endid;
+
+ osalDbgCheckClassI();
+
+ if (id < AT32_DMA_STREAMS) {
+ startid = id;
+ endid = id;
+ }
+#if AT32_DMA_SUPPORTS_DMAMUX == TRUE
+ else if (id == AT32_DMA_STREAM_ID_ANY) {
+ startid = 0U;
+ endid = AT32_DMA_STREAMS - 1U;
+ }
+ else if (id == AT32_DMA_STREAM_ID_ANY_DMA1) {
+ startid = 0U;
+ endid = AT32_DMA1_NUM_CHANNELS - 1U;
+ }
+#if AT32_DMA2_NUM_CHANNELS > 0
+ else if (id == AT32_DMA_STREAM_ID_ANY_DMA2) {
+ startid = AT32_DMA1_NUM_CHANNELS;
+ endid = AT32_DMA_STREAMS - 1U;
+ }
+#endif
+#endif
+ else {
+ osalDbgCheck(false);
+ return NULL;
+ }
+
+ for (i = startid; i <= endid; i++) {
+ uint32_t mask = (1U << i);
+ if ((dma.allocated_mask & mask) == 0U) {
+ const at32_dma_stream_t *dmastp = AT32_DMA_STREAM(i);
+
+ /* Installs the DMA handler.*/
+ dma.streams[i].func = func;
+ dma.streams[i].param = param;
+ dma.allocated_mask |= mask;
+
+ /* Enabling DMA clocks required by the current streams set.*/
+ if ((AT32_DMA1_STREAMS_MASK & mask) != 0U) {
+ crmEnableDMA1(true);
+ }
+#if AT32_DMA2_NUM_CHANNELS > 0
+ if ((AT32_DMA2_STREAMS_MASK & mask) != 0U) {
+ crmEnableDMA2(true);
+ }
+#endif
+
+#if (AT32_DMA_SUPPORTS_DMAMUX == TRUE) && defined(crmEnableDMAMUX)
+ /* Enabling DMAMUX if present.*/
+ if (dma.allocated_mask != 0U) {
+ crmEnableDMAMUX(true);
+ }
+#endif
+#if AT32_DMA_SUPPORTS_DMAMUX == TRUE
+ DMA1->MUXSEL = DMA_MUXSEL_TBL_SEL;
+#if AT32_DMA2_NUM_CHANNELS > 0
+ DMA2->MUXSEL = DMA_MUXSEL_TBL_SEL;
+#endif
+#endif
+ /* Enables the associated IRQ vector if not already enabled and if a
+ callback is defined.*/
+ if (func != NULL) {
+ if ((dma.sts_mask & dmastp->cmask) == 0U) {
+ nvicEnableVector(dmastp->vector, priority);
+ }
+ dma.sts_mask |= mask;
+ }
+
+ /* Putting the stream in a known state.*/
+ dmaStreamDisable(dmastp);
+ dmastp->channel->CTRL = AT32_DMA_CCTRL_RESET_VALUE;
+
+ return dmastp;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * @brief Allocates a DMA stream.
+ * @details The stream is allocated and, if required, the DMA clock enabled.
+ * The function also enables the IRQ vector associated to the stream
+ * and initializes its priority.
+ *
+ * @param[in] id numeric identifiers of a specific stream or:
+ * - @p AT32_DMA_STREAM_ID_ANY for any stream.
+ * - @p AT32_DMA_STREAM_ID_ANY_DMA1 for any stream
+ * on DMA1.
+ * - @p AT32_DMA_STREAM_ID_ANY_DMA2 for any stream
+ * on DMA2.
+ * .
+ * @param[in] priority IRQ priority for the DMA stream
+ * @param[in] func handling function pointer, can be @p NULL
+ * @param[in] param a parameter to be passed to the handling function
+ * @return Pointer to the allocated @p at32_dma_stream_t
+ * structure.
+ * @retval NULL if a/the stream is not available.
+ *
+ * @api
+ */
+const at32_dma_stream_t *dmaStreamAlloc(uint32_t id,
+ uint32_t priority,
+ at32_dmasts_t func,
+ void *param) {
+ const at32_dma_stream_t *dmastp;
+
+ osalSysLock();
+ dmastp = dmaStreamAllocI(id, priority, func, param);
+ osalSysUnlock();
+
+ return dmastp;
+}
+
+/**
+ * @brief Releases a DMA stream.
+ * @details The stream is freed and, if required, the DMA clock disabled.
+ * Trying to release a unallocated stream is an illegal operation
+ * and is trapped if assertions are enabled.
+ *
+ * @param[in] dmastp pointer to a at32_dma_stream_t structure
+ *
+ * @iclass
+ */
+void dmaStreamFreeI(const at32_dma_stream_t *dmastp) {
+ uint32_t selfindex = (uint32_t)dmastp->selfindex;
+
+ osalDbgCheck(dmastp != NULL);
+
+ /* Check if the streams is not taken.*/
+ osalDbgAssert((dma.allocated_mask & (1 << selfindex)) != 0U,
+ "not allocated");
+
+ /* Marks the stream as not allocated.*/
+ dma.allocated_mask &= ~(1U << selfindex);
+ dma.sts_mask &= ~(1U << selfindex);
+
+ /* Disables the associated IRQ vector if it is no more in use.*/
+ if ((dma.sts_mask & dmastp->cmask) == 0U) {
+ nvicDisableVector(dmastp->vector);
+ }
+
+ /* Removes the DMA handler.*/
+ dma.streams[selfindex].func = NULL;
+ dma.streams[selfindex].param = NULL;
+
+ /* Shutting down clocks that are no more required, if any.*/
+ if ((dma.allocated_mask & AT32_DMA1_STREAMS_MASK) == 0U) {
+ crmDisableDMA1();
+ }
+#if AT32_DMA2_NUM_CHANNELS > 0
+ if ((dma.allocated_mask & AT32_DMA2_STREAMS_MASK) == 0U) {
+ crmDisableDMA2();
+ }
+#endif
+
+#if (AT32_DMA_SUPPORTS_DMAMUX == TRUE) && defined(crmDisableDMAMUX)
+ /* Shutting down DMAMUX if present.*/
+ if (dma.allocated_mask == 0U) {
+ crmDisableDMAMUX();
+ }
+#endif
+}
+
+/**
+ * @brief Releases a DMA stream.
+ * @details The stream is freed and, if required, the DMA clock disabled.
+ * Trying to release a unallocated stream is an illegal operation
+ * and is trapped if assertions are enabled.
+ *
+ * @param[in] dmastp pointer to a at32_dma_stream_t structure
+ *
+ * @api
+ */
+void dmaStreamFree(const at32_dma_stream_t *dmastp) {
+
+ osalSysLock();
+ dmaStreamFreeI(dmastp);
+ osalSysUnlock();
+}
+
+/**
+ * @brief Serves a DMA IRQ.
+ *
+ * @param[in] dmastp pointer to a at32_dma_stream_t structure
+ *
+ * @special
+ */
+void dmaServeInterrupt(const at32_dma_stream_t *dmastp) {
+ uint32_t flags;
+ uint32_t selfindex = (uint32_t)dmastp->selfindex;
+
+ flags = (dmastp->dma->STS >> dmastp->shift) & AT32_DMA_STS_MASK;
+ if (flags & dmastp->channel->CTRL) {
+ dmastp->dma->CLR = flags << dmastp->shift;
+ if (dma.streams[selfindex].func) {
+ dma.streams[selfindex].func(dma.streams[selfindex].param, flags);
+ }
+ }
+}
+
+#if (AT32_DMA_SUPPORTS_DMAMUX == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Associates a peripheral request to a DMA stream.
+ * @note This function can be invoked in both ISR or thread context.
+ *
+ * @param[in] dmastp pointer to a @p at32_dma_stream_t structure
+ * @param[in] per peripheral identifier
+ *
+ * @special
+ */
+void dmaSetRequestSource(const at32_dma_stream_t *dmastp, uint32_t per) {
+
+ osalDbgCheck(per < 128U);
+
+ dmastp->mux->MUXCTRL = per;
+}
+#endif
+
+#endif /* AT32_DMA_REQUIRED */
+
+/** @} */
diff --git a/os/hal/ports/AT32/LLD/DMAv2/at32_dma.h b/os/hal/ports/AT32/LLD/DMAv2/at32_dma.h
new file mode 100644
index 0000000000..a695edf645
--- /dev/null
+++ b/os/hal/ports/AT32/LLD/DMAv2/at32_dma.h
@@ -0,0 +1,585 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+ ChibiOS - Copyright (C) 2023..2024 Maxjta
+
+ Licensed 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.
+*/
+
+/**
+ * @file DMAv2/at32_dma.h
+ * @brief DMA helper driver header.
+ * @note This driver uses the new naming convention used for the AT32F4xx
+ * so the "DMA channels" are referred as "DMA streams".
+ *
+ * @addtogroup AT32_DMA
+ * @{
+ */
+
+#ifndef AT32_DMA_H
+#define AT32_DMA_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @brief Requires use of DMAv2 driver model.
+ */
+#define AT32_USE_DMA_V2 TRUE
+
+/**
+ * @brief DMA capability.
+ * @details if @p TRUE then the DMA is able of burst transfers, FIFOs,
+ * scatter gather and other advanced features.
+ */
+#define AT32_DMA_ADVANCED FALSE
+
+/**
+ * @brief Total number of DMA streams.
+ * @details This is the total number of streams among all the DMA units.
+ */
+#define AT32_DMA_STREAMS (AT32_DMA1_NUM_CHANNELS + \
+ AT32_DMA2_NUM_CHANNELS)
+
+/**
+ * @brief Mask of the ISR bits passed to the DMA callback functions.
+ */
+#define AT32_DMA_STS_MASK 0x0E
+
+/**
+ * @brief Returns the request line associated to the specified stream.
+ * @note In some AT32 manuals the request line is named confusingly
+ * channel.
+ *
+ * @param[in] id the unique numeric stream identifier
+ * @param[in] c a stream/request association word, one request per
+ * nibble
+ * @return Returns the request associated to the stream.
+ */
+#define AT32_DMA_GETCHANNEL(id, c) \
+ (((uint32_t)(c) >> (((uint32_t)(id) % (uint32_t)AT32_DMA1_NUM_CHANNELS) * 4U)) & 15U)
+
+/**
+ * @brief Checks if a DMA priority is within the valid range.
+ * @param[in] prio DMA priority
+ *
+ * @retval The check result.
+ * @retval false invalid DMA priority.
+ * @retval true correct DMA priority.
+ */
+#define AT32_DMA_IS_VALID_PRIORITY(prio) (((prio) >= 0U) && ((prio) <= 3U))
+
+#if (AT32_DMA_SUPPORTS_DMAMUX == FALSE) || defined(_DOXYGEN__)
+/**
+ * @brief Checks if a DMA stream id is within the valid range.
+ *
+ * @param[in] id DMA stream id
+ * @retval The check result.
+ * @retval false invalid DMA channel.
+ * @retval true correct DMA channel.
+ */
+#define AT32_DMA_IS_VALID_STREAM(id) (((id) >= 0U) && \
+ ((id) < AT32_DMA_STREAMS))
+#else /* AT32_DMA_SUPPORTS_DMAMUX == FALSE */
+#if AT32_DMA2_NUM_CHANNELS > 0
+#define AT32_DMA_IS_VALID_STREAM(id) (((id) >= 0U) && \
+ ((id) <= (AT32_DMA_STREAMS + 2)))
+#else
+#define AT32_DMA_IS_VALID_STREAM(id) (((id) >= 0U) && \
+ ((id) <= (AT32_DMA_STREAMS + 1)))
+#endif
+#endif /* AT32_DMA_SUPPORTS_DMAMUX == FALSE */
+
+/**
+ * @brief Returns an unique numeric identifier for a DMA stream.
+ *
+ * @param[in] dma the DMA unit number
+ * @param[in] stream the stream number
+ * @return An unique numeric stream identifier.
+ */
+#define AT32_DMA_STREAM_ID(dma, stream) \
+ ((((dma) - 1) * AT32_DMA1_NUM_CHANNELS) + ((stream) - 1))
+
+/**
+ * @brief Returns a DMA stream identifier mask.
+ *
+ *
+ * @param[in] dma the DMA unit number
+ * @param[in] stream the stream number
+ * @return A DMA stream identifier mask.
+ */
+#define AT32_DMA_STREAM_ID_MSK(dma, stream) \
+ (1U << AT32_DMA_STREAM_ID(dma, stream))
+
+/**
+ * @brief Checks if a DMA stream unique identifier belongs to a mask.
+ *
+ * @param[in] id the stream numeric identifier
+ * @param[in] mask the stream numeric identifiers mask
+ *
+ * @retval The check result.
+ * @retval false id does not belong to the mask.
+ * @retval true id belongs to the mask.
+ */
+#define AT32_DMA_IS_VALID_ID(id, mask) (((1U << (id)) & (mask)))
+
+#if (AT32_DMA_SUPPORTS_DMAMUX == TRUE) || defined(_DOXYGEN__)
+/**
+ * @name Special stream identifiers
+ * @{
+ */
+#define AT32_DMA_STREAM_ID_ANY AT32_DMA_STREAMS
+#define AT32_DMA_STREAM_ID_ANY_DMA1 (AT32_DMA_STREAM_ID_ANY + 1)
+#if AT32_DMA2_NUM_CHANNELS > 0
+#define AT32_DMA_STREAM_ID_ANY_DMA2 (AT32_DMA_STREAM_ID_ANY_DMA1 + 1)
+#endif
+/** @} */
+#endif
+
+/**
+ * @name DMA streams identifiers
+ * @{
+ */
+/**
+ * @brief Returns a pointer to a at32_dma_stream_t structure.
+ *
+ * @param[in] id the stream numeric identifier
+ * @return A pointer to the at32_dma_stream_t constant structure
+ * associated to the DMA stream.
+ */
+#define AT32_DMA_STREAM(id) (&_at32_dma_streams[id])
+
+#if AT32_DMA1_NUM_CHANNELS > 0
+#define AT32_DMA1_STREAM1 AT32_DMA_STREAM(0)
+#endif
+#if AT32_DMA1_NUM_CHANNELS > 1
+#define AT32_DMA1_STREAM2 AT32_DMA_STREAM(1)
+#endif
+#if AT32_DMA1_NUM_CHANNELS > 2
+#define AT32_DMA1_STREAM3 AT32_DMA_STREAM(2)
+#endif
+#if AT32_DMA1_NUM_CHANNELS > 3
+#define AT32_DMA1_STREAM4 AT32_DMA_STREAM(3)
+#endif
+#if AT32_DMA1_NUM_CHANNELS > 4
+#define AT32_DMA1_STREAM5 AT32_DMA_STREAM(4)
+#endif
+#if AT32_DMA1_NUM_CHANNELS > 5
+#define AT32_DMA1_STREAM6 AT32_DMA_STREAM(5)
+#endif
+#if AT32_DMA1_NUM_CHANNELS > 6
+#define AT32_DMA1_STREAM7 AT32_DMA_STREAM(6)
+#endif
+#if AT32_DMA1_NUM_CHANNELS > 7
+#define AT32_DMA1_STREAM8 AT32_DMA_STREAM(7)
+#endif
+#if AT32_DMA2_NUM_CHANNELS > 0
+#define AT32_DMA2_STREAM1 AT32_DMA_STREAM(AT32_DMA1_NUM_CHANNELS + 0)
+#endif
+#if AT32_DMA2_NUM_CHANNELS > 1
+#define AT32_DMA2_STREAM2 AT32_DMA_STREAM(AT32_DMA1_NUM_CHANNELS + 1)
+#endif
+#if AT32_DMA2_NUM_CHANNELS > 2
+#define AT32_DMA2_STREAM3 AT32_DMA_STREAM(AT32_DMA1_NUM_CHANNELS + 2)
+#endif
+#if AT32_DMA2_NUM_CHANNELS > 3
+#define AT32_DMA2_STREAM4 AT32_DMA_STREAM(AT32_DMA1_NUM_CHANNELS + 3)
+#endif
+#if AT32_DMA2_NUM_CHANNELS > 4
+#define AT32_DMA2_STREAM5 AT32_DMA_STREAM(AT32_DMA1_NUM_CHANNELS + 4)
+#endif
+#if AT32_DMA2_NUM_CHANNELS > 5
+#define AT32_DMA2_STREAM6 AT32_DMA_STREAM(AT32_DMA1_NUM_CHANNELS + 5)
+#endif
+#if AT32_DMA2_NUM_CHANNELS > 6
+#define AT32_DMA2_STREAM7 AT32_DMA_STREAM(AT32_DMA1_NUM_CHANNELS + 6)
+#endif
+#if AT32_DMA2_NUM_CHANNELS > 7
+#define AT32_DMA2_STREAM8 AT32_DMA_STREAM(AT32_DMA1_NUM_CHANNELS + 7)
+#endif
+/** @} */
+
+/**
+ * @name CTRL register constants common to all DMA types
+ * @{
+ */
+#define AT32_DMA_CCTRL_RESET_VALUE 0x00000000U
+#define AT32_DMA_CTRL_CHEN DMA_CTRL_CHEN
+#define AT32_DMA_CTRL_DTERRIEN DMA_CTRL_DTERRIEN
+#define AT32_DMA_CTRL_HDTIEN DMA_CTRL_HDTIEN
+#define AT32_DMA_CTRL_FDTIEN DMA_CTRL_FDTIEN
+#define AT32_DMA_CTRL_DTD_MASK (DMA_CTRL_DTD | DMA_CTRL_M2M)
+#define AT32_DMA_CTRL_DTD_P2M 0U
+#define AT32_DMA_CTRL_DTD_M2P DMA_CTRL_DTD
+#define AT32_DMA_CTRL_DTD_M2M DMA_CTRL_M2M
+#define AT32_DMA_CTRL_LM DMA_CTRL_LM
+#define AT32_DMA_CTRL_PINCM DMA_CTRL_PINCM
+#define AT32_DMA_CTRL_MINCM DMA_CTRL_MINCM
+#define AT32_DMA_CTRL_PWIDTH_MASK DMA_CTRL_PWIDTH
+#define AT32_DMA_CTRL_PWIDTH_BYTE 0U
+#define AT32_DMA_CTRL_PWIDTH_HWORD DMA_CTRL_PWIDTH_16BITS
+#define AT32_DMA_CTRL_PWIDTH_WORD DMA_CTRL_PWIDTH_32BITS
+#define AT32_DMA_CTRL_MWIDTH_MASK DMA_CTRL_MWIDTH
+#define AT32_DMA_CTRL_MWIDTH_BYTE 0U
+#define AT32_DMA_CTRL_MWIDTH_HWORD DMA_CTRL_MWIDTH_16BITS
+#define AT32_DMA_CTRL_MWIDTH_WORD DMA_CTRL_MWIDTH_32BITS
+#define AT32_DMA_CTRL_WIDTH_MASK (AT32_DMA_CTRL_PWIDTH_MASK | \
+ AT32_DMA_CTRL_MWIDTH_MASK)
+#define AT32_DMA_CTRL_CHPL_MASK DMA_CTRL_CHPL
+#define AT32_DMA_CTRL_CHPL(n) ((n) << 12U)
+
+#define AT32_DMA_CCTRL_RESET_VALUE 0x00000000U
+#define AT32_DMA_CCTRL_CHEN DMA_CTRL_CHEN
+#define AT32_DMA_CCTRL_DTERRIEN DMA_CTRL_DTERRIEN
+#define AT32_DMA_CCTRL_HDTIEN DMA_CTRL_HDTIEN
+#define AT32_DMA_CCTRL_FDTIEN DMA_CTRL_FDTIEN
+#define AT32_DMA_CCTRL_DTD_MASK (DMA_CTRL_DTD | DMA_CCTRL_M2M)
+#define AT32_DMA_CCTRL_DTD_P2M 0U
+#define AT32_DMA_CCTRL_DTD_M2P DMA_CTRL_DTD
+#define AT32_DMA_CCTRL_DTD_M2M DMA_CTRL_M2M
+#define AT32_DMA_CCTRL_LM DMA_CTRL_LM
+#define AT32_DMA_CCTRL_PINCM DMA_CTRL_PINCM
+#define AT32_DMA_CCTRL_MINCM DMA_CTRL_MINCM
+#define AT32_DMA_CCTRL_PWIDTH_MASK DMA_CTRL_PWIDTH
+#define AT32_DMA_CCTRL_PWIDTH_BYTE 0U
+#define AT32_DMA_CCTRL_PWIDTH_HWORD DMA_CTRL_PWIDTH_16BITS
+#define AT32_DMA_CCTRL_PWIDTH_WORD DMA_CTRL_PWIDTH_32BITS
+#define AT32_DMA_CCTRL_MWIDTH_MASK DMA_CCTRL_MWIDTH
+#define AT32_DMA_CCTRL_MWIDTH_BYTE 0U
+#define AT32_DMA_CCTRL_MWIDTH_HWORD DMA_CTRL_MWIDTH_16BITS
+#define AT32_DMA_CCTRL_MWIDTH_WORD DMA_CTRL_MWIDTH_32BITS
+#define AT32_DMA_CCTRL_SIZE_MASK (AT32_DMA_CTRL_PWIDTH_MASK | \
+ AT32_DMA_CTRL_MWIDTH_MASK)
+#define AT32_DMA_CCTRL_CHPL_MASK DMA_CTRL_CHPL
+#define AT32_DMA_CCTRL_CHPL(n) ((n) << 12U)
+/** @} */
+
+/**
+ * @name Request line selector macro
+ * @{
+ */
+#if AT32_DMA_SUPPORTS_CSELR || defined(__DOXYGEN__)
+#define AT32_DMA_CTRL_CHSEL_MASK (15U << 16U)
+#define AT32_DMA_CTRL_CHSEL(n) ((n) << 16U)
+#else
+#define AT32_DMA_CTRL_CHSEL_MASK 0U
+#define AT32_DMA_CTRL_CHSEL(n) 0U
+#endif
+/** @} */
+
+/**
+ * @name CTRL register constants only found in enhanced DMA
+ * @{
+ */
+#define AT32_DMA_CTRL_DMERRIEN 0U /**< @brief Ignored by normal DMA. */
+/** @} */
+
+/**
+ * @name Status flags passed to the ISR callbacks
+ * @{
+ */
+#define AT32_DMA_STS_FERRF 0U
+#define AT32_DMA_STS_DMERRF 0U
+#define AT32_DMA_STS_DTERRF (0x1U << 3)
+#define AT32_DMA_STS_HDTF (0x1U << 2)
+#define AT32_DMA_STS_FDTF (0x1U << 1)
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if !defined(AT32_DMA_SUPPORTS_DMAMUX)
+#error "AT32_DMA_SUPPORTS_DMAMUX not defined in registry"
+#endif
+
+#if !defined(AT32_DMA_SUPPORTS_CSELR)
+#error "AT32_DMA_SUPPORTS_CSELR not defined in registry"
+#endif
+
+#if AT32_DMA_SUPPORTS_DMAMUX && AT32_DMA_SUPPORTS_CSELR
+#error "AT32_DMA_SUPPORTS_DMAMUX and AT32_DMA_SUPPORTS_CSELR both TRUE"
+#endif
+
+#if !defined(AT32_DMA1_NUM_CHANNELS)
+#error "AT32_DMA1_NUM_CHANNELS not defined in registry"
+#endif
+
+#if !defined(AT32_DMA2_NUM_CHANNELS)
+#error "AT32_DMA2_NUM_CHANNELS not defined in registry"
+#endif
+
+#if (AT32_DMA1_NUM_CHANNELS < 0) || (AT32_DMA1_NUM_CHANNELS > 8)
+#error "unsupported channels configuration"
+#endif
+
+#if (AT32_DMA2_NUM_CHANNELS < 0) || (AT32_DMA2_NUM_CHANNELS > 8)
+#error "unsupported channels configuration"
+#endif
+
+#if (AT32_DMA_SUPPORTS_DMAMUX == TRUE) || defined(__DOXYGEN__)
+#include "at32_dmamux.h"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of a DMA callback.
+ *
+ * @param[in] p parameter for the registered function
+ * @param[in] flags pre-shifted content of the STS register, the bits
+ * are aligned to bit zero
+ */
+typedef void (*at32_dmasts_t)(void *p, uint32_t flags);
+
+/**
+ * @brief AT32 DMA stream descriptor structure.
+ */
+typedef struct {
+ DMA_TypeDef *dma; /**< @brief Associated DMA. */
+ DMA_Channel_TypeDef *channel; /**< @brief Associated DMA channel. */
+ uint32_t cmask; /**< @brief Mask of streams sharing
+ the same ISR. */
+#if (AT32_DMA_SUPPORTS_CSELR == TRUE) || defined(__DOXYGEN__)
+ volatile uint32_t *cselr; /**< @brief Associated CSELR reg. */
+#elif AT32_DMA_SUPPORTS_DMAMUX == TRUE
+ DMAMUX_Channel_TypeDef *mux; /**< @brief Associated DMA mux. */
+#else
+ uint8_t dummy; /**< @brief Filler. */
+#endif
+ uint8_t shift; /**< @brief Bit offset in STS, CLR
+ and CSELR registers. */
+ uint8_t selfindex; /**< @brief Index to self in array. */
+ uint8_t vector; /**< @brief Associated IRQ vector. */
+} at32_dma_stream_t;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @name Macro Functions
+ * @{
+ */
+/**
+ * @brief Associates a peripheral data register to a DMA stream.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAlloc().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a at32_dma_stream_t structure
+ * @param[in] addr value to be written in the PADDR register
+ *
+ * @special
+ */
+#define dmaStreamSetPeripheral(dmastp, addr) { \
+ (dmastp)->channel->PADDR = (uint32_t)(addr); \
+}
+
+/**
+ * @brief Associates a memory destination to a DMA stream.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAlloc().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a at32_dma_stream_t structure
+ * @param[in] addr value to be written in the MADDR register
+ *
+ * @special
+ */
+#define dmaStreamSetMemory0(dmastp, addr) { \
+ (dmastp)->channel->MADDR = (uint32_t)(addr); \
+}
+
+/**
+ * @brief Sets the number of transfers to be performed.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAlloc().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a at32_dma_stream_t structure
+ * @param[in] size value to be written in the DTCNT register
+ *
+ * @special
+ */
+#define dmaStreamSetTransactionSize(dmastp, size) { \
+ (dmastp)->channel->DTCNT = (uint32_t)(size); \
+}
+
+/**
+ * @brief Returns the number of transfers to be performed.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAlloc().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a at32_dma_stream_t structure
+ * @return The number of transfers to be performed.
+ *
+ * @special
+ */
+#define dmaStreamGetTransactionSize(dmastp) ((size_t)((dmastp)->channel->DTCNT))
+
+/**
+ * @brief Programs the stream mode settings.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAlloc().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a at32_dma_stream_t structure
+ * @param[in] mode value to be written in the CCR register
+ *
+ * @special
+ */
+#if AT32_DMA_SUPPORTS_CSELR || defined(__DOXYGEN__)
+#define dmaStreamSetMode(dmastp, mode) { \
+ uint32_t cselr = *(dmastp)->cselr; \
+ cselr &= ~(0x0000000FU << (dmastp)->shift); \
+ cselr |= (((uint32_t)(mode) >> 16U) << (dmastp)->shift); \
+ *(dmastp)->cselr = cselr; \
+ (dmastp)->channel->CTRL = (uint32_t)(mode); \
+}
+#else
+#define dmaStreamSetMode(dmastp, mode) { \
+ (dmastp)->channel->CTRL = (uint32_t)(mode); \
+}
+#endif
+
+/**
+ * @brief DMA stream enable.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAlloc().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a at32_dma_stream_t structure
+ *
+ * @special
+ */
+#define dmaStreamEnable(dmastp) { \
+ (dmastp)->channel->CTRL |= AT32_DMA_CTRL_CHEN; \
+}
+
+/**
+ * @brief DMA stream disable.
+ * @details The function disables the specified stream and then clears any
+ * pending interrupt.
+ * @note This function can be invoked in both ISR or thread context.
+ * @note Interrupts enabling flags are set to zero after this call, see
+ * bug 3607518.
+ * @pre The stream must have been allocated using @p dmaStreamAlloc().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a at32_dma_stream_t structure
+ *
+ * @special
+ */
+#define dmaStreamDisable(dmastp) { \
+ (dmastp)->channel->CTRL &= ~(AT32_DMA_CTRL_FDTIEN | AT32_DMA_CTRL_HDTIEN | \
+ AT32_DMA_CTRL_DTERRIEN | AT32_DMA_CTRL_CHEN); \
+ dmaStreamClearInterrupt(dmastp); \
+}
+
+/**
+ * @brief DMA stream interrupt sources clear.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAlloc().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a at32_dma_stream_t structure
+ *
+ * @special
+ */
+#define dmaStreamClearInterrupt(dmastp) { \
+ (dmastp)->dma->CLR = AT32_DMA_STS_MASK << (dmastp)->shift; \
+}
+
+/**
+ * @brief Starts a memory to memory operation using the specified stream.
+ * @note The default transfer data mode is "byte to byte" but it can be
+ * changed by specifying extra options in the @p mode parameter.
+ * @pre The stream must have been allocated using @p dmaStreamAlloc().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a at32_dma_stream_t structure
+ * @param[in] mode value to be written in the CCR register, this value
+ * is implicitly ORed with:
+ * - @p AT32_DMA_CTRL_MINCM
+ * - @p AT32_DMA_CTRL_PINCM
+ * - @p AT32_DMA_CTRL_DTD_M2M
+ * - @p AT32_DMA_CTRL_CHEN
+ * .
+ * @param[in] src source address
+ * @param[in] dst destination address
+ * @param[in] n number of data units to copy
+ */
+#define dmaStartMemCopy(dmastp, mode, src, dst, n) { \
+ dmaStreamSetPeripheral(dmastp, src); \
+ dmaStreamSetMemory0(dmastp, dst); \
+ dmaStreamSetTransactionSize(dmastp, n); \
+ dmaStreamSetMode(dmastp, (mode) | \
+ AT32_DMA_CTRL_MINCM | AT32_DMA_CTRL_PINCM | \
+ AT32_DMA_CTRL_DTD_M2M | AT32_DMA_CTRL_CHEN); \
+}
+
+/**
+ * @brief Polled wait for DMA transfer end.
+ * @pre The stream must have been allocated using @p dmaStreamAlloc().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a at32_dma_stream_t structure
+ */
+#define dmaWaitCompletion(dmastp) { \
+ while ((dmastp)->channel->DTCNT > 0U) \
+ ; \
+ dmaStreamDisable(dmastp); \
+}
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(__DOXYGEN__)
+extern const at32_dma_stream_t _at32_dma_streams[AT32_DMA_STREAMS];
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void dmaInit(void);
+ const at32_dma_stream_t *dmaStreamAllocI(uint32_t id,
+ uint32_t priority,
+ at32_dmasts_t func,
+ void *param);
+ const at32_dma_stream_t *dmaStreamAlloc(uint32_t id,
+ uint32_t priority,
+ at32_dmasts_t func,
+ void *param);
+ void dmaStreamFreeI(const at32_dma_stream_t *dmastp);
+ void dmaStreamFree(const at32_dma_stream_t *dmastp);
+ void dmaServeInterrupt(const at32_dma_stream_t *dmastp);
+#if AT32_DMA_SUPPORTS_DMAMUX == TRUE
+ void dmaSetRequestSource(const at32_dma_stream_t *dmastp, uint32_t per);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AT32_DMA_H */
+
+/** @} */
diff --git a/os/hal/ports/AT32/LLD/DMAv2/driver.mk b/os/hal/ports/AT32/LLD/DMAv2/driver.mk
new file mode 100644
index 0000000000..4f01edf899
--- /dev/null
+++ b/os/hal/ports/AT32/LLD/DMAv2/driver.mk
@@ -0,0 +1,2 @@
+PLATFORMSRC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/AT32/LLD/DMAv2/at32_dma.c
+PLATFORMINC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/AT32/LLD/DMAv2
diff --git a/os/hal/ports/AT32/LLD/EXINTv1/at32_exint.h b/os/hal/ports/AT32/LLD/EXINTv1/at32_exint.h
index 138f14fdbc..95c2e2037d 100644
--- a/os/hal/ports/AT32/LLD/EXINTv1/at32_exint.h
+++ b/os/hal/ports/AT32/LLD/EXINTv1/at32_exint.h
@@ -112,11 +112,11 @@ typedef uint32_t exintmode_t;
* @special
*/
#define exintGetAndClearGroup1(mask, out) do { \
- uint32_t intsts; \
+ uint32_t intsts1; \
\
- intsts = EXINT->INTSTS & (mask); \
- (out) = intsts; \
- EXINT->INTSTS = intsts; \
+ intsts1 = EXINT->INTSTS & (mask); \
+ (out) = intsts1; \
+ EXINT->INTSTS = intsts1; \
} while (false)
/*===========================================================================*/
diff --git a/os/hal/ports/AT32/LLD/GPIOv2/at32_gpio.h b/os/hal/ports/AT32/LLD/GPIOv2/at32_gpio.h
new file mode 100644
index 0000000000..99f905c661
--- /dev/null
+++ b/os/hal/ports/AT32/LLD/GPIOv2/at32_gpio.h
@@ -0,0 +1,126 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+ ChibiOS - Copyright (C) 2024 Maxjta
+
+ Licensed 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.
+*/
+
+/**
+ * @file GPIOv2/at32_gpio.h
+ * @brief AT32 GPIO units common header.
+ * @note This file requires definitions from the AT32 header file.
+ *
+ * @addtogroup AT32_GPIOv2
+ * @{
+ */
+
+#ifndef AT32_GPIO_H
+#define AT32_GPIO_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/* Discarded definitions from the AT headers, the PAL driver uses its own
+ definitions in order to have an unified handling for all devices.
+ Unfortunately the AT headers have no uniform definitions for the same
+ objects across the various sub-families.*/
+#undef GPIOA
+#undef GPIOB
+#undef GPIOC
+#undef GPIOD
+#undef GPIOE
+#undef GPIOF
+#undef GPIOG
+#undef GPIOH
+#undef GPIOI
+#undef GPIOJ
+#undef GPIOK
+
+/**
+ * @name GPIO ports definitions
+ * @{
+ */
+#define GPIOA ((at32_gpio_t *)GPIOA_BASE)
+#define GPIOB ((at32_gpio_t *)GPIOB_BASE)
+#define GPIOC ((at32_gpio_t *)GPIOC_BASE)
+#define GPIOD ((at32_gpio_t *)GPIOD_BASE)
+#define GPIOE ((at32_gpio_t *)GPIOE_BASE)
+#define GPIOF ((at32_gpio_t *)GPIOF_BASE)
+#if AT32_HAS_GPIOG
+#define GPIOG ((at32_gpio_t *)GPIOG_BASE)
+#endif
+#if AT32_HAS_GPIOH
+#define GPIOH ((at32_gpio_t *)GPIOH_BASE)
+#endif
+#if AT32_HAS_GPIOI
+#define GPIOI ((at32_gpio_t *)GPIOI_BASE)
+#endif
+#if AT32_HAS_GPIOJ
+#define GPIOJ ((at32_gpio_t *)GPIOJ_BASE)
+#endif
+#if AT32_HAS_GPIOK
+#define GPIOK ((at32_gpio_t *)GPIOK_BASE)
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief AT32 GPIO registers block.
+ */
+typedef struct {
+
+ volatile uint32_t CFGR;
+ volatile uint32_t OMODE;
+ volatile uint32_t ODRVR;
+ volatile uint32_t PULL;
+ volatile uint32_t IDT;
+ volatile uint32_t ODT;
+ volatile union {
+ uint32_t W;
+ struct {
+ uint16_t set;
+ uint16_t clear;
+ } H;
+ } SCR;
+ volatile uint32_t WPR;
+ volatile uint32_t MUXL;
+ volatile uint32_t MUXH;
+ volatile uint32_t CLR;
+ volatile uint32_t TOGR;
+ volatile uint32_t resvd30[3];
+ volatile uint32_t HDRV;
+} at32_gpio_t;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#endif /* AT32_GPIO_H */
+
+/** @} */
diff --git a/os/hal/ports/AT32/LLD/GPIOv2/driver.mk b/os/hal/ports/AT32/LLD/GPIOv2/driver.mk
new file mode 100644
index 0000000000..19c2f5d7f5
--- /dev/null
+++ b/os/hal/ports/AT32/LLD/GPIOv2/driver.mk
@@ -0,0 +1,9 @@
+ifeq ($(USE_SMART_BUILD),yes)
+ifneq ($(findstring HAL_USE_PAL TRUE,$(HALCONF)),)
+PLATFORMSRC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/AT32/LLD/GPIOv2/hal_pal_lld.c
+endif
+else
+PLATFORMSRC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/AT32/LLD/GPIOv2/hal_pal_lld.c
+endif
+
+PLATFORMINC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/AT32/LLD/GPIOv2
diff --git a/os/hal/ports/AT32/LLD/GPIOv2/hal_pal_lld.c b/os/hal/ports/AT32/LLD/GPIOv2/hal_pal_lld.c
new file mode 100644
index 0000000000..7415a5376a
--- /dev/null
+++ b/os/hal/ports/AT32/LLD/GPIOv2/hal_pal_lld.c
@@ -0,0 +1,249 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+ ChibiOS - Copyright (C) 2024 Maxjta
+
+ Licensed 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.
+*/
+
+/**
+ * @file GPIOv2/hal_pal_lld.c
+ * @brief AT32 PAL low level driver code.
+ *
+ * @addtogroup PAL
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_PAL || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+#if (PAL_USE_WAIT == TRUE) || (PAL_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Event records for the 16 GPIO EXINT channels.
+ */
+palevent_t _pal_events[16];
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief PAL driver initialization.
+ *
+ * @notapi
+ */
+void _pal_lld_init(void) {
+
+#if PAL_USE_CALLBACKS || PAL_USE_WAIT || defined(__DOXYGEN__)
+ unsigned i;
+
+ for (i = 0; i < 16; i++) {
+ _pal_init_event(i);
+ }
+#endif
+ crmEnableAHB1(AT32_GPIO_EN_MASK, false);
+}
+
+/**
+ * @brief Pads mode setup.
+ * @details This function programs a pads group belonging to the same port
+ * with the specified mode.
+ * @note @p PAL_MODE_UNCONNECTED is implemented as push pull at minimum
+ * speed.
+ *
+ * @param[in] port the port identifier
+ * @param[in] mask the group mask
+ * @param[in] mode the mode
+ *
+ * @notapi
+ */
+void _pal_lld_setgroupmode(ioportid_t port,
+ ioportmask_t mask,
+ iomode_t mode) {
+
+ uint32_t cfgr = (mode & PAL_AT32_MODE_MASK) >> 0;
+ uint32_t omode = (mode & PAL_AT32_OMODE_MASK) >> 2;
+ uint32_t odrvr = (mode & PAL_AT32_ODRV_MASK) >> 3;
+ uint32_t pull = (mode & PAL_AT32_PULL_MASK) >> 5;
+ uint32_t muxr = (mode & PAL_AT32_ALTERNATE_MASK) >> 7;
+ uint32_t hdrv = (mode & PAL_AT32_HDRV_MASK) >> 11;
+ uint32_t bit = 0;
+
+ while (true) {
+ if ((mask & 1) != 0) {
+ uint32_t muxrmask, m1, m2, m4;
+
+ muxrmask = muxr << ((bit & 7) * 4);
+ m1 = 1 << bit;
+ m2 = 3 << (bit * 2);
+ m4 = 15 << ((bit & 7) * 4);
+ port->OMODE = (port->OMODE & ~m1) | omode;
+ port->ODRVR = (port->ODRVR & ~m2) | odrvr;
+ port->PULL = (port->PULL & ~m2) | pull;
+ port->HDRV = (port->HDRV & ~m1) | hdrv;
+ if ((mode & PAL_AT32_MODE_MASK) == PAL_AT32_MODE_ALTERNATE) {
+ /* If going in alternate mode then the alternate number is set
+ before switching mode in order to avoid glitches.*/
+ if (bit < 8)
+ port->MUXL = (port->MUXL & ~m4) | muxrmask;
+ else
+ port->MUXH = (port->MUXH & ~m4) | muxrmask;
+ port->CFGR = (port->CFGR & ~m2) | cfgr;
+ }
+ else {
+ /* If going into a non-alternate mode then the mode is switched
+ before setting the alternate mode in order to avoid glitches.*/
+ port->CFGR = (port->CFGR & ~m2) | cfgr;
+ if (bit < 8)
+ port->MUXL = (port->MUXL & ~m4) | muxrmask;
+ else
+ port->MUXH = (port->MUXH & ~m4) | muxrmask;
+ }
+ }
+ mask >>= 1;
+ if (!mask)
+ return;
+ omode <<= 1;
+ odrvr <<= 2;
+ pull <<= 2;
+ cfgr <<= 2;
+ bit++;
+ }
+}
+
+#if PAL_USE_CALLBACKS || PAL_USE_WAIT || defined(__DOXYGEN__)
+/**
+ * @brief Pad event enable.
+ * @note Programming an unknown or unsupported mode is silently ignored.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ * @param[in] mode pad event mode
+ *
+ * @notapi
+ */
+void _pal_lld_enablepadevent(ioportid_t port,
+ iopadid_t pad,
+ ioeventmode_t mode) {
+
+ uint32_t padmask, cidx, coff, cmask, portidx;
+
+ /* Enable SCFG clock. */
+ crmEnableSCFG(false);
+
+ /* Mask of the pad.*/
+ padmask = 1U << (uint32_t)pad;
+
+ /* Multiple channel setting of the same channel not allowed, first disable
+ it. This is done because on AT32 the same channel cannot be mapped on
+ multiple ports.*/
+ osalDbgAssert(((EXINT->POLCFG1 & padmask) == 0U) &&
+ ((EXINT->POLCFG2 & padmask) == 0U), "channel already in use");
+
+ /* Port index is obtained assuming that GPIO ports are placed at regular
+ 0x400 intervals in memory space. So far this is true for all devices.*/
+ portidx = (((uint32_t)port - (uint32_t)GPIOA) >> 10U) & 0xFU;
+
+ /* Index and mask of the EXINTC register to be used.*/
+ cidx = (uint32_t)pad >> 2U;
+ coff = ((uint32_t)pad & 3U) * 4U;
+ cmask = ~(0xFU << coff);
+ SCFG->EXINTC[cidx] = (SCFG->EXINTC[cidx] & cmask) | (portidx << coff);
+
+ /* Programming edge registers.*/
+ if (mode & PAL_EVENT_MODE_RISING_EDGE)
+ EXINT->POLCFG1 |= padmask;
+ else
+ EXINT->POLCFG1 &= ~padmask;
+ if (mode & PAL_EVENT_MODE_FALLING_EDGE)
+ EXINT->POLCFG2 |= padmask;
+ else
+ EXINT->POLCFG2 &= ~padmask;
+
+ /* Programming interrupt and event registers.*/
+ EXINT->INTEN |= padmask;
+ EXINT->EVTEN &= ~padmask;
+}
+
+/**
+ * @brief Pad event disable.
+ * @details This function disables previously programmed event callbacks.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ *
+ * @notapi
+ */
+void _pal_lld_disablepadevent(ioportid_t port, iopadid_t pad) {
+ uint32_t padmask, polcfg1, polcfg2;
+
+ polcfg1 = EXINT->POLCFG1;
+ polcfg2 = EXINT->POLCFG2;
+
+ /* Mask of the pad.*/
+ padmask = 1U << (uint32_t)pad;
+
+ /* If either RTRS1 or POLCFG2 is enabled then the channel is in use.*/
+ if (((polcfg1 | polcfg2) & padmask) != 0U) {
+ uint32_t cidx, coff, cport, portidx;
+
+ /* Port index is obtained assuming that GPIO ports are placed at regular
+ 0x400 intervals in memory space. So far this is true for all devices.*/
+ portidx = (((uint32_t)port - (uint32_t)GPIOA) >> 10U) & 0xFU;
+
+ /* Index and mask of the EXINTC register to be used.*/
+ cidx = (uint32_t)pad >> 2U;
+ coff = ((uint32_t)pad & 3U) * 4U;
+ cport = (SCFG->EXINTC[cidx] >> coff) & 0xFU;
+
+ osalDbgAssert(cport == portidx, "channel mapped on different port");
+
+ /* Disabling channel.*/
+ EXINT->INTEN &= ~padmask;
+ EXINT->EVTEN &= ~padmask;
+ EXINT->POLCFG1 = polcfg1 & ~padmask;
+ EXINT->POLCFG2 = polcfg2 & ~padmask;
+ EXINT->INTSTS = padmask;
+
+#if PAL_USE_CALLBACKS || PAL_USE_WAIT
+ /* Callback cleared and/or thread reset.*/
+ _pal_clear_event(pad);
+#endif
+ }
+}
+#endif /* PAL_USE_CALLBACKS || PAL_USE_WAIT */
+
+#endif /* HAL_USE_PAL */
+
+/** @} */
diff --git a/os/hal/ports/AT32/LLD/GPIOv2/hal_pal_lld.h b/os/hal/ports/AT32/LLD/GPIOv2/hal_pal_lld.h
new file mode 100644
index 0000000000..2194f7cf4f
--- /dev/null
+++ b/os/hal/ports/AT32/LLD/GPIOv2/hal_pal_lld.h
@@ -0,0 +1,525 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+ ChibiOS - Copyright (C) 2024 Maxjta
+
+ Licensed 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.
+*/
+
+/**
+ * @file GPIOv2/hal_pal_lld.h
+ * @brief AT32 PAL low level driver header.
+ *
+ * @addtogroup PAL
+ * @{
+ */
+
+#ifndef HAL_PAL_LLD_H
+#define HAL_PAL_LLD_H
+
+#include "at32_gpio.h"
+
+#if HAL_USE_PAL || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Unsupported modes and specific modes */
+/*===========================================================================*/
+
+/* Specifies palInit() without parameter, required until all platforms will
+ be updated to the new style.*/
+#define PAL_NEW_INIT
+
+#undef PAL_MODE_RESET
+#undef PAL_MODE_UNCONNECTED
+#undef PAL_MODE_INPUT
+#undef PAL_MODE_INPUT_PULLUP
+#undef PAL_MODE_INPUT_PULLDOWN
+#undef PAL_MODE_INPUT_ANALOG
+#undef PAL_MODE_OUTPUT_PUSHPULL
+#undef PAL_MODE_OUTPUT_OPENDRAIN
+
+/**
+ * @name AT32-specific I/O mode flags
+ * @{
+ */
+#define PAL_AT32_MODE_MASK (3U << 0U)
+#define PAL_AT32_MODE_INPUT (0U << 0U)
+#define PAL_AT32_MODE_OUTPUT (1U << 0U)
+#define PAL_AT32_MODE_ALTERNATE (2U << 0U)
+#define PAL_AT32_MODE_ANALOG (3U << 0U)
+
+#define PAL_AT32_OMODE_MASK (1U << 2U)
+#define PAL_AT32_OMODE_PUSHPULL (0U << 2U)
+#define PAL_AT32_OMODE_OPENDRAIN (1U << 2U)
+
+#define PAL_AT32_ODRV_MASK (3U << 3U)
+#define PAL_AT32_ODRV_STRONGER (1U << 3U)
+#define PAL_AT32_ODRV_MODERATE (2U << 3U)
+
+#define PAL_AT32_PULL_MASK (3U << 5U)
+#define PAL_AT32_PULL_FLOATING (0U << 5U)
+#define PAL_AT32_PULL_PULLUP (1U << 5U)
+#define PAL_AT32_PULL_PULLDOWN (2U << 5U)
+
+#define PAL_AT32_ALTERNATE_MASK (15U << 7U)
+#define PAL_AT32_ALTERNATE(n) ((n) << 7U)
+
+#define PAL_AT32_HDRV_MASK (1U << 11U)
+#define PAL_AT32_HDRV_NORMAL (0U << 11U)
+#define PAL_AT32_HDRV_HUGE (1U << 11U)
+
+/**
+ * @brief Alternate function.
+ *
+ * @param[in] n alternate function selector
+ */
+#define PAL_MODE_ALTERNATE(n) (PAL_AT32_MODE_ALTERNATE | \
+ PAL_AT32_ALTERNATE(n))
+/** @} */
+
+/**
+ * @name Standard I/O mode flags
+ * @{
+ */
+/**
+ * @brief Implemented as input.
+ */
+#define PAL_MODE_RESET PAL_AT32_MODE_INPUT
+
+/**
+ * @brief Implemented as input with pull-up.
+ */
+#define PAL_MODE_UNCONNECTED PAL_MODE_INPUT_PULLUP
+
+/**
+ * @brief Regular input high-Z pad.
+ */
+#define PAL_MODE_INPUT PAL_AT32_MODE_INPUT
+
+/**
+ * @brief Input pad with weak pull up resistor.
+ */
+#define PAL_MODE_INPUT_PULLUP (PAL_AT32_MODE_INPUT | \
+ PAL_AT32_PULL_PULLUP)
+
+/**
+ * @brief Input pad with weak pull down resistor.
+ */
+#define PAL_MODE_INPUT_PULLDOWN (PAL_AT32_MODE_INPUT | \
+ PAL_AT32_PULL_PULLDOWN)
+
+/**
+ * @brief Analog input mode.
+ */
+#define PAL_MODE_INPUT_ANALOG PAL_AT32_MODE_ANALOG
+
+/**
+ * @brief Push-pull output pad.
+ */
+#define PAL_MODE_OUTPUT_PUSHPULL (PAL_AT32_MODE_OUTPUT | \
+ PAL_AT32_OMODE_PUSHPULL)
+
+/**
+ * @brief Open-drain output pad.
+ */
+#define PAL_MODE_OUTPUT_OPENDRAIN (PAL_AT32_MODE_OUTPUT | \
+ PAL_AT32_OMODE_OPENDRAIN)
+/** @} */
+
+/*===========================================================================*/
+/* I/O Ports Types and constants. */
+/*===========================================================================*/
+
+/**
+ * @name Port related definitions
+ * @{
+ */
+/**
+ * @brief Width, in bits, of an I/O port.
+ */
+#define PAL_IOPORTS_WIDTH 16
+
+/**
+ * @brief Whole port mask.
+ * @details This macro specifies all the valid bits into a port.
+ */
+#define PAL_WHOLE_PORT ((ioportmask_t)0xFFFF)
+/** @} */
+
+/**
+ * @name Line handling macros
+ * @{
+ */
+/**
+ * @brief Forms a line identifier.
+ * @details A port/pad pair are encoded into an @p ioline_t type. The encoding
+ * of this type is platform-dependent.
+ * @note In this driver the pad number is encoded in the lower 4 bits of
+ * the GPIO address which are guaranteed to be zero.
+ */
+#define PAL_LINE(port, pad) \
+ ((ioline_t)((uint32_t)(port)) | ((uint32_t)(pad)))
+
+/**
+ * @brief Decodes a port identifier from a line identifier.
+ */
+#define PAL_PORT(line) \
+ ((at32_gpio_t *)(((uint32_t)(line)) & 0xFFFFFFF0U))
+
+/**
+ * @brief Decodes a pad identifier from a line identifier.
+ */
+#define PAL_PAD(line) \
+ ((uint32_t)((uint32_t)(line) & 0x0000000FU))
+
+/**
+ * @brief Value identifying an invalid line.
+ */
+#define PAL_NOLINE 0U
+/** @} */
+
+/**
+ * @brief Type of digital I/O port sized unsigned integer.
+ */
+typedef uint32_t ioportmask_t;
+
+/**
+ * @brief Type of digital I/O modes.
+ */
+typedef uint32_t iomode_t;
+
+/**
+ * @brief Type of an I/O line.
+ */
+typedef uint32_t ioline_t;
+
+/**
+ * @brief Type of an event mode.
+ */
+typedef uint32_t ioeventmode_t;
+
+/**
+ * @brief Type of a port Identifier.
+ * @details This type can be a scalar or some kind of pointer, do not make
+ * any assumption about it, use the provided macros when populating
+ * variables of this type.
+ */
+typedef at32_gpio_t * ioportid_t;
+
+/**
+ * @brief Type of an pad identifier.
+ */
+typedef uint32_t iopadid_t;
+
+/*===========================================================================*/
+/* I/O Ports Identifiers. */
+/* The low level driver wraps the definitions already present in the AT32 */
+/* firmware library. */
+/*===========================================================================*/
+
+/**
+ * @brief GPIO port A identifier.
+ */
+#if AT32_HAS_GPIOA || defined(__DOXYGEN__)
+#define IOPORT1 GPIOA
+#endif
+
+/**
+ * @brief GPIO port B identifier.
+ */
+#if AT32_HAS_GPIOB || defined(__DOXYGEN__)
+#define IOPORT2 GPIOB
+#endif
+
+/**
+ * @brief GPIO port C identifier.
+ */
+#if AT32_HAS_GPIOC || defined(__DOXYGEN__)
+#define IOPORT3 GPIOC
+#endif
+
+/**
+ * @brief GPIO port D identifier.
+ */
+#if AT32_HAS_GPIOD || defined(__DOXYGEN__)
+#define IOPORT4 GPIOD
+#endif
+
+/**
+ * @brief GPIO port E identifier.
+ */
+#if AT32_HAS_GPIOE || defined(__DOXYGEN__)
+#define IOPORT5 GPIOE
+#endif
+
+/**
+ * @brief GPIO port F identifier.
+ */
+#if AT32_HAS_GPIOF || defined(__DOXYGEN__)
+#define IOPORT6 GPIOF
+#endif
+
+/**
+ * @brief GPIO port G identifier.
+ */
+#if AT32_HAS_GPIOG || defined(__DOXYGEN__)
+#define IOPORT7 GPIOG
+#endif
+
+/**
+ * @brief GPIO port H identifier.
+ */
+#if AT32_HAS_GPIOH || defined(__DOXYGEN__)
+#define IOPORT8 GPIOH
+#endif
+
+/**
+ * @brief GPIO port I identifier.
+ */
+#if AT32_HAS_GPIOI || defined(__DOXYGEN__)
+#define IOPORT9 GPIOI
+#endif
+
+/**
+ * @brief GPIO port J identifier.
+ */
+#if AT32_HAS_GPIOJ || defined(__DOXYGEN__)
+#define IOPORT10 GPIOJ
+#endif
+
+/**
+ * @brief GPIO port K identifier.
+ */
+#if AT32_HAS_GPIOK || defined(__DOXYGEN__)
+#define IOPORT11 GPIOK
+#endif
+
+/*===========================================================================*/
+/* Implementation, some of the following macros could be implemented as */
+/* functions, if so please put them in pal_lld.c. */
+/*===========================================================================*/
+
+/**
+ * @brief GPIO ports subsystem initialization.
+ *
+ * @notapi
+ */
+#define pal_lld_init() _pal_lld_init()
+
+/**
+ * @brief Reads an I/O port.
+ * @details This function is implemented by reading the GPIO IDT register, the
+ * implementation has no side effects.
+ * @note This function is not meant to be invoked directly by the application
+ * code.
+ *
+ * @param[in] port port identifier
+ * @return The port bits.
+ *
+ * @notapi
+ */
+#define pal_lld_readport(port) ((ioportmask_t)((port)->IDT))
+
+/**
+ * @brief Reads the output latch.
+ * @details This function is implemented by reading the GPIO ODT register, the
+ * implementation has no side effects.
+ * @note This function is not meant to be invoked directly by the application
+ * code.
+ *
+ * @param[in] port port identifier
+ * @return The latched logical states.
+ *
+ * @notapi
+ */
+#define pal_lld_readlatch(port) ((ioportmask_t)((port)->ODT))
+
+/**
+ * @brief Writes on a I/O port.
+ * @details This function is implemented by writing the GPIO ODT register, the
+ * implementation has no side effects.
+ *
+ * @param[in] port port identifier
+ * @param[in] bits bits to be written on the specified port
+ *
+ * @notapi
+ */
+#define pal_lld_writeport(port, bits) ((port)->ODT = (uint32_t)(bits))
+
+/**
+ * @brief Sets a bits mask on a I/O port.
+ * @details This function is implemented by writing the GPIO SCR register, the
+ * implementation has no side effects.
+ *
+ * @param[in] port port identifier
+ * @param[in] bits bits to be ORed on the specified port
+ *
+ * @notapi
+ */
+#define pal_lld_setport(port, bits) ((port)->SCR.H.set = (uint16_t)(bits))
+
+/**
+ * @brief Clears a bits mask on a I/O port.
+ * @details This function is implemented by writing the GPIO SCR register, the
+ * implementation has no side effects.
+ *
+ * @param[in] port port identifier
+ * @param[in] bits bits to be cleared on the specified port
+ *
+ * @notapi
+ */
+#define pal_lld_clearport(port, bits) ((port)->SCR.H.clear = (uint16_t)(bits))
+
+/**
+ * @brief Toggles a bits mask on a I/O port.
+ * @details This function is implemented by writing the GPIO TOGR register, the
+ * implementation has no side effects.
+ *
+ * @param[in] port port identifier
+ * @param[in] bits bits to be toggled on the specified port
+ *
+ * @notapi
+ */
+#define pal_lld_toggleport(port, bits) ((port)->TOGR = (uint16_t)(bits))
+
+/**
+ * @brief Writes a group of bits.
+ * @details This function is implemented by writing the GPIO SCR register, the
+ * implementation has no side effects.
+ *
+ * @param[in] port port identifier
+ * @param[in] mask group mask
+ * @param[in] offset the group bit offset within the port
+ * @param[in] bits bits to be written. Values exceeding the group
+ * width are masked.
+ *
+ * @notapi
+ */
+#define pal_lld_writegroup(port, mask, offset, bits) { \
+ uint32_t w = ((~(uint32_t)(bits) & (uint32_t)(mask)) << (16U + (offset))) | \
+ ((uint32_t)(bits) & (uint32_t)(mask)) << (offset); \
+ (port)->SCR.W = w; \
+}
+
+/**
+ * @brief Pads group mode setup.
+ * @details This function programs a pads group belonging to the same port
+ * with the specified mode.
+ *
+ * @param[in] port port identifier
+ * @param[in] mask group mask
+ * @param[in] offset group bit offset within the port
+ * @param[in] mode group mode
+ *
+ * @notapi
+ */
+#define pal_lld_setgroupmode(port, mask, offset, mode) \
+ _pal_lld_setgroupmode(port, mask << offset, mode)
+
+/**
+ * @brief Writes a logical state on an output pad.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ * @param[in] bit logical value, the value must be @p PAL_LOW or
+ * @p PAL_HIGH
+ *
+ * @notapi
+ */
+#define pal_lld_writepad(port, pad, bit) pal_lld_writegroup(port, 1, pad, bit)
+
+/**
+ * @brief Pad event enable.
+ * @note Programming an unknown or unsupported mode is silently ignored.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ * @param[in] mode pad event mode
+ *
+ * @notapi
+ */
+#define pal_lld_enablepadevent(port, pad, mode) \
+ _pal_lld_enablepadevent(port, pad, mode)
+
+/**
+ * @brief Pad event disable.
+ * @details This function disables previously programmed event callbacks.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ *
+ * @notapi
+ */
+#define pal_lld_disablepadevent(port, pad) \
+ _pal_lld_disablepadevent(port, pad)
+
+/**
+ * @brief Returns a PAL event structure associated to a pad.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ *
+ * @notapi
+ */
+#define pal_lld_get_pad_event(port, pad) \
+ &_pal_events[pad]; (void)(port)
+
+/**
+ * @brief Returns a PAL event structure associated to a line.
+ *
+ * @param[in] line line identifier
+ *
+ * @notapi
+ */
+#define pal_lld_get_line_event(line) \
+ &_pal_events[PAL_PAD(line)]
+
+/**
+ * @brief Pad event enable check.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ * @return Pad event status.
+ * @retval false if the pad event is disabled.
+ * @retval true if the pad event is enabled.
+ *
+ * @notapi
+ */
+#define pal_lld_ispadeventenabled(port, pad) \
+ (bool)((EXINT->INTEN & (1U << (uint32_t)pad)) != 0U)
+
+#if !defined(__DOXYGEN__)
+#if (PAL_USE_WAIT == TRUE) || (PAL_USE_CALLBACKS == TRUE)
+extern palevent_t _pal_events[16];
+#endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void _pal_lld_init(void);
+ void _pal_lld_setgroupmode(ioportid_t port,
+ ioportmask_t mask,
+ iomode_t mode);
+ void _pal_lld_enablepadevent(ioportid_t port,
+ iopadid_t pad,
+ ioeventmode_t mode);
+ void _pal_lld_disablepadevent(ioportid_t port, iopadid_t pad);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_PAL */
+
+#endif /* HAL_PAL_LLD_H */
+
+/** @} */
diff --git a/os/hal/ports/AT32/LLD/I2Cv2/driver.mk b/os/hal/ports/AT32/LLD/I2Cv2/driver.mk
new file mode 100644
index 0000000000..ea3344b51c
--- /dev/null
+++ b/os/hal/ports/AT32/LLD/I2Cv2/driver.mk
@@ -0,0 +1,21 @@
+ifeq ($(USE_HAL_I2C_FALLBACK),yes)
+ # Fallback SW driver.
+ ifeq ($(USE_SMART_BUILD),yes)
+ ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),)
+ PLATFORMSRC_CONTRIB += $(CHIBIOS)/os/hal/lib/fallback/I2C/hal_i2c_lld.c
+ endif
+ else
+ PLATFORMSRC_CONTRIB += $(CHIBIOS)/os/hal/lib/fallback/I2C/hal_i2c_lld.c
+ endif
+ PLATFORMINC_CONTRIB += $(CHIBIOS)/os/hal/lib/fallback/I2C
+else
+ # Default HW driver.
+ ifeq ($(USE_SMART_BUILD),yes)
+ ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),)
+ PLATFORMSRC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/AT32/LLD/I2Cv2/hal_i2c_lld.c
+ endif
+ else
+ PLATFORMSRC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/AT32/LLD/I2Cv2/hal_i2c_lld.c
+ endif
+ PLATFORMINC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/AT32/LLD/I2Cv2
+endif
diff --git a/os/hal/ports/AT32/LLD/I2Cv2/hal_i2c_lld.c b/os/hal/ports/AT32/LLD/I2Cv2/hal_i2c_lld.c
new file mode 100644
index 0000000000..501f9b7d1a
--- /dev/null
+++ b/os/hal/ports/AT32/LLD/I2Cv2/hal_i2c_lld.c
@@ -0,0 +1,1189 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+ ChibiOS - Copyright (C) 2023..2024 Maxjta
+
+ Licensed 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.
+*/
+
+/**
+ * @file I2Cv2/hal_i2c_lld.c
+ * @brief AT32 I2C subsystem low level driver source.
+ *
+ * @addtogroup I2C
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_I2C || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#if AT32_I2C_USE_DMA == TRUE
+#define DMAMODE_COMMON \
+ (AT32_DMA_CTRL_PWIDTH_BYTE | AT32_DMA_CTRL_MWIDTH_BYTE | \
+ AT32_DMA_CTRL_MINCM | AT32_DMA_CTRL_DMERRIEN | \
+ AT32_DMA_CTRL_DTERRIEN | AT32_DMA_CTRL_FDTIEN)
+
+#define I2C1_RX_DMA_CHANNEL \
+ AT32_DMA_GETCHANNEL(AT32_I2C_I2C1_RX_DMA_STREAM, \
+ AT32_I2C1_RX_DMA_CHN)
+
+#define I2C1_TX_DMA_CHANNEL \
+ AT32_DMA_GETCHANNEL(AT32_I2C_I2C1_TX_DMA_STREAM, \
+ AT32_I2C1_TX_DMA_CHN)
+
+#define I2C2_RX_DMA_CHANNEL \
+ AT32_DMA_GETCHANNEL(AT32_I2C_I2C2_RX_DMA_STREAM, \
+ AT32_I2C2_RX_DMA_CHN)
+
+#define I2C2_TX_DMA_CHANNEL \
+ AT32_DMA_GETCHANNEL(AT32_I2C_I2C2_TX_DMA_STREAM, \
+ AT32_I2C2_TX_DMA_CHN)
+
+#define I2C3_RX_DMA_CHANNEL \
+ AT32_DMA_GETCHANNEL(AT32_I2C_I2C3_RX_DMA_STREAM, \
+ AT32_I2C3_RX_DMA_CHN)
+
+#define I2C3_TX_DMA_CHANNEL \
+ AT32_DMA_GETCHANNEL(AT32_I2C_I2C3_TX_DMA_STREAM, \
+ AT32_I2C3_TX_DMA_CHN)
+
+#define I2C4_RX_DMA_CHANNEL \
+ AT32_DMA_GETCHANNEL(AT32_I2C_I2C4_RX_DMA_STREAM, \
+ AT32_I2C4_RX_DMA_CHN)
+
+#define I2C4_TX_DMA_CHANNEL \
+ AT32_DMA_GETCHANNEL(AT32_I2C_I2C4_TX_DMA_STREAM, \
+ AT32_I2C4_TX_DMA_CHN)
+#endif /* AT32_I2C_USE_DMA == TRUE */
+
+#if AT32_I2C_USE_DMA == TRUE
+#define i2c_lld_get_rxbytes(i2cp) dmaStreamGetTransactionSize((i2cp)->dmarx)
+#define i2c_lld_get_txbytes(i2cp) dmaStreamGetTransactionSize((i2cp)->dmatx)
+#else
+#define i2c_lld_get_rxbytes(i2cp) (i2cp)->rxbytes
+#define i2c_lld_get_txbytes(i2cp) (i2cp)->txbytes
+#endif
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+#define I2C_ERROR_MASK \
+ ((uint32_t)(I2C_STS_BUSERR | I2C_STS_ARLOST | I2C_STS_OUF | I2C_STS_PECERR | \
+ I2C_STS_TMOUT | I2C_STS_ALERTF))
+
+#define I2C_INT_MASK \
+ ((uint32_t)(I2C_STS_TCRLD | I2C_STS_TDC | I2C_STS_STOPF | I2C_STS_ACKFAILF | \
+ I2C_STS_ADDRF | I2C_STS_RDBF | I2C_STS_TDIS))
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief I2C1 driver identifier.*/
+#if AT32_I2C_USE_I2C1 || defined(__DOXYGEN__)
+I2CDriver I2CD1;
+#endif
+
+/** @brief I2C2 driver identifier.*/
+#if AT32_I2C_USE_I2C2 || defined(__DOXYGEN__)
+I2CDriver I2CD2;
+#endif
+
+/** @brief I2C3 driver identifier.*/
+#if AT32_I2C_USE_I2C3 || defined(__DOXYGEN__)
+I2CDriver I2CD3;
+#endif
+
+/** @brief I2C4 driver identifier.*/
+#if AT32_I2C_USE_I2C4 || defined(__DOXYGEN__)
+I2CDriver I2CD4;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Slave address setup.
+ * @note The RW bit is set to zero internally.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ * @param[in] addr slave device address
+ *
+ * @notapi
+ */
+static void i2c_lld_set_address(I2CDriver *i2cp, i2caddr_t addr) {
+ I2C_TypeDef *dp = i2cp->i2c;
+
+ /* Address alignment depends on the addressing mode selected.*/
+ if ((i2cp->config->ctrl2 & I2C_CTRL2_ADDR10) == 0U)
+ dp->CTRL2 = (uint32_t)addr << 1U;
+ else
+ dp->CTRL2 = (uint32_t)addr;
+}
+
+/**
+ * @brief I2C RX transfer setup.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+static void i2c_lld_setup_rx_transfer(I2CDriver *i2cp) {
+ I2C_TypeDef *dp = i2cp->i2c;
+ uint32_t rlden;
+ size_t n;
+
+ /* The unit can transfer 255 bytes maximum in a single operation.*/
+ n = i2c_lld_get_rxbytes(i2cp);
+ if (n > 255U) {
+ n = 255U;
+ rlden = I2C_CTRL2_RLDEN;
+ }
+ else {
+ rlden = 0U;
+ }
+
+ /* Configures the CTRL2 registers with both the calculated and static
+ settings.*/
+ dp->CTRL2 = (dp->CTRL2 & ~(I2C_CTRL2_CNT_MASK | I2C_CTRL2_RLDEN)) | i2cp->config->ctrl2 |
+ I2C_CTRL2_DIR | (n << 16U) | rlden;
+}
+
+/**
+ * @brief I2C TX transfer setup.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+static void i2c_lld_setup_tx_transfer(I2CDriver *i2cp) {
+ I2C_TypeDef *dp = i2cp->i2c;
+ uint32_t rlden;
+ size_t n;
+
+ /* The unit can transfer 255 bytes maximum in a single operation.*/
+ n = i2c_lld_get_txbytes(i2cp);
+ if (n > 255U) {
+ n = 255U;
+ rlden = I2C_CTRL2_RLDEN;
+ } else {
+ rlden = 0U;
+ }
+
+ /* Configures the CTRL2 registers with both the calculated and static
+ settings.*/
+ dp->CTRL2 = (dp->CTRL2 & ~(I2C_CTRL2_CNT_MASK | I2C_CTRL2_RLDEN)) | i2cp->config->ctrl2 |
+ (n << 16U) | rlden;
+}
+
+/**
+ * @brief Aborts an I2C transaction.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+static void i2c_lld_abort_operation(I2CDriver *i2cp) {
+ I2C_TypeDef *dp = i2cp->i2c;
+
+ if (dp->CTRL1 & I2C_CTRL1_I2CEN) {
+ /* Stops the I2C peripheral.*/
+ dp->CTRL1 &= ~I2C_CTRL1_I2CEN;
+ while (dp->CTRL1 & I2C_CTRL1_I2CEN)
+ dp->CTRL1 &= ~I2C_CTRL1_I2CEN;
+ dp->CTRL1 |= I2C_CTRL1_I2CEN;
+ }
+
+#if AT32_I2C_USE_DMA == TRUE
+ /* Stops the associated DMA streams.*/
+ dmaStreamDisable(i2cp->dmatx);
+ dmaStreamDisable(i2cp->dmarx);
+#else
+ dp->CTRL1 &= ~(I2C_CTRL1_TDIEN | I2C_CTRL1_RDIEN);
+#endif
+}
+
+/**
+ * @brief I2C shared ISR code.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ * @param[in] sts content of the STS register to be decoded
+ *
+ * @notapi
+ */
+static void i2c_lld_serve_interrupt(I2CDriver *i2cp, uint32_t sts) {
+ I2C_TypeDef *dp = i2cp->i2c;
+
+ /* Special case of a received NACK, the transfer is aborted.*/
+ if ((sts & I2C_STS_ACKFAILF) != 0U) {
+#if AT32_I2C_USE_DMA == TRUE
+ /* Stops the associated DMA streams.*/
+ dmaStreamDisable(i2cp->dmatx);
+ dmaStreamDisable(i2cp->dmarx);
+#endif
+
+ /* Error flag.*/
+ i2cp->errors |= I2C_ACK_FAILURE;
+
+ /* Transaction finished sending the STOP.*/
+ dp->CTRL2 |= I2C_CTRL2_GENSTOP;
+
+ /* Make sure no more interrupts.*/
+ dp->CTRL1 &= ~(I2C_CTRL1_TDCIEN | I2C_CTRL1_TDIEN | I2C_CTRL1_RDIEN);
+
+ /* Errors are signaled to the upper layer.*/
+ _i2c_wakeup_error_isr(i2cp);
+
+ return;
+ }
+
+#if AT32_I2C_USE_DMA == FALSE
+ /* Handling of data transfer if the DMA mode is disabled.*/
+ {
+ uint32_t ctrl1 = dp->CTRL1;
+
+ if (i2cp->state == I2C_ACTIVE_TX) {
+ /* Transmission phase.*/
+ if (((ctrl1 & I2C_CTRL1_TDIEN) != 0U) && ((sts & I2C_STS_TDIS) != 0U)) {
+ dp->TXDT = (uint32_t)*i2cp->txptr;
+ i2cp->txptr++;
+ i2cp->txbytes--;
+ if (i2cp->txbytes == 0U) {
+ dp->CTRL1 &= ~I2C_CTRL1_TDIEN;
+ }
+ }
+ }
+ else {
+ /* Receive phase.*/
+ if (((ctrl1 & I2C_CTRL1_RDIEN) != 0U) && ((sts & I2C_STS_RDBF) != 0U)) {
+ *i2cp->rxptr = (uint8_t)dp->RXDT;
+ i2cp->rxptr++;
+ i2cp->rxbytes--;
+ if (i2cp->rxbytes == 0U) {
+ dp->CTRL1 &= ~I2C_CTRL1_RDIEN;
+ }
+ }
+ }
+ }
+#endif
+
+ /* Partial transfer handling, restarting the transfer and returning.*/
+ if ((sts & I2C_STS_TCRLD) != 0U) {
+ if (i2cp->state == I2C_ACTIVE_TX) {
+ i2c_lld_setup_tx_transfer(i2cp);
+ }
+ else {
+ i2c_lld_setup_rx_transfer(i2cp);
+ }
+ return;
+ }
+
+ /* The following condition is true if a transfer phase has been completed.*/
+ if ((sts & I2C_STS_TDC) != 0U) {
+ if (i2cp->state == I2C_ACTIVE_TX) {
+ /* End of the transmit phase.*/
+
+#if AT32_I2C_USE_DMA == TRUE
+ /* Disabling TX DMA channel.*/
+ dmaStreamDisable(i2cp->dmatx);
+#endif
+
+ /* Starting receive phase if necessary.*/
+ if (i2c_lld_get_rxbytes(i2cp) > 0U) {
+ /* Setting up the peripheral.*/
+ i2c_lld_setup_rx_transfer(i2cp);
+
+#if AT32_I2C_USE_DMA == TRUE
+ /* Enabling RX DMA.*/
+ dmaStreamEnable(i2cp->dmarx);
+#else
+ /* RX interrupt enabled.*/
+ dp->CTRL1 |= I2C_CTRL1_RDIEN;
+#endif
+
+ /* Starts the read operation.*/
+ dp->CTRL2 |= I2C_CTRL2_GENSTART;
+
+ /* State change.*/
+ i2cp->state = I2C_ACTIVE_RX;
+
+ /* Note, returning because the transaction is not over yet.*/
+ return;
+ }
+ }
+ else {
+ /* End of the receive phase.*/
+#if AT32_I2C_USE_DMA == TRUE
+ /* Disabling RX DMA channel.*/
+ dmaStreamDisable(i2cp->dmarx);
+#endif
+ }
+
+ /* Transaction finished sending the STOP.*/
+ dp->CTRL2 |= I2C_CTRL2_GENSTOP;
+
+ /* Make sure no more 'Transfer Complete' interrupts.*/
+ dp->CTRL1 &= ~I2C_CTRL1_TDCIEN;
+
+ /* Normal transaction end.*/
+ _i2c_wakeup_isr(i2cp);
+ }
+}
+
+/**
+ * @brief I2C error handler.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ * @param[in] sts content of the STS register to be decoded
+ *
+ * @notapi
+ */
+static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp, uint32_t sts) {
+
+#if AT32_I2C_USE_DMA == TRUE
+ /* Clears DMA interrupt flags just to be safe.*/
+ dmaStreamDisable(i2cp->dmatx);
+ dmaStreamDisable(i2cp->dmarx);
+#else
+ /* Disabling RX and TX interrupts.*/
+ i2cp->i2c->CTRL1 &= ~(I2C_CTRL1_TDIEN | I2C_CTRL1_RDIEN);
+#endif
+
+ if (sts & I2C_STS_BUSERR)
+ i2cp->errors |= I2C_BUS_ERROR;
+
+ if (sts & I2C_STS_ARLOST)
+ i2cp->errors |= I2C_ARBITRATION_LOST;
+
+ if (sts & I2C_STS_OUF)
+ i2cp->errors |= I2C_OVERRUN;
+
+ if (sts & I2C_STS_TMOUT)
+ i2cp->errors |= I2C_TIMEOUT;
+
+ /* If some error has been identified then sends wakes the waiting thread.*/
+ if (i2cp->errors != I2C_NO_ERROR)
+ _i2c_wakeup_error_isr(i2cp);
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if AT32_I2C_USE_I2C1 || defined(__DOXYGEN__)
+#if defined(AT32_I2C1_GLOBAL_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief I2C1 event interrupt handler.
+ *
+ * @notapi
+ */
+OSAL_IRQ_HANDLER(AT32_I2C1_GLOBAL_HANDLER) {
+ uint32_t sts = I2CD1.i2c->STS;
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Clearing IRQ bits.*/
+ I2CD1.i2c->CLR = sts;
+
+ if (sts & I2C_ERROR_MASK)
+ i2c_lld_serve_error_interrupt(&I2CD1, sts);
+ else if (sts & I2C_INT_MASK)
+ i2c_lld_serve_interrupt(&I2CD1, sts);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+#elif defined(AT32_I2C1_EVENT_HANDLER) && defined(AT32_I2C1_ERROR_HANDLER)
+OSAL_IRQ_HANDLER(AT32_I2C1_EVENT_HANDLER) {
+ uint32_t sts = I2CD1.i2c->STS;
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Clearing IRQ bits.*/
+ I2CD1.i2c->CLR = sts & I2C_INT_MASK;
+
+ i2c_lld_serve_interrupt(&I2CD1, sts);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+OSAL_IRQ_HANDLER(AT32_I2C1_ERROR_HANDLER) {
+ uint32_t sts = I2CD1.i2c->STS;
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Clearing IRQ bits.*/
+ I2CD1.i2c->CLR = sts & I2C_ERROR_MASK;
+
+ i2c_lld_serve_error_interrupt(&I2CD1, sts);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+#else
+#error "I2C1 interrupt handlers not defined"
+#endif
+#endif /* AT32_I2C_USE_I2C1 */
+
+#if AT32_I2C_USE_I2C2 || defined(__DOXYGEN__)
+#if defined(AT32_I2C2_GLOBAL_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief I2C2 event interrupt handler.
+ *
+ * @notapi
+ */
+OSAL_IRQ_HANDLER(AT32_I2C2_GLOBAL_HANDLER) {
+ uint32_t sts = I2CD2.i2c->STS;
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Clearing IRQ bits.*/
+ I2CD2.i2c->CLR = sts;
+
+ if (sts & I2C_ERROR_MASK)
+ i2c_lld_serve_error_interrupt(&I2CD2, sts);
+ else if (sts & I2C_INT_MASK)
+ i2c_lld_serve_interrupt(&I2CD2, sts);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+#elif defined(AT32_I2C2_EVENT_HANDLER) && defined(AT32_I2C2_ERROR_HANDLER)
+OSAL_IRQ_HANDLER(AT32_I2C2_EVENT_HANDLER) {
+ uint32_t sts = I2CD2.i2c->STS;
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Clearing IRQ bits.*/
+ I2CD2.i2c->CLR = sts & I2C_INT_MASK;
+
+ i2c_lld_serve_interrupt(&I2CD2, sts);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+OSAL_IRQ_HANDLER(AT32_I2C2_ERROR_HANDLER) {
+ uint32_t sts = I2CD2.i2c->STS;
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Clearing IRQ bits.*/
+ I2CD2.i2c->CLR = sts & I2C_ERROR_MASK;
+
+ i2c_lld_serve_error_interrupt(&I2CD2, sts);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+#else
+#error "I2C2 interrupt handlers not defined"
+#endif
+#endif /* AT32_I2C_USE_I2C2 */
+
+#if AT32_I2C_USE_I2C3 || defined(__DOXYGEN__)
+#if defined(AT32_I2C3_GLOBAL_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief I2C3 event interrupt handler.
+ *
+ * @notapi
+ */
+OSAL_IRQ_HANDLER(AT32_I2C3_GLOBAL_HANDLER) {
+ uint32_t sts = I2CD3.i2c->STS;
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Clearing IRQ bits.*/
+ I2CD3.i2c->CLR = sts;
+
+ if (sts & I2C_ERROR_MASK)
+ i2c_lld_serve_error_interrupt(&I2CD3, sts);
+ else if (sts & I2C_INT_MASK)
+ i2c_lld_serve_interrupt(&I2CD3, sts);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+#elif defined(AT32_I2C3_EVENT_HANDLER) && defined(AT32_I2C3_ERROR_HANDLER)
+OSAL_IRQ_HANDLER(AT32_I2C3_EVENT_HANDLER) {
+ uint32_t sts = I2CD3.i2c->STS;
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Clearing IRQ bits.*/
+ I2CD3.i2c->CLR = sts & I2C_INT_MASK;
+
+ i2c_lld_serve_interrupt(&I2CD3, sts);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+OSAL_IRQ_HANDLER(AT32_I2C3_ERROR_HANDLER) {
+ uint32_t sts = I2CD3.i2c->STS;
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Clearing IRQ bits.*/
+ I2CD3.i2c->CLR = sts & I2C_ERROR_MASK;
+
+ i2c_lld_serve_error_interrupt(&I2CD3, sts);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+#else
+#error "I2C3 interrupt handlers not defined"
+#endif
+#endif /* AT32_I2C_USE_I2C3 */
+
+#if AT32_I2C_USE_I2C4 || defined(__DOXYGEN__)
+#if defined(AT32_I2C4_GLOBAL_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief I2C4 event interrupt handler.
+ *
+ * @notapi
+ */
+OSAL_IRQ_HANDLER(AT32_I2C4_GLOBAL_HANDLER) {
+ uint32_t sts = I2CD4.i2c->STS;
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Clearing IRQ bits.*/
+ I2CD4.i2c->CLR = sts;
+
+ if (sts & I2C_ERROR_MASK)
+ i2c_lld_serve_error_interrupt(&I2CD4, sts);
+ else if (sts & I2C_INT_MASK)
+ i2c_lld_serve_interrupt(&I2CD4, sts);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+#elif defined(AT32_I2C4_EVENT_HANDLER) && defined(AT32_I2C4_ERROR_HANDLER)
+OSAL_IRQ_HANDLER(AT32_I2C4_EVENT_HANDLER) {
+ uint32_t sts = I2CD4.i2c->STS;
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Clearing IRQ bits.*/
+ I2CD4.i2c->CLR = sts & I2C_INT_MASK;
+
+ i2c_lld_serve_interrupt(&I2CD4, sts);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+OSAL_IRQ_HANDLER(AT32_I2C4_ERROR_HANDLER) {
+ uint32_t sts = I2CD4.i2c->STS;
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Clearing IRQ bits.*/
+ I2CD4.i2c->CLR = sts & I2C_ERROR_MASK;
+
+ i2c_lld_serve_error_interrupt(&I2CD4, sts);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+#else
+#error "I2C4 interrupt handlers not defined"
+#endif
+#endif /* AT32_I2C_USE_I2C4 */
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level I2C driver initialization.
+ *
+ * @notapi
+ */
+void i2c_lld_init(void) {
+
+#if AT32_I2C_USE_I2C1
+ i2cObjectInit(&I2CD1);
+ I2CD1.thread = NULL;
+ I2CD1.i2c = I2C1;
+#if AT32_I2C_USE_DMA == TRUE
+ I2CD1.dmarx = NULL;
+ I2CD1.dmatx = NULL;
+#endif
+#endif /* AT32_I2C_USE_I2C1 */
+
+#if AT32_I2C_USE_I2C2
+ i2cObjectInit(&I2CD2);
+ I2CD2.thread = NULL;
+ I2CD2.i2c = I2C2;
+#if AT32_I2C_USE_DMA == TRUE
+ I2CD2.dmarx = NULL;
+ I2CD2.dmatx = NULL;
+#endif
+#endif /* AT32_I2C_USE_I2C2 */
+
+#if AT32_I2C_USE_I2C3
+ i2cObjectInit(&I2CD3);
+ I2CD3.thread = NULL;
+ I2CD3.i2c = I2C3;
+#if AT32_I2C_USE_DMA == TRUE
+ I2CD3.dmarx = NULL;
+ I2CD3.dmatx = NULL;
+#endif
+#endif /* AT32_I2C_USE_I2C3 */
+
+#if AT32_I2C_USE_I2C4
+ i2cObjectInit(&I2CD4);
+ I2CD4.thread = NULL;
+ I2CD4.i2c = I2C4;
+#if AT32_I2C_USE_DMA == TRUE
+ I2CD4.dmarx = NULL;
+ I2CD4.dmatx = NULL;
+#endif
+#endif /* AT32_I2C_USE_I2C4 */
+}
+
+/**
+ * @brief Configures and activates the I2C peripheral.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+void i2c_lld_start(I2CDriver *i2cp) {
+ I2C_TypeDef *dp = i2cp->i2c;
+
+ /* Make sure I2C peripheral is disabled */
+ dp->CTRL1 &= ~I2C_CTRL1_I2CEN;
+
+ /* If in stopped state then enables the I2C and DMA clocks.*/
+ if (i2cp->state == I2C_STOP) {
+
+#if AT32_I2C_USE_DMA == TRUE
+ /* Common DMA modes.*/
+ i2cp->txdmamode = DMAMODE_COMMON | AT32_DMA_CTRL_DTD_M2P;
+ i2cp->rxdmamode = DMAMODE_COMMON | AT32_DMA_CTRL_DTD_P2M;
+#endif
+
+#if AT32_I2C_USE_I2C1
+ if (&I2CD1 == i2cp) {
+
+ crmResetI2C1();
+ crmEnableI2C1(true);
+#if AT32_I2C_USE_DMA == TRUE
+ {
+ i2cp->dmarx = dmaStreamAllocI(AT32_I2C_I2C1_RX_DMA_STREAM,
+ AT32_I2C_I2C1_IRQ_PRIORITY,
+ NULL,
+ (void *)i2cp);
+ osalDbgAssert(i2cp->dmarx != NULL, "unable to allocate stream");
+ i2cp->dmatx = dmaStreamAllocI(AT32_I2C_I2C1_TX_DMA_STREAM,
+ AT32_I2C_I2C1_IRQ_PRIORITY,
+ NULL,
+ (void *)i2cp);
+ osalDbgAssert(i2cp->dmatx != NULL, "unable to allocate stream");
+
+ i2cp->rxdmamode |= AT32_DMA_CTRL_CHSEL(I2C1_RX_DMA_CHANNEL) |
+ AT32_DMA_CTRL_CHPL(AT32_I2C_I2C1_DMA_PRIORITY);
+ i2cp->txdmamode |= AT32_DMA_CTRL_CHSEL(I2C1_TX_DMA_CHANNEL) |
+ AT32_DMA_CTRL_CHPL(AT32_I2C_I2C1_DMA_PRIORITY);
+#if AT32_DMA_SUPPORTS_DMAMUX
+#if AT32_USE_DMA_V1 && AT32_DMA_USE_DMAMUX
+ dmaSetRequestSource(i2cp->dmarx, AT32_I2C_I2C1_RX_DMAMUX_CHANNEL, AT32_DMAMUX_I2C1_RX);
+ dmaSetRequestSource(i2cp->dmatx, AT32_I2C_I2C1_TX_DMAMUX_CHANNEL, AT32_DMAMUX_I2C1_TX);
+#elif AT32_USE_DMA_V2 || AT32_USE_DMA_V3
+ dmaSetRequestSource(i2cp->dmarx, AT32_DMAMUX_I2C1_RX);
+ dmaSetRequestSource(i2cp->dmatx, AT32_DMAMUX_I2C1_TX);
+#endif
+#endif
+ }
+#endif /* AT32_I2C_USE_DMA == TRUE */
+
+#if defined(AT32_I2C1_GLOBAL_NUMBER) || defined(__DOXYGEN__)
+ nvicEnableVector(AT32_I2C1_GLOBAL_NUMBER, AT32_I2C_I2C1_IRQ_PRIORITY);
+#elif defined(AT32_I2C1_EVENT_NUMBER) && defined(AT32_I2C1_ERROR_NUMBER)
+ nvicEnableVector(AT32_I2C1_EVENT_NUMBER, AT32_I2C_I2C1_IRQ_PRIORITY);
+ nvicEnableVector(AT32_I2C1_ERROR_NUMBER, AT32_I2C_I2C1_IRQ_PRIORITY);
+#else
+#error "I2C1 interrupt numbers not defined"
+#endif
+ }
+#endif /* AT32_I2C_USE_I2C1 */
+
+#if AT32_I2C_USE_I2C2
+ if (&I2CD2 == i2cp) {
+
+ crmResetI2C2();
+ crmEnableI2C2(true);
+#if AT32_I2C_USE_DMA == TRUE
+ {
+ i2cp->dmarx = dmaStreamAllocI(AT32_I2C_I2C2_RX_DMA_STREAM,
+ AT32_I2C_I2C2_IRQ_PRIORITY,
+ NULL,
+ (void *)i2cp);
+ osalDbgAssert(i2cp->dmarx != NULL, "unable to allocate stream");
+ i2cp->dmatx = dmaStreamAllocI(AT32_I2C_I2C2_TX_DMA_STREAM,
+ AT32_I2C_I2C2_IRQ_PRIORITY,
+ NULL,
+ (void *)i2cp);
+ osalDbgAssert(i2cp->dmatx != NULL, "unable to allocate stream");
+
+ i2cp->rxdmamode |= AT32_DMA_CTRL_CHSEL(I2C2_RX_DMA_CHANNEL) |
+ AT32_DMA_CTRL_CHPL(AT32_I2C_I2C2_DMA_PRIORITY);
+ i2cp->txdmamode |= AT32_DMA_CTRL_CHSEL(I2C2_TX_DMA_CHANNEL) |
+ AT32_DMA_CTRL_CHPL(AT32_I2C_I2C2_DMA_PRIORITY);
+#if AT32_DMA_SUPPORTS_DMAMUX
+#if AT32_USE_DMA_V1 && AT32_DMA_USE_DMAMUX
+ dmaSetRequestSource(i2cp->dmarx, AT32_I2C_I2C2_RX_DMAMUX_CHANNEL, AT32_DMAMUX_I2C2_RX);
+ dmaSetRequestSource(i2cp->dmatx, AT32_I2C_I2C2_TX_DMAMUX_CHANNEL, AT32_DMAMUX_I2C2_TX);
+#elif AT32_USE_DMA_V2 || AT32_USE_DMA_V3
+ dmaSetRequestSource(i2cp->dmarx, AT32_DMAMUX_I2C2_RX);
+ dmaSetRequestSource(i2cp->dmatx, AT32_DMAMUX_I2C2_TX);
+#endif
+#endif
+ }
+#endif /* AT32_I2C_USE_DMA == TRUE */
+
+#if defined(AT32_I2C2_GLOBAL_NUMBER) || defined(__DOXYGEN__)
+ nvicEnableVector(AT32_I2C2_GLOBAL_NUMBER, AT32_I2C_I2C2_IRQ_PRIORITY);
+#elif defined(AT32_I2C2_EVENT_NUMBER) && defined(AT32_I2C2_ERROR_NUMBER)
+ nvicEnableVector(AT32_I2C2_EVENT_NUMBER, AT32_I2C_I2C2_IRQ_PRIORITY);
+ nvicEnableVector(AT32_I2C2_ERROR_NUMBER, AT32_I2C_I2C2_IRQ_PRIORITY);
+#else
+#error "I2C2 interrupt numbers not defined"
+#endif
+ }
+#endif /* AT32_I2C_USE_I2C2 */
+
+#if AT32_I2C_USE_I2C3
+ if (&I2CD3 == i2cp) {
+
+ crmResetI2C3();
+ crmEnableI2C3(true);
+#if AT32_I2C_USE_DMA == TRUE
+ {
+ i2cp->dmarx = dmaStreamAllocI(AT32_I2C_I2C3_RX_DMA_STREAM,
+ AT32_I2C_I2C3_IRQ_PRIORITY,
+ NULL,
+ (void *)i2cp);
+ osalDbgAssert(i2cp->dmarx != NULL, "unable to allocate stream");
+ i2cp->dmatx = dmaStreamAllocI(AT32_I2C_I2C3_TX_DMA_STREAM,
+ AT32_I2C_I2C3_IRQ_PRIORITY,
+ NULL,
+ (void *)i2cp);
+ osalDbgAssert(i2cp->dmatx != NULL, "unable to allocate stream");
+
+ i2cp->rxdmamode |= AT32_DMA_CTRL_CHSEL(I2C3_RX_DMA_CHANNEL) |
+ AT32_DMA_CTRL_CHPL(AT32_I2C_I2C3_DMA_PRIORITY);
+ i2cp->txdmamode |= AT32_DMA_CTRL_CHSEL(I2C3_TX_DMA_CHANNEL) |
+ AT32_DMA_CTRL_CHPL(AT32_I2C_I2C3_DMA_PRIORITY);
+#if AT32_DMA_SUPPORTS_DMAMUX
+#if AT32_USE_DMA_V1 && AT32_DMA_USE_DMAMUX
+ dmaSetRequestSource(i2cp->dmarx, AT32_I2C_I2C3_RX_DMAMUX_CHANNEL, AT32_DMAMUX_I2C3_RX);
+ dmaSetRequestSource(i2cp->dmatx, AT32_I2C_I2C3_TX_DMAMUX_CHANNEL, AT32_DMAMUX_I2C3_TX);
+#elif AT32_USE_DMA_V2 || AT32_USE_DMA_V3
+ dmaSetRequestSource(i2cp->dmarx, AT32_DMAMUX_I2C3_RX);
+ dmaSetRequestSource(i2cp->dmatx, AT32_DMAMUX_I2C3_TX);
+#endif
+#endif
+ }
+#endif /* AT32_I2C_USE_DMA == TRUE */
+
+#if defined(AT32_I2C3_GLOBAL_NUMBER) || defined(__DOXYGEN__)
+ nvicEnableVector(AT32_I2C3_GLOBAL_NUMBER, AT32_I2C_I2C3_IRQ_PRIORITY);
+#elif defined(AT32_I2C3_EVENT_NUMBER) && defined(AT32_I2C3_ERROR_NUMBER)
+ nvicEnableVector(AT32_I2C3_EVENT_NUMBER, AT32_I2C_I2C3_IRQ_PRIORITY);
+ nvicEnableVector(AT32_I2C3_ERROR_NUMBER, AT32_I2C_I2C3_IRQ_PRIORITY);
+#else
+#error "I2C3 interrupt numbers not defined"
+#endif
+ }
+#endif /* AT32_I2C_USE_I2C3 */
+
+#if AT32_I2C_USE_I2C4
+ if (&I2CD4 == i2cp) {
+
+ crmResetI2C4();
+ crmEnableI2C4(true);
+#if AT32_I2C_USE_DMA == TRUE
+ {
+ i2cp->dmarx = dmaStreamAllocI(AT32_I2C_I2C4_RX_DMA_STREAM,
+ AT32_I2C_I2C4_IRQ_PRIORITY,
+ NULL,
+ (void *)i2cp);
+ osalDbgAssert(i2cp->dmarx != NULL, "unable to allocate stream");
+ i2cp->dmatx = dmaStreamAllocI(AT32_I2C_I2C4_TX_DMA_STREAM,
+ AT32_I2C_I2C4_IRQ_PRIORITY,
+ NULL,
+ (void *)i2cp);
+ osalDbgAssert(i2cp->dmatx != NULL, "unable to allocate stream");
+
+ i2cp->rxdmamode |= AT32_DMA_CTRL_CHSEL(I2C4_RX_DMA_CHANNEL) |
+ AT32_DMA_CTRL_CHPL(AT32_I2C_I2C4_DMA_PRIORITY);
+ i2cp->txdmamode |= AT32_DMA_CTRL_CHSEL(I2C4_TX_DMA_CHANNEL) |
+ AT32_DMA_CTRL_CHPL(AT32_I2C_I2C4_DMA_PRIORITY);
+#if AT32_DMA_SUPPORTS_DMAMUX
+#if AT32_USE_DMA_V1 && AT32_DMA_USE_DMAMUX
+ dmaSetRequestSource(i2cp->dmarx, AT32_I2C_I2C4_RX_DMAMUX_CHANNEL, AT32_DMAMUX_I2C4_RX);
+ dmaSetRequestSource(i2cp->dmatx, AT32_I2C_I2C4_TX_DMAMUX_CHANNEL, AT32_DMAMUX_I2C4_TX);
+#elif AT32_USE_DMA_V2 || AT32_USE_DMA_V3
+ dmaSetRequestSource(i2cp->dmarx, AT32_DMAMUX_I2C4_RX);
+ dmaSetRequestSource(i2cp->dmatx, AT32_DMAMUX_I2C4_TX);
+#endif
+#endif
+ }
+#endif /* AT32_I2C_USE_DMA == TRUE */
+
+#if defined(AT32_I2C4_GLOBAL_NUMBER) || defined(__DOXYGEN__)
+ nvicEnableVector(AT32_I2C4_GLOBAL_NUMBER, AT32_I2C_I2C4_IRQ_PRIORITY);
+#elif defined(AT32_I2C4_EVENT_NUMBER) && defined(AT32_I2C4_ERROR_NUMBER)
+ nvicEnableVector(AT32_I2C4_EVENT_NUMBER, AT32_I2C_I2C4_IRQ_PRIORITY);
+ nvicEnableVector(AT32_I2C4_ERROR_NUMBER, AT32_I2C_I2C4_IRQ_PRIORITY);
+#else
+#error "I2C4 interrupt numbers not defined"
+#endif
+ }
+#endif /* AT32_I2C_USE_I2C4 */
+ }
+
+#if AT32_I2C_USE_DMA == TRUE
+ /* I2C registers pointed by the DMA.*/
+ dmaStreamSetPeripheral(i2cp->dmarx, &dp->RXDT);
+ dmaStreamSetPeripheral(i2cp->dmatx, &dp->TXDT);
+#endif
+
+ /* Reset i2c peripheral, the TCIE bit will be handled separately.*/
+ dp->CTRL1 = i2cp->config->ctrl1 |
+#if AT32_I2C_USE_DMA == TRUE
+ I2C_CTRL1_DMATEN | I2C_CTRL1_DMAREN | /* Enable only if using DMA */
+#endif
+ I2C_CTRL1_ERRIEN | I2C_CTRL1_ACKFAILIEN;
+
+ /* Setup I2C parameters.*/
+ dp->CLKCTRL = i2cp->config->clkctrl;
+
+ /* Ready to go.*/
+ dp->CTRL1 |= I2C_CTRL1_I2CEN;
+}
+
+/**
+ * @brief Deactivates the I2C peripheral.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+void i2c_lld_stop(I2CDriver *i2cp) {
+
+ /* If not in stopped state then disables the I2C clock.*/
+ if (i2cp->state != I2C_STOP) {
+
+ /* I2C disable.*/
+ i2c_lld_abort_operation(i2cp);
+#if AT32_I2C_USE_DMA == TRUE
+ dmaStreamFreeI(i2cp->dmatx);
+ dmaStreamFreeI(i2cp->dmarx);
+ i2cp->dmatx = NULL;
+ i2cp->dmarx = NULL;
+#endif
+
+#if AT32_I2C_USE_I2C1
+ if (&I2CD1 == i2cp) {
+#if defined(AT32_I2C1_GLOBAL_NUMBER) || defined(__DOXYGEN__)
+ nvicDisableVector(AT32_I2C1_GLOBAL_NUMBER);
+#elif defined(AT32_I2C1_EVENT_NUMBER) && defined(AT32_I2C1_ERROR_NUMBER)
+ nvicDisableVector(AT32_I2C1_EVENT_NUMBER);
+ nvicDisableVector(AT32_I2C1_ERROR_NUMBER);
+#else
+#error "I2C1 interrupt numbers not defined"
+#endif
+
+ crmDisableI2C1();
+ }
+#endif
+
+#if AT32_I2C_USE_I2C2
+ if (&I2CD2 == i2cp) {
+#if defined(AT32_I2C2_GLOBAL_NUMBER) || defined(__DOXYGEN__)
+ nvicDisableVector(AT32_I2C2_GLOBAL_NUMBER);
+#elif defined(AT32_I2C2_EVENT_NUMBER) && defined(AT32_I2C2_ERROR_NUMBER)
+ nvicDisableVector(AT32_I2C2_EVENT_NUMBER);
+ nvicDisableVector(AT32_I2C2_ERROR_NUMBER);
+#else
+#error "I2C2 interrupt numbers not defined"
+#endif
+
+ crmDisableI2C2();
+ }
+#endif
+
+#if AT32_I2C_USE_I2C3
+ if (&I2CD3 == i2cp) {
+#if defined(AT32_I2C3_GLOBAL_NUMBER) || defined(__DOXYGEN__)
+ nvicDisableVector(AT32_I2C3_GLOBAL_NUMBER);
+#elif defined(AT32_I2C3_EVENT_NUMBER) && defined(AT32_I2C3_ERROR_NUMBER)
+ nvicDisableVector(AT32_I2C3_EVENT_NUMBER);
+ nvicDisableVector(AT32_I2C3_ERROR_NUMBER);
+#else
+#error "I2C3 interrupt numbers not defined"
+#endif
+
+ crmDisableI2C3();
+ }
+#endif
+
+#if AT32_I2C_USE_I2C4
+ if (&I2CD4 == i2cp) {
+#if defined(AT32_I2C4_GLOBAL_NUMBER) || defined(__DOXYGEN__)
+ nvicDisableVector(AT32_I2C4_GLOBAL_NUMBER);
+#elif defined(AT32_I2C4_EVENT_NUMBER) && defined(AT32_I2C4_ERROR_NUMBER)
+ nvicDisableVector(AT32_I2C4_EVENT_NUMBER);
+ nvicDisableVector(AT32_I2C4_ERROR_NUMBER);
+#else
+#error "I2C4 interrupt numbers not defined"
+#endif
+
+ crmDisableI2C4();
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Receives data via the I2C bus as master.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ * @param[in] addr slave device address
+ * @param[out] rxbuf pointer to the receive buffer
+ * @param[in] rxbytes number of bytes to be received
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a
+ * timeout the driver must be stopped and restarted
+ * because the bus is in an uncertain state.
+ *
+ * @notapi
+ */
+msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
+ uint8_t *rxbuf, size_t rxbytes,
+ sysinterval_t timeout) {
+ msg_t msg;
+ I2C_TypeDef *dp = i2cp->i2c;
+ systime_t start, end;
+
+ /* Resetting error flags for this transfer.*/
+ i2cp->errors = I2C_NO_ERROR;
+
+ /* Releases the lock from high level driver.*/
+ osalSysUnlock();
+
+#if AT32_I2C_USE_DMA == TRUE
+ /* RX DMA setup.*/
+ dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
+ dmaStreamSetMemory0(i2cp->dmarx, rxbuf);
+ dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes);
+#else
+ i2cp->rxptr = rxbuf;
+ i2cp->rxbytes = rxbytes;
+#endif
+
+ /* Calculating the time window for the timeout on the busy bus condition.*/
+ start = osalOsGetSystemTimeX();
+ end = osalTimeAddX(start, OSAL_MS2I(AT32_I2C_BUSY_TIMEOUT));
+
+ /* Waits until BUSY flag is reset or, alternatively, for a timeout
+ condition.*/
+ while (true) {
+ osalSysLock();
+
+ /* If the bus is not busy then the operation can continue, note, the
+ loop is exited in the locked state.*/
+ if ((dp->STS & I2C_STS_BUSYF) == 0)
+ break;
+
+ /* If the system time went outside the allowed window then a timeout
+ condition is returned.*/
+ if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) {
+ return MSG_TIMEOUT;
+ }
+
+ osalSysUnlock();
+ }
+
+ /* Setting up the slave address.*/
+ i2c_lld_set_address(i2cp, addr);
+
+ /* Setting up the peripheral.*/
+ i2c_lld_setup_rx_transfer(i2cp);
+
+#if AT32_I2C_USE_DMA == TRUE
+ /* Enabling RX DMA.*/
+ dmaStreamEnable(i2cp->dmarx);
+
+ /* Transfer complete interrupt enabled.*/
+ dp->CTRL1 |= I2C_CTRL1_TDCIEN;
+#else
+
+ /* Transfer complete and RX interrupts enabled.*/
+ dp->CTRL1 |= I2C_CTRL1_TDCIEN | I2C_CTRL1_RDIEN;
+#endif
+
+ /* Starts the operation.*/
+ dp->CTRL2 |= I2C_CTRL2_GENSTART;
+
+ /* Waits for the operation completion or a timeout.*/
+ msg = osalThreadSuspendTimeoutS(&i2cp->thread, timeout);
+
+ /* In case of a software timeout a STOP is sent as an extreme attempt
+ to release the bus and DMA is forcibly disabled.*/
+ if (msg == MSG_TIMEOUT) {
+ dp->CTRL2 |= I2C_CTRL2_GENSTOP;
+#if AT32_I2C_USE_DMA == TRUE
+ dmaStreamDisable(i2cp->dmarx);
+#endif
+ }
+
+ return msg;
+}
+
+/**
+ * @brief Transmits data via the I2C bus as master.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ * @param[in] addr slave device address
+ * @param[in] txbuf pointer to the transmit buffer
+ * @param[in] txbytes number of bytes to be transmitted
+ * @param[out] rxbuf pointer to the receive buffer
+ * @param[in] rxbytes number of bytes to be received
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a
+ * timeout the driver must be stopped and restarted
+ * because the bus is in an uncertain state.
+ *
+ * @notapi
+ */
+msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
+ const uint8_t *txbuf, size_t txbytes,
+ uint8_t *rxbuf, size_t rxbytes,
+ sysinterval_t timeout) {
+ msg_t msg;
+ I2C_TypeDef *dp = i2cp->i2c;
+ systime_t start, end;
+
+ /* Resetting error flags for this transfer.*/
+ i2cp->errors = I2C_NO_ERROR;
+
+ /* Releases the lock from high level driver.*/
+ osalSysUnlock();
+
+#if AT32_I2C_USE_DMA == TRUE
+ /* TX DMA setup.*/
+ dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode);
+ dmaStreamSetMemory0(i2cp->dmatx, txbuf);
+ dmaStreamSetTransactionSize(i2cp->dmatx, txbytes);
+
+ /* RX DMA setup, note, rxbytes can be zero but we write the value anyway.*/
+ dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
+ dmaStreamSetMemory0(i2cp->dmarx, rxbuf);
+ dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes);
+#else
+ i2cp->txptr = txbuf;
+ i2cp->txbytes = txbytes;
+ i2cp->rxptr = rxbuf;
+ i2cp->rxbytes = rxbytes;
+#endif
+
+ /* Calculating the time window for the timeout on the busy bus condition.*/
+ start = osalOsGetSystemTimeX();
+ end = osalTimeAddX(start, OSAL_MS2I(AT32_I2C_BUSY_TIMEOUT));
+
+ /* Waits until BUSY flag is reset or, alternatively, for a timeout
+ condition.*/
+ while (true) {
+ osalSysLock();
+
+ /* If the bus is not busy then the operation can continue, note, the
+ loop is exited in the locked state.*/
+ if ((dp->STS & I2C_STS_BUSYF) == 0)
+ break;
+
+ /* If the system time went outside the allowed window then a timeout
+ condition is returned.*/
+ if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) {
+ return MSG_TIMEOUT;
+ }
+
+ osalSysUnlock();
+ }
+
+ /* Setting up the slave address.*/
+ i2c_lld_set_address(i2cp, addr);
+
+ /* Preparing the transfer.*/
+ i2c_lld_setup_tx_transfer(i2cp);
+
+#if AT32_I2C_USE_DMA == TRUE
+ /* Enabling TX DMA.*/
+ dmaStreamEnable(i2cp->dmatx);
+
+ /* Transfer complete interrupt enabled.*/
+ dp->CTRL1 |= I2C_CTRL1_TDCIEN;
+#else
+ /* Transfer complete and TX interrupts enabled.*/
+ dp->CTRL1 |= I2C_CTRL1_TDCIEN | I2C_CTRL1_TDIEN;
+#endif
+
+ /* Starts the operation.*/
+ dp->CTRL2 |= I2C_CTRL2_GENSTART;
+
+ /* Waits for the operation completion or a timeout.*/
+ msg = osalThreadSuspendTimeoutS(&i2cp->thread, timeout);
+
+ /* In case of a software timeout a STOP is sent as an extreme attempt
+ to release the bus and DMA is forcibly disabled.*/
+ if (msg == MSG_TIMEOUT) {
+ dp->CTRL2 |= I2C_CTRL2_GENSTOP;
+#if AT32_I2C_USE_DMA == TRUE
+ dmaStreamDisable(i2cp->dmarx);
+ dmaStreamDisable(i2cp->dmatx);
+#endif
+ }
+
+ return msg;
+}
+
+#endif /* HAL_USE_I2C */
+
+/** @} */
diff --git a/os/hal/ports/AT32/LLD/I2Cv2/hal_i2c_lld.h b/os/hal/ports/AT32/LLD/I2Cv2/hal_i2c_lld.h
new file mode 100644
index 0000000000..f6d22314fc
--- /dev/null
+++ b/os/hal/ports/AT32/LLD/I2Cv2/hal_i2c_lld.h
@@ -0,0 +1,525 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+ ChibiOS - Copyright (C) 2023..2024 Maxjta
+
+ Licensed 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.
+*/
+/*
+ Concepts and parts of this file have been contributed by Uladzimir Pylinsky
+ aka barthess.
+ */
+
+/**
+ * @file I2Cv2/hal_i2c_lld.h
+ * @brief AT32 I2C subsystem low level driver header.
+ *
+ * @addtogroup I2C
+ * @{
+ */
+
+#ifndef HAL_I2C_LLD_H
+#define HAL_I2C_LLD_H
+
+#if HAL_USE_I2C || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name CLKCTRL register definitions
+ * @{
+ */
+#define AT32_CLKCTRL_DIVL_MASK (15U << 28)
+#define AT32_CLKCTRL_DIVL(n) ((n) << 28)
+#define AT32_CLKCTRL_DIVH_MASK (15U << 24)
+#define AT32_CLKCTRL_DIVH(n) ((n) << 24)
+#define AT32_CLKCTRL_SCLD_MASK (15U << 20)
+#define AT32_CLKCTRL_SCLD(n) ((n) << 20)
+#define AT32_CLKCTRL_SDAD_MASK (15U << 16)
+#define AT32_CLKCTRL_SDAD(n) ((n) << 16)
+#define AT32_CLKCTRL_SCLH_MASK (255U << 8)
+#define AT32_CLKCTRL_SCLH(n) ((n) << 8)
+#define AT32_CLKCTRL_SCLL_MASK (255U << 0)
+#define AT32_CLKCTRL_SCLL(n) ((n) << 0)
+
+
+/* Same as stm32 */
+#define STM32_TIMINGR_PRESC_MASK (AT32_CLKCTRL_DIVH_MASK | AT32_CLKCTRL_DIVL_MASK)
+#define STM32_TIMINGR_PRESC(n) (AT32_CLKCTRL_DIVL(n&0xF) | AT32_CLKCTRL_DIVH((n>>4)&0xF))
+#define STM32_TIMINGR_SCLDEL_MASK AT32_CLKCTRL_SCLD_MASK
+#define STM32_TIMINGR_SCLDEL(n) AT32_CLKCTRL_SCLD(n)
+#define STM32_TIMINGR_SDADEL_MASK AT32_CLKCTRL_SDAD_MASK
+#define STM32_TIMINGR_SDADEL(n) AT32_CLKCTRL_SDAD(n)
+#define STM32_TIMINGR_SCLH_MASK AT32_CLKCTRL_SCLH_MASK
+#define STM32_TIMINGR_SCLH(n) AT32_CLKCTRL_SCLH(n)
+#define STM32_TIMINGR_SCLL_MASK AT32_CLKCTRL_SCLL_MASK
+#define STM32_TIMINGR_SCLL(n) AT32_CLKCTRL_SCLL(n)
+
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief I2C1 driver enable switch.
+ * @details If set to @p TRUE the support for I2C1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(AT32_I2C_USE_I2C1) || defined(__DOXYGEN__)
+#define AT32_I2C_USE_I2C1 FALSE
+#endif
+
+/**
+ * @brief I2C2 driver enable switch.
+ * @details If set to @p TRUE the support for I2C2 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(AT32_I2C_USE_I2C2) || defined(__DOXYGEN__)
+#define AT32_I2C_USE_I2C2 FALSE
+#endif
+
+/**
+ * @brief I2C3 driver enable switch.
+ * @details If set to @p TRUE the support for I2C3 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(AT32_I2C_USE_I2C3) || defined(__DOXYGEN__)
+#define AT32_I2C_USE_I2C3 FALSE
+#endif
+
+/**
+ * @brief I2C4 driver enable switch.
+ * @details If set to @p TRUE the support for I2C4 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(AT32_I2C_USE_I2C4) || defined(__DOXYGEN__)
+#define AT32_I2C_USE_I2C4 FALSE
+#endif
+
+/**
+ * @brief I2C timeout on busy condition in milliseconds.
+ */
+#if !defined(AT32_I2C_BUSY_TIMEOUT) || defined(__DOXYGEN__)
+#define AT32_I2C_BUSY_TIMEOUT 50
+#endif
+
+/**
+ * @brief I2C1 interrupt priority level setting.
+ */
+#if !defined(AT32_I2C_I2C1_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_I2C_I2C1_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief I2C2 interrupt priority level setting.
+ */
+#if !defined(AT32_I2C_I2C2_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_I2C_I2C2_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief I2C3 interrupt priority level setting.
+ */
+#if !defined(AT32_I2C_I2C3_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_I2C_I2C3_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief I2C4 interrupt priority level setting.
+ */
+#if !defined(AT32_I2C_I2C4_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_I2C_I2C4_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief DMA use switch.
+ */
+#if !defined(AT32_I2C_USE_DMA) || defined(__DOXYGEN__)
+#define AT32_I2C_USE_DMA TRUE
+#endif
+
+/**
+ * @brief I2C1 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA streams but
+ * because of the streams ordering the RX stream has always priority
+ * over the TX stream.
+ */
+#if !defined(AT32_I2C_I2C1_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_I2C_I2C1_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief I2C2 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA streams but
+ * because of the streams ordering the RX stream has always priority
+ * over the TX stream.
+ */
+#if !defined(AT32_I2C_I2C2_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_I2C_I2C2_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief I2C3 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA streams but
+ * because of the streams ordering the RX stream has always priority
+ * over the TX stream.
+ */
+#if !defined(AT32_I2C_I2C3_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_I2C_I2C3_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief I2C4 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA streams but
+ * because of the streams ordering the RX stream has always priority
+ * over the TX stream.
+ */
+#if !defined(AT32_I2C_I2C4_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_I2C_I2C4_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief I2C DMA error hook.
+ * @note The default action for DMA errors is a system halt because DMA
+ * error can only happen because programming errors.
+ */
+#if !defined(AT32_I2C_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
+#define AT32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure")
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/** @brief error checks */
+#if AT32_I2C_USE_I2C1 && !AT32_HAS_I2C1
+#error "I2C1 not present in the selected device"
+#endif
+
+#if AT32_I2C_USE_I2C2 && !AT32_HAS_I2C2
+#error "I2C2 not present in the selected device"
+#endif
+
+#if AT32_I2C_USE_I2C3 && !AT32_HAS_I2C3
+#error "I2C3 not present in the selected device"
+#endif
+
+#if AT32_I2C_USE_I2C4 && !AT32_HAS_I2C4
+#error "I2C4 not present in the selected device"
+#endif
+
+#if !AT32_I2C_USE_I2C1 && !AT32_I2C_USE_I2C2 && !AT32_I2C_USE_I2C3 && \
+ !AT32_I2C_USE_I2C4
+#error "I2C driver activated but no I2C peripheral assigned"
+#endif
+
+#if AT32_I2C_USE_I2C1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(AT32_I2C_I2C1_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to I2C1"
+#endif
+
+#if AT32_I2C_USE_I2C2 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(AT32_I2C_I2C2_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to I2C2"
+#endif
+
+#if AT32_I2C_USE_I2C3 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(AT32_I2C_I2C3_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to I2C3"
+#endif
+
+#if AT32_I2C_USE_I2C4 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(AT32_I2C_I2C4_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to I2C4"
+#endif
+
+#if AT32_I2C_USE_DMA == TRUE
+#if AT32_I2C_USE_I2C1 && \
+ !AT32_DMA_IS_VALID_PRIORITY(AT32_I2C_I2C1_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to I2C1"
+#endif
+
+#if AT32_I2C_USE_I2C2 && \
+ !AT32_DMA_IS_VALID_PRIORITY(AT32_I2C_I2C2_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to I2C2"
+#endif
+
+#if AT32_I2C_USE_I2C3 && \
+ !AT32_DMA_IS_VALID_PRIORITY(AT32_I2C_I2C3_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to I2C3"
+#endif
+
+#if AT32_I2C_USE_I2C4 && \
+ !AT32_DMA_IS_VALID_PRIORITY(AT32_I2C_I2C4_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to I2C4"
+#endif
+#if 0
+/* Check on the presence of the DMA streams settings in mcuconf.h.*/
+#if AT32_I2C_USE_I2C1 && (!defined(AT32_I2C_I2C1_RX_DMA_STREAM) || \
+ !defined(AT32_I2C_I2C1_TX_DMA_STREAM))
+#error "I2C1 DMA streams not defined"
+#endif
+
+#if AT32_I2C_USE_I2C2 && (!defined(AT32_I2C_I2C2_RX_DMA_STREAM) || \
+ !defined(AT32_I2C_I2C2_TX_DMA_STREAM))
+#error "I2C2 DMA streams not defined"
+#endif
+
+#if AT32_I2C_USE_I2C3 && (!defined(AT32_I2C_I2C3_RX_DMA_STREAM) || \
+ !defined(AT32_I2C_I2C3_TX_DMA_STREAM))
+#error "I2C3 DMA streams not defined"
+#endif
+
+#if AT32_I2C_USE_I2C4 && (!defined(AT32_I2C_I2C4_RX_DMA_STREAM) || \
+ !defined(AT32_I2C_I2C4_TX_DMA_STREAM))
+#error "I2C4 DMA streams not defined"
+#endif
+#endif
+/* Devices without DMAMUX require an additional check.*/
+#if !AT32_DMA_SUPPORTS_DMAMUX
+
+/* Check on the validity of the assigned DMA channels.*/
+#if AT32_I2C_USE_I2C1 && \
+ !AT32_DMA_IS_VALID_ID(AT32_I2C_I2C1_RX_DMA_STREAM, \
+ AT32_I2C1_RX_DMA_MSK)
+#error "invalid DMA stream associated to I2C1 RX"
+#endif
+
+#if AT32_I2C_USE_I2C1 && \
+ !AT32_DMA_IS_VALID_ID(AT32_I2C_I2C1_TX_DMA_STREAM, \
+ AT32_I2C1_TX_DMA_MSK)
+#error "invalid DMA stream associated to I2C1 TX"
+#endif
+
+#if AT32_I2C_USE_I2C2 && \
+ !AT32_DMA_IS_VALID_ID(AT32_I2C_I2C2_RX_DMA_STREAM, \
+ AT32_I2C2_RX_DMA_MSK)
+#error "invalid DMA stream associated to I2C2 RX"
+#endif
+
+#if AT32_I2C_USE_I2C2 && \
+ !AT32_DMA_IS_VALID_ID(AT32_I2C_I2C2_TX_DMA_STREAM, \
+ AT32_I2C2_TX_DMA_MSK)
+#error "invalid DMA stream associated to I2C2 TX"
+#endif
+
+#if AT32_I2C_USE_I2C3 && \
+ !AT32_DMA_IS_VALID_ID(AT32_I2C_I2C3_RX_DMA_STREAM, \
+ AT32_I2C3_RX_DMA_MSK)
+#error "invalid DMA stream associated to I2C3 RX"
+#endif
+
+#if AT32_I2C_USE_I2C3 && \
+ !AT32_DMA_IS_VALID_ID(AT32_I2C_I2C3_TX_DMA_STREAM, \
+ AT32_I2C3_TX_DMA_MSK)
+#error "invalid DMA stream associated to I2C3 TX"
+#endif
+
+#if AT32_I2C_USE_I2C4 && \
+ !AT32_DMA_IS_VALID_ID(AT32_I2C_I2C4_RX_DMA_STREAM, \
+ AT32_I2C4_RX_DMA_MSK)
+#error "invalid DMA stream associated to I2C4 RX"
+#endif
+
+#if AT32_I2C_USE_I2C4 && \
+ !AT32_DMA_IS_VALID_ID(AT32_I2C_I2C4_TX_DMA_STREAM, \
+ AT32_I2C4_TX_DMA_MSK)
+#error "invalid DMA stream associated to I2C4 TX"
+#endif
+
+#endif /* !AT32_DMA_SUPPORTS_DMAMUX */
+
+#if !defined(AT32_DMA_REQUIRED)
+#define AT32_DMA_REQUIRED
+#endif
+#endif /* AT32_I2C_USE_DMA == TRUE */
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type representing an I2C address.
+ */
+typedef uint16_t i2caddr_t;
+
+/**
+ * @brief Type of I2C driver condition flags.
+ */
+typedef uint32_t i2cflags_t;
+
+/**
+ * @brief I2C driver configuration structure.
+ */
+struct hal_i2c_config {
+ /**
+ * @brief CLKCTRL register initialization.
+ * @note Refer to the AT32 reference manual, the values are affected
+ * by the system clock settings in mcuconf.h.
+ */
+ uint32_t clkctrl;
+ /**
+ * @brief CTRL1 register initialization.
+ * @note Leave to zero unless you know what you are doing.
+ */
+ uint32_t ctrl1;
+ /**
+ * @brief CTRL2 register initialization.
+ * @note Only the ADD10 bit can eventually be specified here.
+ */
+ uint32_t ctrl2;
+};
+
+/**
+ * @brief Type of a structure representing an I2C configuration.
+ */
+typedef struct hal_i2c_config I2CConfig;
+
+/**
+ * @brief Type of a structure representing an I2C driver.
+ */
+typedef struct hal_i2c_driver I2CDriver;
+
+/**
+ * @brief Structure representing an I2C driver.
+ */
+struct hal_i2c_driver {
+ /**
+ * @brief Driver state.
+ */
+ i2cstate_t state;
+ /**
+ * @brief Current configuration data.
+ */
+ const I2CConfig *config;
+ /**
+ * @brief Error flags.
+ */
+ i2cflags_t errors;
+#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
+ mutex_t mutex;
+#endif /* I2C_USE_MUTUAL_EXCLUSION */
+#if defined(I2C_DRIVER_EXT_FIELDS)
+ I2C_DRIVER_EXT_FIELDS
+#endif
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Thread waiting for I/O completion.
+ */
+ thread_reference_t thread;
+#if (AT32_I2C_USE_DMA == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief RX DMA mode bit mask.
+ */
+ uint32_t rxdmamode;
+ /**
+ * @brief TX DMA mode bit mask.
+ */
+ uint32_t txdmamode;
+ /**
+ * @brief Receive DMA channel.
+ */
+ const at32_dma_stream_t *dmarx;
+ /**
+ * @brief Transmit DMA channel.
+ */
+ const at32_dma_stream_t *dmatx;
+#else /* AT32_I2C_USE_DMA == FALSE */
+ /**
+ * @brief Pointer to the next TX buffer location.
+ */
+ const uint8_t *txptr;
+ /**
+ * @brief Number of bytes in TX phase.
+ */
+ size_t txbytes;
+ /**
+ * @brief Pointer to the next RX buffer location.
+ */
+ uint8_t *rxptr;
+ /**
+ * @brief Number of bytes in RX phase.
+ */
+ size_t rxbytes;
+#endif /* AT32_I2C_USE_DMA == FALSE */
+ /**
+ * @brief Pointer to the I2Cx registers block.
+ */
+ I2C_TypeDef *i2c;
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Get errors from I2C driver.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+#define i2c_lld_get_errors(i2cp) ((i2cp)->errors)
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(__DOXYGEN__)
+#if AT32_I2C_USE_I2C1
+extern I2CDriver I2CD1;
+#endif
+
+#if AT32_I2C_USE_I2C2
+extern I2CDriver I2CD2;
+#endif
+
+#if AT32_I2C_USE_I2C3
+extern I2CDriver I2CD3;
+#endif
+
+#if AT32_I2C_USE_I2C4
+extern I2CDriver I2CD4;
+#endif
+
+#endif /* !defined(__DOXYGEN__) */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void i2c_lld_init(void);
+ void i2c_lld_start(I2CDriver *i2cp);
+ void i2c_lld_stop(I2CDriver *i2cp);
+ msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
+ const uint8_t *txbuf, size_t txbytes,
+ uint8_t *rxbuf, size_t rxbytes,
+ sysinterval_t timeout);
+ msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
+ uint8_t *rxbuf, size_t rxbytes,
+ sysinterval_t timeout);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_I2C */
+
+#endif /* HAL_I2C_LLD_H */
+
+/** @} */
diff --git a/os/hal/ports/AT32/LLD/OTGv1/hal_usb_lld.c b/os/hal/ports/AT32/LLD/OTGv1/hal_usb_lld.c
index b43b3edb2e..4486b8f946 100644
--- a/os/hal/ports/AT32/LLD/OTGv1/hal_usb_lld.c
+++ b/os/hal/ports/AT32/LLD/OTGv1/hal_usb_lld.c
@@ -2,6 +2,7 @@
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
ChibiOS - Copyright (C) 2023..2024 HorrorTroll
ChibiOS - Copyright (C) 2023..2024 Zhaqian
+ ChibiOS - Copyright (C) 2023..2024 Maxjta
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -783,6 +784,8 @@ void usb_lld_start(USBDriver *usbp) {
#if AT32_USB_USE_OTG2
if (&USBD2 == usbp) {
+
+#if AT32_OTG2_SUPPORTS_HS
/* OTG HS clock enable and reset.*/
crmEnableOTG_HS(true);
crmResetOTG_HS();
@@ -791,16 +794,8 @@ void usb_lld_start(USBDriver *usbp) {
nvicEnableVector(AT32_OTG2_NUMBER, AT32_USB_OTG2_IRQ_PRIORITY);
/* - Forced device mode.
- - USB turn-around time = USBTRDTIM_VALUE_HS or USBTRDTIM_VALUE_FS.*/
-#if defined(BOARD_OTG2_USES_ULPI)
- /* High speed ULPI PHY.*/
+ - USB turn-around time = USBTRDTIM_VALUE_HS or USBTRDTIM_VALUE_FS.*/
otgp->GUSBCFG = GUSBCFG_FDEVMODE | GUSBCFG_USBTRDTIM(USBTRDTIM_VALUE_HS);
-#else
- otgp->GUSBCFG = GUSBCFG_FDEVMODE | GUSBCFG_USBTRDTIM(USBTRDTIM_VALUE_FS) |
- GUSBCFG_PHYSEL;
-#endif
-
-#if defined(BOARD_OTG2_USES_ULPI)
#if AT32_USE_USB_OTG2_HS
/* USB 2.0 High Speed PHY in HS mode.*/
otgp->DCFG = 0x02200000 | DCFG_DEVSPD_HS;
@@ -808,7 +803,20 @@ void usb_lld_start(USBDriver *usbp) {
/* USB 2.0 High Speed PHY in FS mode.*/
otgp->DCFG = 0x02200000 | DCFG_DEVSPD_HS_FS;
#endif
+
#else
+ /* OTG FS clock enable and reset.*/
+ crmEnableOTG_FS2(true);
+ crmResetOTG_FS2();
+
+ /* Enables IRQ vector.*/
+ nvicEnableVector(AT32_OTG2_NUMBER, AT32_USB_OTG2_IRQ_PRIORITY);
+
+ /* - Forced device mode.
+ - USB turn-around time = USBTRDTIM_VALUE_HS or USBTRDTIM_VALUE_FS.*/
+ otgp->GUSBCFG = GUSBCFG_FDEVMODE | GUSBCFG_USBTRDTIM(USBTRDTIM_VALUE_FS) |
+ GUSBCFG_PHYSEL;
+
/* 48MHz 1.1 PHY.*/
otgp->DCFG = 0x02200000 | DCFG_DEVSPD_FS11;
#endif
diff --git a/os/hal/ports/AT32/LLD/SPIv2/driver.mk b/os/hal/ports/AT32/LLD/SPIv2/driver.mk
new file mode 100644
index 0000000000..3ccd2ddbb1
--- /dev/null
+++ b/os/hal/ports/AT32/LLD/SPIv2/driver.mk
@@ -0,0 +1,9 @@
+ifeq ($(USE_SMART_BUILD),yes)
+ifneq ($(findstring HAL_USE_SPI TRUE,$(HALCONF)),)
+PLATFORMSRC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/AT32/LLD/SPIv2/hal_spi_v2_lld.c
+endif
+else
+PLATFORMSRC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/AT32/LLD/SPIv2/hal_spi_v2_lld.c
+endif
+
+PLATFORMINC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/AT32/LLD/SPIv2
diff --git a/os/hal/ports/AT32/LLD/SPIv2/hal_spi_v2_lld.c b/os/hal/ports/AT32/LLD/SPIv2/hal_spi_v2_lld.c
new file mode 100644
index 0000000000..c1ef1cd24e
--- /dev/null
+++ b/os/hal/ports/AT32/LLD/SPIv2/hal_spi_v2_lld.c
@@ -0,0 +1,626 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+ ChibiOS - Copyright (C) 2023..2024 HorrorTroll
+ ChibiOS - Copyright (C) 2023..2024 Zhaqian
+ ChibiOS - Copyright (C) 2023..2024 Maxjta
+
+ Licensed 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.
+*/
+
+/**
+ * @file SPIv1/hal_spi_v2_lld.c
+ * @brief AT32 SPI (v2) subsystem low level driver source.
+ *
+ * @addtogroup SPI
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_SPI || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#if !defined(SPI_SPID1_MEMORY)
+#define SPI_SPID1_MEMORY
+#endif
+
+#if !defined(SPI_SPID2_MEMORY)
+#define SPI_SPID2_MEMORY
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief SPI1 driver identifier.*/
+#if AT32_SPI_USE_SPI1 || defined(__DOXYGEN__)
+SPI_SPID1_MEMORY SPIDriver SPID1;
+#endif
+
+/** @brief SPI2 driver identifier.*/
+#if AT32_SPI_USE_SPI2 || defined(__DOXYGEN__)
+SPI_SPID2_MEMORY SPIDriver SPID2;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static void spi_lld_configure(SPIDriver *spip) {
+ uint32_t ctrl1, ctrl2;
+
+ /* Disabling SPI during (re)configuration.*/
+ spip->spi->CTRL1 = 0U;
+
+ /* Common CTRL1 and CTRL2 options.*/
+ ctrl1 = spip->config->ctrl1 & ~(SPI_CTRL1_MSTEN | SPI_CTRL1_SPIEN);
+ ctrl2 = spip->config->ctrl2 | SPI_CTRL2_DMAREN | SPI_CTRL2_DMATEN;
+
+ /* SPI setup.*/
+ if (spip->config->slave == false) {
+ ctrl1 |= SPI_CTRL1_SWCSEN | SPI_CTRL1_SWCSIL | SPI_CTRL1_MSTEN;
+ ctrl2 |= SPI_CTRL2_HWCSOE;
+ }
+
+ /* New configuration.*/
+ spip->spi->CTRL2 = ctrl2;
+ spip->spi->CTRL1 = ctrl1;
+ spip->spi->CTRL1 = ctrl1 | SPI_CTRL1_SPIEN;
+}
+
+/**
+ * @brief Stopping the SPI transaction.
+ * @note This is done nicely or by brutally resetting it depending on
+ * the mode and settings.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ */
+static msg_t spi_lld_stop_abort(SPIDriver *spip) {
+
+ if (!spip->config->slave) {
+ /* Master mode, stopping gracefully.*/
+
+ /* Stopping TX DMA channel.*/
+ dmaStreamDisable(spip->dmatx);
+
+ /* Waiting for current frame completion then stop SPI.*/
+ while ((spip->spi->STS & SPI_STS_BF) != 0U) {
+ }
+
+ /* Now it is idle, stopping RX DMA channel.*/
+ dmaStreamDisable(spip->dmarx);
+ }
+ else {
+ /* Slave mode, this will not be nice.*/
+
+ /* Stopping DMAs.*/
+ dmaStreamDisable(spip->dmatx);
+ dmaStreamDisable(spip->dmarx);
+
+ /* Resetting SPI, this will stop it for sure and leave it
+ in a clean state.*/
+ if (false) {
+ }
+
+#if AT32_SPI_USE_SPI1
+ else if (&SPID1 == spip) {
+ crmResetSPI1();
+ }
+#endif
+
+#if AT32_SPI_USE_SPI2
+ else if (&SPID2 == spip) {
+ crmResetSPI2();
+ }
+#endif
+
+ else {
+ osalDbgAssert(false, "invalid SPI instance");
+ }
+
+ /* Reconfiguring SPI.*/
+ spi_lld_configure(spip);
+ }
+
+ return HAL_RET_SUCCESS;
+}
+
+/**
+ * @brief Shared end-of-rx service routine.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] flags pre-shifted content of the STS register
+ */
+static void spi_lld_serve_rx_interrupt(SPIDriver *spip, uint32_t flags) {
+
+ /* DMA errors handling.*/
+ if ((flags & AT32_DMA_STS_DTERRF) != 0) {
+#if defined(AT32_SPI_DMA_ERROR_HOOK)
+ /* Hook first, if defined.*/
+ AT32_SPI_DMA_ERROR_HOOK(spip);
+#endif
+
+ /* Aborting the transfer.*/
+ (void) spi_lld_stop_abort(spip);
+
+ /* Reporting the failure.*/
+ __spi_isr_error_code(spip, HAL_RET_HW_FAILURE);
+ }
+ else if (spip->config->circular) {
+ if ((flags & AT32_DMA_STS_HDTF) != 0U) {
+ /* Half buffer interrupt.*/
+ __spi_isr_half_code(spip);
+ }
+ if ((flags & AT32_DMA_STS_FDTF) != 0U) {
+ /* End buffer interrupt.*/
+ __spi_isr_full_code(spip);
+ }
+ }
+ else {
+ /* Stopping the transfer.*/
+ (void) spi_lld_stop_abort(spip);
+
+ /* Operation finished interrupt.*/
+ __spi_isr_complete_code(spip);
+ }
+}
+
+/**
+ * @brief Shared end-of-tx service routine.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] flags pre-shifted content of the STS register
+ */
+static void spi_lld_serve_tx_interrupt(SPIDriver *spip, uint32_t flags) {
+
+ /* DMA errors handling.*/
+ if ((flags & AT32_DMA_STS_DTERRF) != 0) {
+#if defined(AT32_SPI_DMA_ERROR_HOOK)
+ /* Hook first, if defined.*/
+ AT32_SPI_DMA_ERROR_HOOK(spip);
+#endif
+
+ /* Aborting the transfer.*/
+ (void) spi_lld_stop_abort(spip);
+
+ /* Reporting the failure.*/
+ __spi_isr_error_code(spip, HAL_RET_HW_FAILURE);
+ }
+}
+
+/**
+ * @brief DMA streams allocation.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] rxstream stream to be allocated for RX
+ * @param[in] txstream stream to be allocated for TX
+ * @param[in] priority streams IRQ priority
+ * @return The operation status.
+ */
+static msg_t spi_lld_get_dma(SPIDriver *spip, uint32_t rxstream,
+ uint32_t txstream, uint32_t priority) {
+
+ spip->dmarx = dmaStreamAllocI(rxstream, priority,
+ (at32_dmasts_t)spi_lld_serve_rx_interrupt,
+ (void *)spip);
+ if (spip->dmarx == NULL) {
+ return HAL_RET_NO_RESOURCE;
+ }
+
+ spip->dmatx = dmaStreamAllocI(txstream, priority,
+ (at32_dmasts_t)spi_lld_serve_tx_interrupt,
+ (void *)spip);
+ if (spip->dmatx == NULL) {
+ dmaStreamFreeI(spip->dmarx);
+ return HAL_RET_NO_RESOURCE;
+ }
+
+ return HAL_RET_SUCCESS;
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level SPI driver initialization.
+ *
+ * @notapi
+ */
+void spi_lld_init(void) {
+
+#if AT32_SPI_USE_SPI1
+ spiObjectInit(&SPID1);
+ SPID1.spi = SPI1;
+ SPID1.dmarx = NULL;
+ SPID1.dmatx = NULL;
+ SPID1.rxdmamode = AT32_DMA_CTRL_CHPL(AT32_SPI_SPI1_DMA_PRIORITY) |
+ AT32_DMA_CTRL_DTD_P2M |
+ AT32_DMA_CTRL_FDTIEN |
+ AT32_DMA_CTRL_DTERRIEN;
+ SPID1.txdmamode = AT32_DMA_CTRL_CHPL(AT32_SPI_SPI1_DMA_PRIORITY) |
+ AT32_DMA_CTRL_DTD_M2P |
+ AT32_DMA_CTRL_DTERRIEN;
+#endif
+
+#if AT32_SPI_USE_SPI2
+ spiObjectInit(&SPID2);
+ SPID2.spi = SPI2;
+ SPID2.dmarx = NULL;
+ SPID2.dmatx = NULL;
+ SPID2.rxdmamode = AT32_DMA_CTRL_CHPL(AT32_SPI_SPI2_DMA_PRIORITY) |
+ AT32_DMA_CTRL_DTD_P2M |
+ AT32_DMA_CTRL_FDTIEN |
+ AT32_DMA_CTRL_DTERRIEN;
+ SPID2.txdmamode = AT32_DMA_CTRL_CHPL(AT32_SPI_SPI2_DMA_PRIORITY) |
+ AT32_DMA_CTRL_DTD_M2P |
+ AT32_DMA_CTRL_DTERRIEN;
+#endif
+}
+
+/**
+ * @brief Configures and activates the SPI peripheral.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @return The operation status.
+ *
+ * @notapi
+ */
+msg_t spi_lld_start(SPIDriver *spip) {
+ msg_t msg;
+
+ /* Resetting TX pattern source.*/
+ spip->txsource = (uint32_t)AT32_SPI_FILLER_PATTERN;
+
+ /* If in stopped state then enables the SPI and DMA clocks.*/
+ if (spip->state == SPI_STOP) {
+ if (false) {
+ }
+
+#if AT32_SPI_USE_SPI1
+ else if (&SPID1 == spip) {
+ msg = spi_lld_get_dma(spip,
+ AT32_SPI_SPI1_RX_DMA_STREAM,
+ AT32_SPI_SPI1_TX_DMA_STREAM,
+ AT32_SPI_SPI1_IRQ_PRIORITY);
+ if (msg != HAL_RET_SUCCESS) {
+ return msg;
+ }
+ crmEnableSPI1(true);
+ crmResetSPI1();
+#if AT32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(spip->dmarx, AT32_DMAMUX_SPI1_RX);
+ dmaSetRequestSource(spip->dmatx, AT32_DMAMUX_SPI1_TX);
+#endif
+ }
+#endif
+
+#if AT32_SPI_USE_SPI2
+ else if (&SPID2 == spip) {
+ msg = spi_lld_get_dma(spip,
+ AT32_SPI_SPI2_RX_DMA_STREAM,
+ AT32_SPI_SPI2_TX_DMA_STREAM,
+ AT32_SPI_SPI2_IRQ_PRIORITY);
+ if (msg != HAL_RET_SUCCESS) {
+ return msg;
+ }
+ crmEnableSPI2(true);
+ crmResetSPI2();
+#if AT32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(spip->dmarx, AT32_DMAMUX_SPI2_RX);
+ dmaSetRequestSource(spip->dmatx, AT32_DMAMUX_SPI2_TX);
+#endif
+ }
+#endif
+
+ else {
+ osalDbgAssert(false, "invalid SPI instance");
+ }
+
+ /* DMA setup.*/
+ dmaStreamSetPeripheral(spip->dmarx, &spip->spi->DT);
+ dmaStreamSetPeripheral(spip->dmatx, &spip->spi->DT);
+ }
+
+ /* Configuration-specific DMA setup.*/
+ if ((spip->config->ctrl1 & SPI_CTRL1_FBN) == 0) {
+ /* Frame width is 8 bits or smaller.*/
+ spip->rxdmamode = (spip->rxdmamode & ~AT32_DMA_CTRL_WIDTH_MASK) |
+ AT32_DMA_CTRL_PWIDTH_BYTE | AT32_DMA_CTRL_MWIDTH_BYTE;
+ spip->txdmamode = (spip->txdmamode & ~AT32_DMA_CTRL_WIDTH_MASK) |
+ AT32_DMA_CTRL_PWIDTH_BYTE | AT32_DMA_CTRL_MWIDTH_BYTE;
+ }
+ else {
+ /* Frame width is larger than 8 bits.*/
+ spip->rxdmamode = (spip->rxdmamode & ~AT32_DMA_CTRL_WIDTH_MASK) |
+ AT32_DMA_CTRL_PWIDTH_HWORD | AT32_DMA_CTRL_MWIDTH_HWORD;
+ spip->txdmamode = (spip->txdmamode & ~AT32_DMA_CTRL_WIDTH_MASK) |
+ AT32_DMA_CTRL_PWIDTH_HWORD | AT32_DMA_CTRL_MWIDTH_HWORD;
+ }
+
+ if (spip->config->circular) {
+ spip->rxdmamode |= (AT32_DMA_CTRL_LM | AT32_DMA_CTRL_HDTIEN);
+ spip->txdmamode |= (AT32_DMA_CTRL_LM | AT32_DMA_CTRL_HDTIEN);
+ }
+ else {
+ spip->rxdmamode &= ~(AT32_DMA_CTRL_LM | AT32_DMA_CTRL_HDTIEN);
+ spip->txdmamode &= ~(AT32_DMA_CTRL_LM | AT32_DMA_CTRL_HDTIEN);
+ }
+
+ /* SPI setup.*/
+ spi_lld_configure(spip);
+
+ return HAL_RET_SUCCESS;
+}
+
+/**
+ * @brief Deactivates the SPI peripheral.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+void spi_lld_stop(SPIDriver *spip) {
+
+ /* If in ready state then disables the SPI clock.*/
+ if (spip->state == SPI_READY) {
+
+ /* Just in case this has been called uncleanly.*/
+ (void) spi_lld_stop_abort(spip);
+
+ /* SPI cleanup.*/
+ spip->spi->CTRL1 = 0;
+ spip->spi->CTRL2 = 0;
+
+ /* DMA channels release.*/
+ dmaStreamFreeI(spip->dmatx);
+ dmaStreamFreeI(spip->dmarx);
+ spip->dmarx = NULL;
+ spip->dmatx = NULL;
+
+ /* Clock shutdown.*/
+ if (false) {
+ }
+
+#if AT32_SPI_USE_SPI1
+ else if (&SPID1 == spip) {
+ crmDisableSPI1();
+ }
+#endif
+
+#if AT32_SPI_USE_SPI2
+ else if (&SPID2 == spip) {
+ crmDisableSPI2();
+ }
+#endif
+
+ else {
+ osalDbgAssert(false, "invalid SPI instance");
+ }
+ }
+}
+
+#if (SPI_SELECT_MODE == SPI_SELECT_MODE_LLD) || defined(__DOXYGEN__)
+/**
+ * @brief Asserts the slave select signal and prepares for transfers.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+void spi_lld_select(SPIDriver *spip) {
+
+ /* No implementation on AT32.*/
+}
+
+/**
+ * @brief Deasserts the slave select signal.
+ * @details The previously selected peripheral is unselected.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+void spi_lld_unselect(SPIDriver *spip) {
+
+ /* No implementation on AT32.*/
+}
+#endif
+
+/**
+ * @brief Ignores data on the SPI bus.
+ * @details This synchronous function performs the transmission of a series of
+ * idle words on the SPI bus and ignores the received data.
+ * @pre In order to use this function the option @p SPI_USE_SYNCHRONIZATION
+ * must be enabled.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to be ignored
+ * @return The operation status.
+ *
+ * @notapi
+ */
+msg_t spi_lld_ignore(SPIDriver *spip, size_t n) {
+
+ osalDbgAssert(n <= AT32_DMA_MAX_TRANSFER, "unsupported DMA transfer size");
+
+ dmaStreamSetMemory0(spip->dmarx, &spip->rxsink);
+ dmaStreamSetTransactionSize(spip->dmarx, n);
+ dmaStreamSetMode(spip->dmarx, spip->rxdmamode);
+
+ dmaStreamSetMemory0(spip->dmatx, &spip->txsource);
+ dmaStreamSetTransactionSize(spip->dmatx, n);
+ dmaStreamSetMode(spip->dmatx, spip->txdmamode);
+
+ dmaStreamEnable(spip->dmarx);
+ dmaStreamEnable(spip->dmatx);
+
+ return HAL_RET_SUCCESS;
+}
+
+/**
+ * @brief Exchanges data on the SPI bus.
+ * @details This asynchronous function starts a simultaneous transmit/receive
+ * operation.
+ * @post At the end of the operation the configured callback is invoked.
+ * @note The buffers are organized as uint8_t arrays for data sizes below or
+ * equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to be exchanged
+ * @param[in] txbuf the pointer to the transmit buffer
+ * @param[out] rxbuf the pointer to the receive buffer
+ * @return The operation status.
+ *
+ * @notapi
+ */
+msg_t spi_lld_exchange(SPIDriver *spip, size_t n,
+ const void *txbuf, void *rxbuf) {
+
+ osalDbgAssert(n <= AT32_DMA_MAX_TRANSFER, "unsupported DMA transfer size");
+
+ dmaStreamSetMemory0(spip->dmarx, rxbuf);
+ dmaStreamSetTransactionSize(spip->dmarx, n);
+ dmaStreamSetMode(spip->dmarx, spip->rxdmamode | AT32_DMA_CTRL_MINCM);
+
+ dmaStreamSetMemory0(spip->dmatx, txbuf);
+ dmaStreamSetTransactionSize(spip->dmatx, n);
+ dmaStreamSetMode(spip->dmatx, spip->txdmamode | AT32_DMA_CTRL_MINCM);
+
+ dmaStreamEnable(spip->dmarx);
+ dmaStreamEnable(spip->dmatx);
+
+ return HAL_RET_SUCCESS;
+}
+
+/**
+ * @brief Sends data over the SPI bus.
+ * @details This asynchronous function starts a transmit operation.
+ * @post At the end of the operation the configured callback is invoked.
+ * @note The buffers are organized as uint8_t arrays for data sizes below or
+ * equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to send
+ * @param[in] txbuf the pointer to the transmit buffer
+ * @return The operation status.
+ *
+ * @notapi
+ */
+msg_t spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) {
+
+ osalDbgAssert(n <= AT32_DMA_MAX_TRANSFER, "unsupported DMA transfer size");
+
+ dmaStreamSetMemory0(spip->dmarx, &spip->rxsink);
+ dmaStreamSetTransactionSize(spip->dmarx, n);
+ dmaStreamSetMode(spip->dmarx, spip->rxdmamode);
+
+ dmaStreamSetMemory0(spip->dmatx, txbuf);
+ dmaStreamSetTransactionSize(spip->dmatx, n);
+ dmaStreamSetMode(spip->dmatx, spip->txdmamode | AT32_DMA_CTRL_MINCM);
+
+ dmaStreamEnable(spip->dmarx);
+ dmaStreamEnable(spip->dmatx);
+
+ return HAL_RET_SUCCESS;
+}
+
+/**
+ * @brief Receives data from the SPI bus.
+ * @details This asynchronous function starts a receive operation.
+ * @post At the end of the operation the configured callback is invoked.
+ * @note The buffers are organized as uint8_t arrays for data sizes below or
+ * equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to receive
+ * @param[out] rxbuf the pointer to the receive buffer
+ * @return The operation status.
+ *
+ * @notapi
+ */
+msg_t spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) {
+
+ osalDbgAssert(n <= AT32_DMA_MAX_TRANSFER, "unsupported DMA transfer size");
+
+ dmaStreamSetMemory0(spip->dmarx, rxbuf);
+ dmaStreamSetTransactionSize(spip->dmarx, n);
+ dmaStreamSetMode(spip->dmarx, spip->rxdmamode | AT32_DMA_CTRL_MINCM);
+
+ dmaStreamSetMemory0(spip->dmatx, &spip->txsource);
+ dmaStreamSetTransactionSize(spip->dmatx, n);
+ dmaStreamSetMode(spip->dmatx, spip->txdmamode);
+
+ dmaStreamEnable(spip->dmarx);
+ dmaStreamEnable(spip->dmatx);
+
+ return HAL_RET_SUCCESS;
+}
+
+/**
+ * @brief Aborts the ongoing SPI operation, if any.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[out] sizep pointer to the counter of frames not yet transferred
+ * or @p NULL
+ * @return The operation status.
+ *
+ * @notapi
+ */
+msg_t spi_lld_stop_transfer(SPIDriver *spip, size_t *sizep) {
+ msg_t msg;
+
+ /* Stopping everything.*/
+ msg = spi_lld_stop_abort(spip);
+
+ if (sizep != NULL) {
+ *sizep = dmaStreamGetTransactionSize(spip->dmarx);
+ }
+
+ return msg;
+}
+
+/**
+ * @brief Exchanges one frame using a polled wait.
+ * @details This synchronous function exchanges one frame using a polled
+ * synchronization method. This function is useful when exchanging
+ * small amount of data on high speed channels, usually in this
+ * situation is much more efficient just wait for completion using
+ * polling than suspending the thread waiting for an interrupt.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] frame the data frame to send over the SPI bus
+ * @return The received data frame from the SPI bus.
+ */
+uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame) {
+
+ spip->spi->DT = frame;
+ while ((spip->spi->STS & SPI_STS_RDBF) == 0U)
+ ;
+ return spip->spi->DT;
+}
+
+#endif /* HAL_USE_SPI */
+
+/** @} */
diff --git a/os/hal/ports/AT32/LLD/SPIv2/hal_spi_v2_lld.h b/os/hal/ports/AT32/LLD/SPIv2/hal_spi_v2_lld.h
new file mode 100644
index 0000000000..02f96a82ef
--- /dev/null
+++ b/os/hal/ports/AT32/LLD/SPIv2/hal_spi_v2_lld.h
@@ -0,0 +1,234 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+ ChibiOS - Copyright (C) 2023..2024 HorrorTroll
+ ChibiOS - Copyright (C) 2023..2024 Zhaqian
+ ChibiOS - Copyright (C) 2024 Maxjta
+
+ Licensed 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.
+*/
+
+/**
+ * @file SPIv1/hal_spi_v2_lld.h
+ * @brief AT32 SPI (v2) subsystem low level driver header.
+ *
+ * @addtogroup SPI
+ * @{
+ */
+
+#ifndef HAL_SPI_V2_LLD_H
+#define HAL_SPI_V2_LLD_H
+
+#if HAL_USE_SPI || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @brief Circular mode support flag.
+ */
+#define SPI_SUPPORTS_CIRCULAR TRUE
+
+/**
+ * @brief Slave mode support flag.
+ */
+#define SPI_SUPPORTS_SLAVE_MODE TRUE
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief SPI1 driver enable switch.
+ * @details If set to @p TRUE the support for SPI1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(AT32_SPI_USE_SPI1) || defined(__DOXYGEN__)
+#define AT32_SPI_USE_SPI1 FALSE
+#endif
+
+/**
+ * @brief SPI2 driver enable switch.
+ * @details If set to @p TRUE the support for SPI2 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(AT32_SPI_USE_SPI2) || defined(__DOXYGEN__)
+#define AT32_SPI_USE_SPI2 FALSE
+#endif
+
+/**
+ * @brief Filler pattern used when there is nothing to transmit.
+ */
+#if !defined(AT32_SPI_FILLER_PATTERN) || defined(__DOXYGEN__)
+#define AT32_SPI_FILLER_PATTERN 0xFFFFFFFFU
+#endif
+
+/**
+ * @brief SPI1 interrupt priority level setting.
+ */
+#if !defined(AT32_SPI_SPI1_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_SPI_SPI1_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief SPI2 interrupt priority level setting.
+ */
+#if !defined(AT32_SPI_SPI2_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_SPI_SPI2_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief SPI1 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA streams but
+ * because of the streams ordering the RX stream has always priority
+ * over the TX stream.
+ */
+#if !defined(AT32_SPI_SPI1_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_SPI_SPI1_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief SPI2 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA streams but
+ * because of the streams ordering the RX stream has always priority
+ * over the TX stream.
+ */
+#if !defined(AT32_SPI_SPI2_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_SPI_SPI2_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief SPI DMA error hook.
+ */
+#if !defined(AT32_SPI_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
+#define AT32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure")
+#endif
+
+/**
+ * @brief SPI DMA max transfer hook.
+ */
+#if !defined(AT32_DMA_MAX_TRANSFER) || defined(__DOXYGEN__)
+#define AT32_DMA_MAX_TRANSFER 65536
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if AT32_SPI_USE_SPI1 && !AT32_HAS_SPI1
+#error "SPI1 not present in the selected device"
+#endif
+
+#if AT32_SPI_USE_SPI2 && !AT32_HAS_SPI2
+#error "SPI2 not present in the selected device"
+#endif
+
+#if !AT32_SPI_USE_SPI1 && !AT32_SPI_USE_SPI2
+#error "SPI driver activated but no SPI peripheral assigned"
+#endif
+
+#if AT32_SPI_USE_SPI1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(AT32_SPI_SPI1_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to SPI1"
+#endif
+
+#if AT32_SPI_USE_SPI2 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(AT32_SPI_SPI2_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to SPI2"
+#endif
+
+#if !defined(AT32_DMA_REQUIRED)
+#define AT32_DMA_REQUIRED
+#endif
+
+#if SPI_SELECT_MODE == SPI_SELECT_MODE_LLD
+#error "SPI_SELECT_MODE_LLD not supported by this driver"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+#define spi_lld_driver_fields \
+ /* Pointer to the SPIx registers block.*/ \
+ SPI_TypeDef *spi; \
+ /* Receive DMA stream.*/ \
+ const at32_dma_stream_t *dmarx; \
+ /* Transmit DMA stream.*/ \
+ const at32_dma_stream_t *dmatx; \
+ /* RX DMA mode bit mask.*/ \
+ uint32_t rxdmamode; \
+ /* TX DMA mode bit mask.*/ \
+ uint32_t txdmamode; \
+ /* Sink for discarded data.*/ \
+ uint32_t rxsink; \
+ /* Source for default TX pattern.*/ \
+ uint32_t txsource
+
+/**
+ * @brief Low level fields of the SPI configuration structure.
+ */
+#define spi_lld_config_fields \
+ /* SPI CTRL1 register initialization data.*/ \
+ uint16_t ctrl1; \
+ /* SPI CTRL2 register initialization data.*/ \
+ uint16_t ctrl2
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if AT32_SPI_USE_SPI1 && !defined(__DOXYGEN__)
+extern SPIDriver SPID1;
+#endif
+
+#if AT32_SPI_USE_SPI2 && !defined(__DOXYGEN__)
+extern SPIDriver SPID2;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void spi_lld_init(void);
+ msg_t spi_lld_start(SPIDriver *spip);
+ void spi_lld_stop(SPIDriver *spip);
+#if (SPI_SELECT_MODE == SPI_SELECT_MODE_LLD) || defined(__DOXYGEN__)
+ void spi_lld_select(SPIDriver *spip);
+ void spi_lld_unselect(SPIDriver *spip);
+#endif
+ msg_t spi_lld_ignore(SPIDriver *spip, size_t n);
+ msg_t spi_lld_exchange(SPIDriver *spip, size_t n,
+ const void *txbuf, void *rxbuf);
+ msg_t spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf);
+ msg_t spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf);
+ msg_t spi_lld_stop_transfer(SPIDriver *spip, size_t *sizep);
+ uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_SPI */
+
+#endif /* HAL_SPI_V2_LLD_H */
+
+/** @} */
diff --git a/os/hal/ports/AT32/LLD/TMRv1/at32_tmr13.inc b/os/hal/ports/AT32/LLD/TMRv1/at32_tmr13.inc
new file mode 100644
index 0000000000..e55972480b
--- /dev/null
+++ b/os/hal/ports/AT32/LLD/TMRv1/at32_tmr13.inc
@@ -0,0 +1,136 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+ ChibiOS - Copyright (C) 2023..2024 HorrorTroll
+ ChibiOS - Copyright (C) 2023..2024 Zhaqian
+ ChibiOS - Copyright (C) 2023..2024 Maxjta
+
+ Licensed 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.
+*/
+
+/**
+ * @file TMRv1/at32_tmr13.inc
+ * @brief Shared TMR13 handler.
+ *
+ * @addtogroup AT32_TMR13_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(AT32_HAS_TMR13)
+#error "AT32_HAS_TMR13 not defined in registry"
+#endif
+
+/* Driver checks for robustness, undefined USE macros are defaulted to
+ FALSE. This makes this module independent from drivers implementation.*/
+#if !defined(AT32_GPT_USE_TMR13)
+#define AT32_GPT_USE_TMR13 FALSE
+#endif
+#if !defined(AT32_ICU_USE_TMR13)
+#define AT32_ICU_USE_TMR13 FALSE
+#endif
+#if !defined(AT32_PWM_USE_TMR13)
+#define AT32_PWM_USE_TMR13 FALSE
+#endif
+#if !defined(AT32_ST_USE_TMR13)
+#define AT32_ST_USE_TMR13 FALSE
+#endif
+
+#if AT32_HAS_TMR13
+
+/* Priority settings checks.*/
+#if !defined(AT32_IRQ_TMR13_PRIORITY)
+#error "AT32_IRQ_TMR13_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(AT32_IRQ_TMR13_PRIORITY)
+#error "Invalid IRQ priority assigned to AT32_IRQ_TMR13_PRIORITY"
+#endif
+
+#endif /* AT32_HAS_TMR13 */
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void tmr13_irq_init(void) {
+#if defined(AT32_TMR13_IS_USED)
+ nvicEnableVector(AT32_TMR13_NUMBER, AT32_IRQ_TMR13_PRIORITY);
+#endif
+}
+
+static inline void tmr13_irq_deinit(void) {
+#if defined(AT32_TMR13_IS_USED)
+ nvicDisableVector(AT32_TMR13_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(AT32_TMR13_IS_USED) || defined(__DOXYGEN__)
+/**
+ * @brief TMR13 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_TMR13_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_GPT
+#if AT32_GPT_USE_TMR13
+ gpt_lld_serve_interrupt(&GPTD13);
+#endif
+#endif
+#if HAL_USE_ICU
+#if AT32_ICU_USE_TMR13
+ icu_lld_serve_interrupt(&ICUD13);
+#endif
+#endif
+#if HAL_USE_PWM
+#if AT32_PWM_USE_TMR13
+ pwm_lld_serve_interrupt(&PWMD13);
+#endif
+#endif
+#if 1
+#if AT32_ST_USE_TMR13
+ st_lld_serve_interrupt();
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/os/hal/ports/AT32/LLD/TMRv1/at32_tmr14.inc b/os/hal/ports/AT32/LLD/TMRv1/at32_tmr14.inc
new file mode 100644
index 0000000000..4b70b97a64
--- /dev/null
+++ b/os/hal/ports/AT32/LLD/TMRv1/at32_tmr14.inc
@@ -0,0 +1,136 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+ ChibiOS - Copyright (C) 2023..2024 HorrorTroll
+ ChibiOS - Copyright (C) 2023..2024 Zhaqian
+ ChibiOS - Copyright (C) 2023..2024 Maxjta
+
+ Licensed 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.
+*/
+
+/**
+ * @file TMRv1/at32_tmr14.inc
+ * @brief Shared TMR14 handler.
+ *
+ * @addtogroup AT32_TMR14_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(AT32_HAS_TMR14)
+#error "AT32_HAS_TMR14 not defined in registry"
+#endif
+
+/* Driver checks for robustness, undefined USE macros are defaulted to
+ FALSE. This makes this module independent from drivers implementation.*/
+#if !defined(AT32_GPT_USE_TMR14)
+#define AT32_GPT_USE_TMR14 FALSE
+#endif
+#if !defined(AT32_ICU_USE_TMR14)
+#define AT32_ICU_USE_TMR14 FALSE
+#endif
+#if !defined(AT32_PWM_USE_TMR14)
+#define AT32_PWM_USE_TMR14 FALSE
+#endif
+#if !defined(AT32_ST_USE_TMR14)
+#define AT32_ST_USE_TMR14 FALSE
+#endif
+
+#if AT32_HAS_TMR14
+
+/* Priority settings checks.*/
+#if !defined(AT32_IRQ_TMR14_PRIORITY)
+#error "AT32_IRQ_TMR14_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(AT32_IRQ_TMR14_PRIORITY)
+#error "Invalid IRQ priority assigned to AT32_IRQ_TMR14_PRIORITY"
+#endif
+
+#endif /* AT32_HAS_TMR14 */
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void tmr14_irq_init(void) {
+#if defined(AT32_TMR14_IS_USED)
+ nvicEnableVector(AT32_TMR14_NUMBER, AT32_IRQ_TMR14_PRIORITY);
+#endif
+}
+
+static inline void tmr14_irq_deinit(void) {
+#if defined(AT32_TMR14_IS_USED)
+ nvicDisableVector(AT32_TMR14_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(AT32_TMR14_IS_USED) || defined(__DOXYGEN__)
+/**
+ * @brief TMR14 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_TMR14_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_GPT
+#if AT32_GPT_USE_TMR14
+ gpt_lld_serve_interrupt(&GPTD14);
+#endif
+#endif
+#if HAL_USE_ICU
+#if AT32_ICU_USE_TMR14
+ icu_lld_serve_interrupt(&ICUD14);
+#endif
+#endif
+#if HAL_USE_PWM
+#if AT32_PWM_USE_TMR14
+ pwm_lld_serve_interrupt(&PWMD14);
+#endif
+#endif
+#if 1
+#if AT32_ST_USE_TMR14
+ st_lld_serve_interrupt();
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/os/hal/ports/AT32/LLD/TMRv1/at32_tmr6.inc b/os/hal/ports/AT32/LLD/TMRv1/at32_tmr6.inc
new file mode 100644
index 0000000000..aac92e5593
--- /dev/null
+++ b/os/hal/ports/AT32/LLD/TMRv1/at32_tmr6.inc
@@ -0,0 +1,136 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+ ChibiOS - Copyright (C) 2023..2024 HorrorTroll
+ ChibiOS - Copyright (C) 2023..2024 Zhaqian
+ ChibiOS - Copyright (C) 2023..2024 Maxjta
+
+ Licensed 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.
+*/
+
+/**
+ * @file TMRv1/at32_tmr6.inc
+ * @brief Shared TMR6 handler.
+ *
+ * @addtogroup AT32_TMR6_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(AT32_HAS_TMR6)
+#error "AT32_HAS_TMR6 not defined in registry"
+#endif
+
+/* Driver checks for robustness, undefined USE macros are defaulted to
+ FALSE. This makes this module independent from drivers implementation.*/
+#if !defined(AT32_GPT_USE_TMR6)
+#define AT32_GPT_USE_TMR6 FALSE
+#endif
+#if !defined(AT32_ICU_USE_TMR6)
+#define AT32_ICU_USE_TMR6 FALSE
+#endif
+#if !defined(AT32_PWM_USE_TMR6)
+#define AT32_PWM_USE_TMR6 FALSE
+#endif
+#if !defined(AT32_ST_USE_TMR6)
+#define AT32_ST_USE_TMR6 FALSE
+#endif
+
+#if AT32_HAS_TMR6
+
+/* Priority settings checks.*/
+#if !defined(AT32_IRQ_TMR6_PRIORITY)
+#error "AT32_IRQ_TMR6_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(AT32_IRQ_TMR6_PRIORITY)
+#error "Invalid IRQ priority assigned to AT32_IRQ_TMR6_PRIORITY"
+#endif
+
+#endif /* AT32_HAS_TMR6 */
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void tmr6_irq_init(void) {
+#if defined(AT32_TMR6_IS_USED)
+ nvicEnableVector(AT32_TMR6_NUMBER, AT32_IRQ_TMR6_PRIORITY);
+#endif
+}
+
+static inline void tmr6_irq_deinit(void) {
+#if defined(AT32_TMR6_IS_USED)
+ nvicDisableVector(AT32_TMR6_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(AT32_TMR6_IS_USED) || defined(__DOXYGEN__)
+/**
+ * @brief TMR6 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_TMR6_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_GPT
+#if AT32_GPT_USE_TMR6
+ gpt_lld_serve_interrupt(&GPTD6);
+#endif
+#endif
+#if HAL_USE_ICU
+#if AT32_ICU_USE_TMR6
+ icu_lld_serve_interrupt(&ICUD6);
+#endif
+#endif
+#if HAL_USE_PWM
+#if AT32_PWM_USE_TMR6
+ pwm_lld_serve_interrupt(&PWMD6);
+#endif
+#endif
+#if 1
+#if AT32_ST_USE_TMR6
+ st_lld_serve_interrupt();
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/os/hal/ports/AT32/LLD/TMRv1/at32_tmr7.inc b/os/hal/ports/AT32/LLD/TMRv1/at32_tmr7.inc
new file mode 100644
index 0000000000..6e2317d06b
--- /dev/null
+++ b/os/hal/ports/AT32/LLD/TMRv1/at32_tmr7.inc
@@ -0,0 +1,136 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+ ChibiOS - Copyright (C) 2023..2024 HorrorTroll
+ ChibiOS - Copyright (C) 2023..2024 Zhaqian
+ ChibiOS - Copyright (C) 2023..2024 Maxjta
+
+ Licensed 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.
+*/
+
+/**
+ * @file TMRv1/at32_tmr7.inc
+ * @brief Shared TMR7 handler.
+ *
+ * @addtogroup AT32_TMR7_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(AT32_HAS_TMR7)
+#error "AT32_HAS_TMR7 not defined in registry"
+#endif
+
+/* Driver checks for robustness, undefined USE macros are defaulted to
+ FALSE. This makes this module independent from drivers implementation.*/
+#if !defined(AT32_GPT_USE_TMR7)
+#define AT32_GPT_USE_TMR7 FALSE
+#endif
+#if !defined(AT32_ICU_USE_TMR7)
+#define AT32_ICU_USE_TMR7 FALSE
+#endif
+#if !defined(AT32_PWM_USE_TMR7)
+#define AT32_PWM_USE_TMR7 FALSE
+#endif
+#if !defined(AT32_ST_USE_TMR7)
+#define AT32_ST_USE_TMR7 FALSE
+#endif
+
+#if AT32_HAS_TMR7
+
+/* Priority settings checks.*/
+#if !defined(AT32_IRQ_TMR7_PRIORITY)
+#error "AT32_IRQ_TMR7_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(AT32_IRQ_TMR7_PRIORITY)
+#error "Invalid IRQ priority assigned to AT32_IRQ_TMR7_PRIORITY"
+#endif
+
+#endif /* AT32_HAS_TMR7 */
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void tmr7_irq_init(void) {
+#if defined(AT32_TMR7_IS_USED)
+ nvicEnableVector(AT32_TMR7_NUMBER, AT32_IRQ_TMR7_PRIORITY);
+#endif
+}
+
+static inline void tmr7_irq_deinit(void) {
+#if defined(AT32_TMR7_IS_USED)
+ nvicDisableVector(AT32_TMR7_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(AT32_TMR7_IS_USED) || defined(__DOXYGEN__)
+/**
+ * @brief TMR7 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_TMR7_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_GPT
+#if AT32_GPT_USE_TMR7
+ gpt_lld_serve_interrupt(&GPTD7);
+#endif
+#endif
+#if HAL_USE_ICU
+#if AT32_ICU_USE_TMR7
+ icu_lld_serve_interrupt(&ICUD7);
+#endif
+#endif
+#if HAL_USE_PWM
+#if AT32_PWM_USE_TMR7
+ pwm_lld_serve_interrupt(&PWMD7);
+#endif
+#endif
+#if 1
+#if AT32_ST_USE_TMR7
+ st_lld_serve_interrupt();
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/os/hal/ports/AT32/LLD/USARTv2/at32_uart4.inc b/os/hal/ports/AT32/LLD/USARTv2/at32_uart4.inc
new file mode 100644
index 0000000000..c07c8ff8c6
--- /dev/null
+++ b/os/hal/ports/AT32/LLD/USARTv2/at32_uart4.inc
@@ -0,0 +1,111 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+ ChibiOS - Copyright (C) 2023..2024 HorrorTroll
+ ChibiOS - Copyright (C) 2023..2024 Zhaqian
+
+ Licensed 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.
+*/
+
+/**
+ * @file USART/at32_uart4.inc
+ * @brief Shared UART4 handler.
+ *
+ * @addtogroup AT32_UART4_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(AT32_HAS_UART4)
+#error "AT32_HAS_UART4 not defined in registry"
+#endif
+
+#if AT32_HAS_UART4
+
+/* Priority settings checks.*/
+#if !defined(AT32_IRQ_UART4_PRIORITY)
+#error "AT32_IRQ_UART4_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(AT32_IRQ_UART4_PRIORITY)
+#error "Invalid IRQ priority assigned to AT32_IRQ_UART4_PRIORITY"
+#endif
+
+#endif /* AT32_HAS_UART4 */
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void uart4_irq_init(void) {
+#if defined(AT32_UART4_IS_USED)
+ nvicEnableVector(AT32_UART4_NUMBER, AT32_IRQ_UART4_PRIORITY);
+#endif
+}
+
+static inline void uart4_irq_deinit(void) {
+#if defined(AT32_UART4_IS_USED)
+ nvicDisableVector(AT32_UART4_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(AT32_UART4_IS_USED) || defined(__DOXYGEN__)
+/**
+ * @brief UART4 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_UART4_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_SERIAL
+#if AT32_SERIAL_USE_UART4
+ sd_lld_serve_interrupt(&SD4);
+#endif
+#endif
+
+#if HAL_USE_UART
+#if AT32_UART_USE_UART4
+ uart_lld_serve_interrupt(&UARTD4);
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/os/hal/ports/AT32/LLD/USARTv2/at32_uart5.inc b/os/hal/ports/AT32/LLD/USARTv2/at32_uart5.inc
new file mode 100644
index 0000000000..fff0dadae3
--- /dev/null
+++ b/os/hal/ports/AT32/LLD/USARTv2/at32_uart5.inc
@@ -0,0 +1,111 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+ ChibiOS - Copyright (C) 2023..2024 HorrorTroll
+ ChibiOS - Copyright (C) 2023..2024 Zhaqian
+
+ Licensed 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.
+*/
+
+/**
+ * @file USART/at32_uart5.inc
+ * @brief Shared UART5 handler.
+ *
+ * @addtogroup AT32_UART5_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(AT32_HAS_UART5)
+#error "AT32_HAS_UART5 not defined in registry"
+#endif
+
+#if AT32_HAS_UART5
+
+/* Priority settings checks.*/
+#if !defined(AT32_IRQ_UART5_PRIORITY)
+#error "AT32_IRQ_UART5_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(AT32_IRQ_UART5_PRIORITY)
+#error "Invalid IRQ priority assigned to AT32_IRQ_UART5_PRIORITY"
+#endif
+
+#endif /* AT32_HAS_UART5 */
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void uart5_irq_init(void) {
+#if defined(AT32_UART5_IS_USED)
+ nvicEnableVector(AT32_UART5_NUMBER, AT32_IRQ_UART5_PRIORITY);
+#endif
+}
+
+static inline void uart5_irq_deinit(void) {
+#if defined(AT32_UART5_IS_USED)
+ nvicDisableVector(AT32_UART5_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(AT32_UART5_IS_USED) || defined(__DOXYGEN__)
+/**
+ * @brief UART5 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_UART5_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_SERIAL
+#if AT32_SERIAL_USE_UART5
+ sd_lld_serve_interrupt(&SD5);
+#endif
+#endif
+
+#if HAL_USE_UART
+#if AT32_UART_USE_UART5
+ uart_lld_serve_interrupt(&UARTD5);
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/os/hal/ports/AT32/LLD/USARTv2/at32_uart7.inc b/os/hal/ports/AT32/LLD/USARTv2/at32_uart7.inc
new file mode 100644
index 0000000000..0ddf35dd0c
--- /dev/null
+++ b/os/hal/ports/AT32/LLD/USARTv2/at32_uart7.inc
@@ -0,0 +1,112 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+ ChibiOS - Copyright (C) 2023..2024 HorrorTroll
+ ChibiOS - Copyright (C) 2023..2024 Zhaqian
+ ChibiOS - Copyright (C) 2023..2024 Maxjta
+
+ Licensed 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.
+*/
+
+/**
+ * @file USART/at32_uart7.inc
+ * @brief Shared UART7 handler.
+ *
+ * @addtogroup AT32_UART7_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(AT32_HAS_UART7)
+#error "AT32_HAS_UART7 not defined in registry"
+#endif
+
+#if AT32_HAS_UART7
+
+/* Priority settings checks.*/
+#if !defined(AT32_IRQ_UART7_PRIORITY)
+#error "AT32_IRQ_UART7_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(AT32_IRQ_UART7_PRIORITY)
+#error "Invalid IRQ priority assigned to AT32_IRQ_UART7_PRIORITY"
+#endif
+
+#endif /* AT32_HAS_UART7 */
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void uart7_irq_init(void) {
+#if defined(AT32_UART7_IS_USED)
+ nvicEnableVector(AT32_UART7_NUMBER, AT32_IRQ_UART7_PRIORITY);
+#endif
+}
+
+static inline void uart7_irq_deinit(void) {
+#if defined(AT32_UART7_IS_USED)
+ nvicDisableVector(AT32_UART7_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(AT32_UART7_IS_USED) || defined(__DOXYGEN__)
+/**
+ * @brief UART7 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_UART7_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_SERIAL
+#if AT32_SERIAL_USE_UART7
+ sd_lld_serve_interrupt(&SD7);
+#endif
+#endif
+
+#if HAL_USE_UART
+#if AT32_UART_USE_UART7
+ uart_lld_serve_interrupt(&UARTD7);
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/os/hal/ports/AT32/LLD/USARTv2/at32_uart8.inc b/os/hal/ports/AT32/LLD/USARTv2/at32_uart8.inc
new file mode 100644
index 0000000000..3ec2763eb4
--- /dev/null
+++ b/os/hal/ports/AT32/LLD/USARTv2/at32_uart8.inc
@@ -0,0 +1,112 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+ ChibiOS - Copyright (C) 2023..2024 HorrorTroll
+ ChibiOS - Copyright (C) 2023..2024 Zhaqian
+ ChibiOS - Copyright (C) 2023..2024 Maxjta
+
+ Licensed 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.
+*/
+
+/**
+ * @file USART/at32_UART8.inc
+ * @brief Shared UART8 handler.
+ *
+ * @addtogroup AT32_UART8_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(AT32_HAS_UART8)
+#error "AT32_HAS_UART8 not defined in registry"
+#endif
+
+#if AT32_HAS_UART8
+
+/* Priority settings checks.*/
+#if !defined(AT32_IRQ_UART8_PRIORITY)
+#error "AT32_IRQ_UART8_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(AT32_IRQ_UART8_PRIORITY)
+#error "Invalid IRQ priority assigned to AT32_IRQ_UART8_PRIORITY"
+#endif
+
+#endif /* AT32_HAS_UART8 */
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void uart8_irq_init(void) {
+#if defined(AT32_UART8_IS_USED)
+ nvicEnableVector(AT32_UART8_NUMBER, AT32_IRQ_UART8_PRIORITY);
+#endif
+}
+
+static inline void uart8_irq_deinit(void) {
+#if defined(AT32_UART8_IS_USED)
+ nvicDisableVector(AT32_UART8_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(AT32_UART8_IS_USED) || defined(__DOXYGEN__)
+/**
+ * @brief UART8 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_UART8_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_SERIAL
+#if AT32_SERIAL_USE_UART8
+ sd_lld_serve_interrupt(&SD8);
+#endif
+#endif
+
+#if HAL_USE_UART
+#if AT32_UART_USE_UART8
+ uart_lld_serve_interrupt(&UARTD8);
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/os/hal/ports/AT32/LLD/USARTv2/at32_usart1.inc b/os/hal/ports/AT32/LLD/USARTv2/at32_usart1.inc
new file mode 100644
index 0000000000..f215b4f7c7
--- /dev/null
+++ b/os/hal/ports/AT32/LLD/USARTv2/at32_usart1.inc
@@ -0,0 +1,111 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+ ChibiOS - Copyright (C) 2023..2024 HorrorTroll
+ ChibiOS - Copyright (C) 2023..2024 Zhaqian
+
+ Licensed 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.
+*/
+
+/**
+ * @file USART/at32_usart1.inc
+ * @brief Shared USART1 handler.
+ *
+ * @addtogroup AT32_USART1_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(AT32_HAS_USART1)
+#error "AT32_HAS_USART1 not defined in registry"
+#endif
+
+#if AT32_HAS_USART1
+
+/* Priority settings checks.*/
+#if !defined(AT32_IRQ_USART1_PRIORITY)
+#error "AT32_IRQ_USART1_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(AT32_IRQ_USART1_PRIORITY)
+#error "Invalid IRQ priority assigned to AT32_IRQ_USART1_PRIORITY"
+#endif
+
+#endif /* AT32_HAS_USART1 */
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void usart1_irq_init(void) {
+#if defined(AT32_USART1_IS_USED)
+ nvicEnableVector(AT32_USART1_NUMBER, AT32_IRQ_USART1_PRIORITY);
+#endif
+}
+
+static inline void usart1_irq_deinit(void) {
+#if defined(AT32_USART1_IS_USED)
+ nvicDisableVector(AT32_USART1_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(AT32_USART1_IS_USED) || defined(__DOXYGEN__)
+/**
+ * @brief USART1 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_USART1_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_SERIAL
+#if AT32_SERIAL_USE_USART1
+ sd_lld_serve_interrupt(&SD1);
+#endif
+#endif
+
+#if HAL_USE_UART
+#if AT32_UART_USE_USART1
+ uart_lld_serve_interrupt(&UARTD1);
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/os/hal/ports/AT32/LLD/USARTv2/at32_usart2.inc b/os/hal/ports/AT32/LLD/USARTv2/at32_usart2.inc
new file mode 100644
index 0000000000..1652352b72
--- /dev/null
+++ b/os/hal/ports/AT32/LLD/USARTv2/at32_usart2.inc
@@ -0,0 +1,111 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+ ChibiOS - Copyright (C) 2023..2024 HorrorTroll
+ ChibiOS - Copyright (C) 2023..2024 Zhaqian
+
+ Licensed 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.
+*/
+
+/**
+ * @file USART/at32_usart2.inc
+ * @brief Shared USART2 handler.
+ *
+ * @addtogroup AT32_USART2_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(AT32_HAS_USART2)
+#error "AT32_HAS_USART2 not defined in registry"
+#endif
+
+#if AT32_HAS_USART2
+
+/* Priority settings checks.*/
+#if !defined(AT32_IRQ_USART2_PRIORITY)
+#error "AT32_IRQ_USART2_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(AT32_IRQ_USART2_PRIORITY)
+#error "Invalid IRQ priority assigned to AT32_IRQ_USART2_PRIORITY"
+#endif
+
+#endif /* AT32_HAS_USART2 */
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void usart2_irq_init(void) {
+#if defined(AT32_USART2_IS_USED)
+ nvicEnableVector(AT32_USART2_NUMBER, AT32_IRQ_USART2_PRIORITY);
+#endif
+}
+
+static inline void usart2_irq_deinit(void) {
+#if defined(AT32_USART2_IS_USED)
+ nvicDisableVector(AT32_USART2_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(AT32_USART2_IS_USED) || defined(__DOXYGEN__)
+/**
+ * @brief USART2 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_USART2_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_SERIAL
+#if AT32_SERIAL_USE_USART2
+ sd_lld_serve_interrupt(&SD2);
+#endif
+#endif
+
+#if HAL_USE_UART
+#if AT32_UART_USE_USART2
+ uart_lld_serve_interrupt(&UARTD2);
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/os/hal/ports/AT32/LLD/USARTv2/at32_usart3.inc b/os/hal/ports/AT32/LLD/USARTv2/at32_usart3.inc
new file mode 100644
index 0000000000..a00a1a09ad
--- /dev/null
+++ b/os/hal/ports/AT32/LLD/USARTv2/at32_usart3.inc
@@ -0,0 +1,111 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+ ChibiOS - Copyright (C) 2023..2024 HorrorTroll
+ ChibiOS - Copyright (C) 2023..2024 Zhaqian
+
+ Licensed 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.
+*/
+
+/**
+ * @file USART/at32_usart3.inc
+ * @brief Shared USART3 handler.
+ *
+ * @addtogroup AT32_USART3_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(AT32_HAS_USART3)
+#error "AT32_HAS_USART3 not defined in registry"
+#endif
+
+#if AT32_HAS_USART3
+
+/* Priority settings checks.*/
+#if !defined(AT32_IRQ_USART3_PRIORITY)
+#error "AT32_IRQ_USART3_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(AT32_IRQ_USART3_PRIORITY)
+#error "Invalid IRQ priority assigned to AT32_IRQ_USART3_PRIORITY"
+#endif
+
+#endif /* AT32_HAS_USART3 */
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void usart3_irq_init(void) {
+#if defined(AT32_USART3_IS_USED)
+ nvicEnableVector(AT32_USART3_NUMBER, AT32_IRQ_USART3_PRIORITY);
+#endif
+}
+
+static inline void usart3_irq_deinit(void) {
+#if defined(AT32_USART3_IS_USED)
+ nvicDisableVector(AT32_USART3_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(AT32_USART3_IS_USED) || defined(__DOXYGEN__)
+/**
+ * @brief USART3 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_USART3_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_SERIAL
+#if AT32_SERIAL_USE_USART3
+ sd_lld_serve_interrupt(&SD3);
+#endif
+#endif
+
+#if HAL_USE_UART
+#if AT32_UART_USE_USART3
+ uart_lld_serve_interrupt(&UARTD3);
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/os/hal/ports/AT32/LLD/USARTv2/at32_usart6.inc b/os/hal/ports/AT32/LLD/USARTv2/at32_usart6.inc
new file mode 100644
index 0000000000..cedbc7a285
--- /dev/null
+++ b/os/hal/ports/AT32/LLD/USARTv2/at32_usart6.inc
@@ -0,0 +1,112 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+ ChibiOS - Copyright (C) 2023..2024 HorrorTroll
+ ChibiOS - Copyright (C) 2023..2024 Zhaqian
+ ChibiOS - Copyright (C) 2024 Maxjta
+
+ Licensed 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.
+*/
+
+/**
+ * @file USART/at32_usart6.inc
+ * @brief Shared USART6 handler.
+ *
+ * @addtogroup AT32_USART6_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(AT32_HAS_USART6)
+#error "AT32_HAS_USART6 not defined in registry"
+#endif
+
+#if AT32_HAS_USART6
+
+/* Priority settings checks.*/
+#if !defined(AT32_IRQ_USART6_PRIORITY)
+#error "AT32_IRQ_USART6_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(AT32_IRQ_USART6_PRIORITY)
+#error "Invalid IRQ priority assigned to AT32_IRQ_USART6_PRIORITY"
+#endif
+
+#endif /* AT32_HAS_USART6 */
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void usart6_irq_init(void) {
+#if defined(AT32_USART6_IS_USED)
+ nvicEnableVector(AT32_USART6_NUMBER, AT32_IRQ_USART6_PRIORITY);
+#endif
+}
+
+static inline void usart6_irq_deinit(void) {
+#if defined(AT32_USART6_IS_USED)
+ nvicDisableVector(AT32_USART6_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(AT32_USART6_IS_USED) || defined(__DOXYGEN__)
+/**
+ * @brief USART6 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_USART6_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_SERIAL
+#if AT32_SERIAL_USE_USART6
+ sd_lld_serve_interrupt(&SD6);
+#endif
+#endif
+
+#if HAL_USE_UART
+#if AT32_UART_USE_USART6
+ uart_lld_serve_interrupt(&UARTD6);
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/os/hal/ports/AT32/LLD/USARTv2/driver.mk b/os/hal/ports/AT32/LLD/USARTv2/driver.mk
new file mode 100644
index 0000000000..65b0977e25
--- /dev/null
+++ b/os/hal/ports/AT32/LLD/USARTv2/driver.mk
@@ -0,0 +1,13 @@
+ifeq ($(USE_SMART_BUILD),yes)
+ifneq ($(findstring HAL_USE_SERIAL TRUE,$(HALCONF)),)
+PLATFORMSRC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/AT32/LLD/USARTv2/hal_serial_lld.c
+endif
+ifneq ($(findstring HAL_USE_UART TRUE,$(HALCONF)),)
+PLATFORMSRC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/AT32/LLD/USARTv2/hal_uart_lld.c
+endif
+else
+PLATFORMSRC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/AT32/LLD/USARTv2/hal_serial_lld.c
+PLATFORMSRC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/AT32/LLD/USARTv2/hal_uart_lld.c
+endif
+
+PLATFORMINC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/AT32/LLD/USARTv2
diff --git a/os/hal/ports/AT32/LLD/USARTv2/hal_serial_lld.c b/os/hal/ports/AT32/LLD/USARTv2/hal_serial_lld.c
new file mode 100644
index 0000000000..ecfbc5fb2b
--- /dev/null
+++ b/os/hal/ports/AT32/LLD/USARTv2/hal_serial_lld.c
@@ -0,0 +1,679 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+ ChibiOS - Copyright (C) 2023..2024 HorrorTroll
+ ChibiOS - Copyright (C) 2023..2024 Zhaqian
+ ChibiOS - Copyright (C) 2023..2024 Maxjta
+
+ Licensed 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.
+*/
+
+/**
+ * @file USARTv2/hal_serial_lld.c
+ * @brief AT32 low level serial driver code.
+ *
+ * @addtogroup SERIAL
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_SERIAL || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief USART1 serial driver identifier.*/
+#if AT32_SERIAL_USE_USART1 || defined(__DOXYGEN__)
+SerialDriver SD1;
+#endif
+
+/** @brief USART2 serial driver identifier.*/
+#if AT32_SERIAL_USE_USART2 || defined(__DOXYGEN__)
+SerialDriver SD2;
+#endif
+
+/** @brief USART3 serial driver identifier.*/
+#if AT32_SERIAL_USE_USART3 || defined(__DOXYGEN__)
+SerialDriver SD3;
+#endif
+
+/** @brief UART4 serial driver identifier.*/
+#if AT32_SERIAL_USE_UART4 || defined(__DOXYGEN__)
+SerialDriver SD4;
+#endif
+
+/** @brief UART5 serial driver identifier.*/
+#if AT32_SERIAL_USE_UART5 || defined(__DOXYGEN__)
+SerialDriver SD5;
+#endif
+
+/** @brief USART6 serial driver identifier.*/
+#if AT32_SERIAL_USE_USART6 || defined(__DOXYGEN__)
+SerialDriver SD6;
+#endif
+
+/** @brief UART7 serial driver identifier.*/
+#if AT32_SERIAL_USE_UART7 || defined(__DOXYGEN__)
+SerialDriver SD7;
+#endif
+
+/** @brief UART8 serial driver identifier.*/
+#if AT32_SERIAL_USE_UART8 || defined(__DOXYGEN__)
+SerialDriver SD8;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/** @brief Driver default configuration.*/
+static const SerialConfig default_config =
+{
+ SERIAL_DEFAULT_BITRATE,
+ 0,
+ USART_CTRL2_STOPBN1_BITS,
+ 0
+};
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief USART initialization.
+ * @details This function must be invoked with interrupts disabled.
+ *
+ * @param[in] sdp pointer to a @p SerialDriver object
+ * @param[in] config the architecture-dependent serial driver configuration
+ */
+static void usart_init(SerialDriver *sdp, const SerialConfig *config) {
+ uint32_t baudr;
+ USART_TypeDef *u = sdp->usart;
+
+ baudr = (uint32_t)((sdp->clock + config->speed/2) / config->speed);
+
+ osalDbgAssert(baudr < 0x10000, "invalid BAUDR value");
+
+ u->BAUDR = baudr;
+
+ /* Note that some bits are enforced.*/
+ u->CTRL2 = config->ctrl2 | USART_CTRL2_BFIEN;
+ u->CTRL3 = config->ctrl3 | USART_CTRL3_ERRIEN;
+ u->CTRL1 = config->ctrl1 | USART_CTRL1_UEN | USART_CTRL1_PERRIEN |
+ USART_CTRL1_RDBFIEN | USART_CTRL1_TEN |
+ USART_CTRL1_REN;
+ u->STS = 0;
+ (void)u->STS; /* STS reset step 1.*/
+ (void)u->DT; /* STS reset step 2.*/
+
+ /* Deciding mask to be applied on the data register on receive, this is
+ required in order to mask out the parity bit.*/
+ if ((config->ctrl1 & (USART_CTRL1_DBN | USART_CTRL1_PEN)) == USART_CTRL1_PEN) {
+ sdp->rxmask = 0x7F;
+ }
+ else {
+ sdp->rxmask = 0xFF;
+ }
+}
+
+/**
+ * @brief USART de-initialization.
+ * @details This function must be invoked with interrupts disabled.
+ *
+ * @param[in] u pointer to an USART I/O block
+ */
+static void usart_deinit(USART_TypeDef *u) {
+
+ u->CTRL1 = 0;
+ u->CTRL2 = 0;
+ u->CTRL3 = 0;
+}
+
+/**
+ * @brief Error handling routine.
+ *
+ * @param[in] sdp pointer to a @p SerialDriver object
+ * @param[in] sts USART STS register value
+ */
+static void set_error(SerialDriver *sdp, uint16_t sts) {
+ eventflags_t status = 0;
+
+ if (sts & USART_STS_ROERR)
+ status |= SD_OVERRUN_ERROR;
+ if (sts & USART_STS_PERR)
+ status |= SD_PARITY_ERROR;
+ if (sts & USART_STS_FERR)
+ status |= SD_FRAMING_ERROR;
+ if (sts & USART_STS_NERR)
+ status |= SD_NOISE_ERROR;
+ chnAddFlagsI(sdp, status);
+}
+
+#if AT32_SERIAL_USE_USART1 || defined(__DOXYGEN__)
+static void notify1(io_queue_t *qp) {
+
+ (void)qp;
+ USART1->CTRL1 |= USART_CTRL1_TDBEIEN | USART_CTRL1_TDCIEN;
+}
+#endif
+
+#if AT32_SERIAL_USE_USART2 || defined(__DOXYGEN__)
+static void notify2(io_queue_t *qp) {
+
+ (void)qp;
+ USART2->CTRL1 |= USART_CTRL1_TDBEIEN | USART_CTRL1_TDCIEN;
+}
+#endif
+
+#if AT32_SERIAL_USE_USART3 || defined(__DOXYGEN__)
+static void notify3(io_queue_t *qp) {
+
+ (void)qp;
+ USART3->CTRL1 |= USART_CTRL1_TDBEIEN | USART_CTRL1_TDCIEN;
+}
+#endif
+
+#if AT32_SERIAL_USE_UART4 || defined(__DOXYGEN__)
+static void notify4(io_queue_t *qp) {
+
+ (void)qp;
+ UART4->CTRL1 |= USART_CTRL1_TDBEIEN | USART_CTRL1_TDCIEN;
+}
+#endif
+
+#if AT32_SERIAL_USE_UART5 || defined(__DOXYGEN__)
+static void notify5(io_queue_t *qp) {
+
+ (void)qp;
+ UART5->CTRL1 |= USART_CTRL1_TDBEIEN | USART_CTRL1_TDCIEN;
+}
+#endif
+
+#if AT32_SERIAL_USE_USART6 || defined(__DOXYGEN__)
+static void notify6(io_queue_t *qp) {
+
+ (void)qp;
+ USART6->CTRL1 |= USART_CTRL1_TDBEIEN | USART_CTRL1_TDCIEN;
+}
+#endif
+
+#if AT32_SERIAL_USE_UART7 || defined(__DOXYGEN__)
+static void notify7(io_queue_t *qp) {
+
+ (void)qp;
+ UART7->CTRL1 |= USART_CTRL1_TDBEIEN | USART_CTRL1_TDCIEN;
+}
+#endif
+
+#if AT32_SERIAL_USE_UART8 || defined(__DOXYGEN__)
+static void notify8(io_queue_t *qp) {
+
+ (void)qp;
+ UART8->CTRL1 |= USART_CTRL1_TDBEIEN | USART_CTRL1_TDCIEN;
+}
+#endif
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if AT32_SERIAL_USE_USART1 || defined(__DOXYGEN__)
+#if !defined(AT32_USART1_SUPPRESS_ISR)
+#if !defined(AT32_USART1_HANDLER)
+#error "AT32_USART1_HANDLER not defined"
+#endif
+/**
+ * @brief USART1 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_USART1_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ sd_lld_serve_interrupt(&SD1);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+#if AT32_SERIAL_USE_USART2 || defined(__DOXYGEN__)
+#if !defined(AT32_USART2_SUPPRESS_ISR)
+#if !defined(AT32_USART2_HANDLER)
+#error "AT32_USART2_HANDLER not defined"
+#endif
+/**
+ * @brief USART2 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_USART2_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ sd_lld_serve_interrupt(&SD2);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+#if AT32_SERIAL_USE_USART3 || defined(__DOXYGEN__)
+#if !defined(AT32_USART3_SUPPRESS_ISR)
+#if !defined(AT32_USART3_HANDLER)
+#error "AT32_USART3_HANDLER not defined"
+#endif
+/**
+ * @brief USART3 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_USART3_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ sd_lld_serve_interrupt(&SD3);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+#if AT32_SERIAL_USE_UART4 || defined(__DOXYGEN__)
+#if !defined(AT32_UART4_SUPPRESS_ISR)
+#if !defined(AT32_UART4_HANDLER)
+#error "AT32_UART4_HANDLER not defined"
+#endif
+/**
+ * @brief UART4 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_UART4_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ sd_lld_serve_interrupt(&SD4);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+#if AT32_SERIAL_USE_UART5 || defined(__DOXYGEN__)
+#if !defined(AT32_UART5_SUPPRESS_ISR)
+#if !defined(AT32_UART5_HANDLER)
+#error "AT32_UART5_HANDLER not defined"
+#endif
+/**
+ * @brief UART5 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_UART5_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ sd_lld_serve_interrupt(&SD5);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+#if AT32_SERIAL_USE_USART6 || defined(__DOXYGEN__)
+#if !defined(AT32_USART6_SUPPRESS_ISR)
+#if !defined(AT32_USART6_HANDLER)
+#error "AT32_USART6_HANDLER not defined"
+#endif
+/**
+ * @brief USART6 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_USART6_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ sd_lld_serve_interrupt(&SD6);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+#if AT32_SERIAL_USE_UART7 || defined(__DOXYGEN__)
+#if !defined(AT32_UART7_SUPPRESS_ISR)
+#if !defined(AT32_UART7_HANDLER)
+#error "AT32_UART7_HANDLER not defined"
+#endif
+/**
+ * @brief UART7 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_UART7_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ sd_lld_serve_interrupt(&SD7);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+#if AT32_SERIAL_USE_UART8 || defined(__DOXYGEN__)
+#if !defined(AT32_UART8_SUPPRESS_ISR)
+#if !defined(AT32_UART8_HANDLER)
+#error "AT32_UART8_HANDLER not defined"
+#endif
+/**
+ * @brief UART8 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_UART8_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ sd_lld_serve_interrupt(&SD8);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level serial driver initialization.
+ *
+ * @notapi
+ */
+void sd_lld_init(void) {
+
+#if AT32_SERIAL_USE_USART1
+ sdObjectInit(&SD1, NULL, notify1);
+ SD1.usart = USART1;
+ SD1.clock = AT32_PCLK2;
+#if !defined(AT32_USART1_SUPPRESS_ISR) && defined(AT32_USART1_NUMBER)
+ nvicEnableVector(AT32_USART1_NUMBER, AT32_SERIAL_USART1_PRIORITY);
+#endif
+#endif
+
+#if AT32_SERIAL_USE_USART2
+ sdObjectInit(&SD2, NULL, notify2);
+ SD2.usart = USART2;
+ SD2.clock = AT32_PCLK1;
+#if !defined(AT32_USART2_SUPPRESS_ISR) && defined(AT32_USART2_NUMBER)
+ nvicEnableVector(AT32_USART2_NUMBER, AT32_SERIAL_USART2_PRIORITY);
+#endif
+#endif
+
+#if AT32_SERIAL_USE_USART3
+ sdObjectInit(&SD3, NULL, notify3);
+ SD3.usart = USART3;
+ SD3.clock = AT32_PCLK1;
+#if !defined(AT32_USART3_SUPPRESS_ISR) && defined(AT32_USART3_NUMBER)
+ nvicEnableVector(AT32_USART3_NUMBER, AT32_SERIAL_USART3_PRIORITY);
+#endif
+#endif
+
+#if AT32_SERIAL_USE_UART4
+ sdObjectInit(&SD4, NULL, notify4);
+ SD4.usart = UART4;
+ SD4.clock = AT32_PCLK1;
+#if !defined(AT32_UART4_SUPPRESS_ISR) && defined(AT32_UART4_NUMBER)
+ nvicEnableVector(AT32_UART4_NUMBER, AT32_SERIAL_UART4_PRIORITY);
+#endif
+#endif
+
+#if AT32_SERIAL_USE_UART5
+ sdObjectInit(&SD5, NULL, notify5);
+ SD5.usart = UART5;
+ SD5.clock = AT32_PCLK1;
+#if !defined(AT32_UART5_SUPPRESS_ISR) && defined(AT32_UART5_NUMBER)
+ nvicEnableVector(AT32_UART5_NUMBER, AT32_SERIAL_UART5_PRIORITY);
+#endif
+#endif
+
+#if AT32_SERIAL_USE_USART6
+ sdObjectInit(&SD6, NULL, notify3);
+ SD6.usart = USART6;
+ SD6.clock = AT32_PCLK2;
+#if !defined(AT32_USART6_SUPPRESS_ISR) && defined(AT32_USART6_NUMBER)
+ nvicEnableVector(AT32_USART6_NUMBER, AT32_SERIAL_USART6_PRIORITY);
+#endif
+#endif
+
+#if AT32_SERIAL_USE_UART7
+ sdObjectInit(&SD7, NULL, notify4);
+ SD7.usart = UART7;
+ SD7.clock = AT32_PCLK1;
+#if !defined(AT32_UART7_SUPPRESS_ISR) && defined(AT32_UART7_NUMBER)
+ nvicEnableVector(AT32_UART7_NUMBER, AT32_SERIAL_UART7_PRIORITY);
+#endif
+#endif
+
+#if AT32_SERIAL_USE_UART8
+ sdObjectInit(&SD8, NULL, notify5);
+ SD8.usart = UART8;
+ SD8.clock = AT32_PCLK1;
+#if !defined(AT32_UART8_SUPPRESS_ISR) && defined(AT32_UART8_NUMBER)
+ nvicEnableVector(AT32_UART8_NUMBER, AT32_SERIAL_UART8_PRIORITY);
+#endif
+#endif
+
+}
+
+/**
+ * @brief Low level serial driver configuration and (re)start.
+ *
+ * @param[in] sdp pointer to a @p SerialDriver object
+ * @param[in] config the architecture-dependent serial driver configuration.
+ * If this parameter is set to @p NULL then a default
+ * configuration is used.
+ *
+ * @notapi
+ */
+void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) {
+
+ if (config == NULL)
+ config = &default_config;
+
+ if (sdp->state == SD_STOP) {
+#if AT32_SERIAL_USE_USART1
+ if (&SD1 == sdp) {
+ crmEnableUSART1(true);
+ }
+#endif
+#if AT32_SERIAL_USE_USART2
+ if (&SD2 == sdp) {
+ crmEnableUSART2(true);
+ }
+#endif
+#if AT32_SERIAL_USE_USART3
+ if (&SD3 == sdp) {
+ crmEnableUSART3(true);
+ }
+#endif
+#if AT32_SERIAL_USE_UART4
+ if (&SD4 == sdp) {
+ crmEnableUART4(true);
+ }
+#endif
+#if AT32_SERIAL_USE_UART5
+ if (&SD5 == sdp) {
+ crmEnableUART5(true);
+ }
+#endif
+#if AT32_SERIAL_USE_USART6
+ if (&SD6 == sdp) {
+ crmEnableUSART6(true);
+ }
+#endif
+#if AT32_SERIAL_USE_UART7
+ if (&SD7 == sdp) {
+ crmEnableUART7(true);
+ }
+#endif
+#if AT32_SERIAL_USE_UART8
+ if (&SD8 == sdp) {
+ crmEnableUART8(true);
+ }
+#endif
+ }
+ usart_init(sdp, config);
+}
+
+/**
+ * @brief Low level serial driver stop.
+ * @details De-initializes the USART, stops the associated clock, resets the
+ * interrupt vector.
+ *
+ * @param[in] sdp pointer to a @p SerialDriver object
+ *
+ * @notapi
+ */
+void sd_lld_stop(SerialDriver *sdp) {
+
+ if (sdp->state == SD_READY) {
+ usart_deinit(sdp->usart);
+#if AT32_SERIAL_USE_USART1
+ if (&SD1 == sdp) {
+ crmDisableUSART1();
+ return;
+ }
+#endif
+#if AT32_SERIAL_USE_USART2
+ if (&SD2 == sdp) {
+ crmDisableUSART2();
+ return;
+ }
+#endif
+#if AT32_SERIAL_USE_USART3
+ if (&SD3 == sdp) {
+ crmDisableUSART3();
+ return;
+ }
+#endif
+#if AT32_SERIAL_USE_UART4
+ if (&SD4 == sdp) {
+ crmDisableUART4();
+ return;
+ }
+#endif
+#if AT32_SERIAL_USE_UART5
+ if (&SD5 == sdp) {
+ crmDisableUART5();
+ return;
+ }
+#endif
+#if AT32_SERIAL_USE_USART6
+ if (&SD6 == sdp) {
+ crmDisableUSART6();
+ return;
+ }
+#endif
+#if AT32_SERIAL_USE_UART7
+ if (&SD7 == sdp) {
+ crmDisableUART7();
+ return;
+ }
+#endif
+#if AT32_SERIAL_USE_UART8
+ if (&SD8 == sdp) {
+ crmDisableUART8();
+ return;
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Common IRQ handler.
+ *
+ * @param[in] sdp communication channel associated to the USART
+ */
+void sd_lld_serve_interrupt(SerialDriver *sdp) {
+ USART_TypeDef *u = sdp->usart;
+ uint16_t ctrl1;
+ uint16_t sts = u->STS;
+
+ /* Special case, LIN break detection.*/
+ if (sts & USART_STS_BFF) {
+ osalSysLockFromISR();
+ chnAddFlagsI(sdp, SD_BREAK_DETECTED);
+ u->STS = ~USART_STS_BFF;
+ osalSysUnlockFromISR();
+ }
+
+ /* Data available.*/
+ osalSysLockFromISR();
+ while (sts & (USART_STS_RDBF | USART_STS_ROERR | USART_STS_NERR | USART_STS_FERR |
+ USART_STS_PERR)) {
+ uint8_t b;
+
+ /* Error condition detection.*/
+ if (sts & (USART_STS_ROERR | USART_STS_NERR | USART_STS_FERR | USART_STS_PERR))
+ set_error(sdp, sts);
+ b = (uint8_t)u->DT & sdp->rxmask;
+ if (sts & USART_STS_RDBF)
+ sdIncomingDataI(sdp, b);
+ sts = u->STS;
+ }
+ osalSysUnlockFromISR();
+
+ /* Caching CTRL1.*/
+ ctrl1 = u->CTRL1;
+
+ /* Transmission buffer empty.*/
+ if ((ctrl1 & USART_CTRL1_TDBEIEN) && (sts & USART_STS_TDBE)) {
+ msg_t b;
+ osalSysLockFromISR();
+ b = oqGetI(&sdp->oqueue);
+ if (b < MSG_OK) {
+ chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
+ ctrl1 &= ~USART_CTRL1_TDBEIEN;
+ }
+ else
+ u->DT = b;
+ osalSysUnlockFromISR();
+ }
+
+ /* Physical transmission end.*/
+ if ((ctrl1 & USART_CTRL1_TDCIEN) && (sts & USART_STS_TDC)) {
+ osalSysLockFromISR();
+ if (oqIsEmptyI(&sdp->oqueue)) {
+ chnAddFlagsI(sdp, CHN_TRANSMISSION_END);
+ ctrl1 &= ~USART_CTRL1_TDCIEN;
+ }
+ osalSysUnlockFromISR();
+ }
+
+ /* Writing CTRL1 once.*/
+ u->CTRL1 = ctrl1;
+}
+
+#endif /* HAL_USE_SERIAL */
+
+/** @} */
diff --git a/os/hal/ports/AT32/LLD/USARTv2/hal_serial_lld.h b/os/hal/ports/AT32/LLD/USARTv2/hal_serial_lld.h
new file mode 100644
index 0000000000..86998e70cd
--- /dev/null
+++ b/os/hal/ports/AT32/LLD/USARTv2/hal_serial_lld.h
@@ -0,0 +1,434 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+ ChibiOS - Copyright (C) 2023..2024 HorrorTroll
+ ChibiOS - Copyright (C) 2023..2024 Zhaqian
+ ChibiOS - Copyright (C) 2023..2024 Maxjta
+
+ Licensed 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.
+*/
+
+/**
+ * @file USARTv2/hal_serial_lld.h
+ * @brief AT32 low level serial driver header.
+ *
+ * @addtogroup SERIAL
+ * @{
+ */
+
+#ifndef HAL_SERIAL_LLD_H
+#define HAL_SERIAL_LLD_H
+
+#if HAL_USE_SERIAL || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief USART1 driver enable switch.
+ * @details If set to @p TRUE the support for USART1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(AT32_SERIAL_USE_USART1) || defined(__DOXYGEN__)
+#define AT32_SERIAL_USE_USART1 FALSE
+#endif
+
+/**
+ * @brief USART2 driver enable switch.
+ * @details If set to @p TRUE the support for USART2 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(AT32_SERIAL_USE_USART2) || defined(__DOXYGEN__)
+#define AT32_SERIAL_USE_USART2 FALSE
+#endif
+
+/**
+ * @brief USART3 driver enable switch.
+ * @details If set to @p TRUE the support for USART3 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(AT32_SERIAL_USE_USART3) || defined(__DOXYGEN__)
+#define AT32_SERIAL_USE_USART3 FALSE
+#endif
+
+/**
+ * @brief UART4 driver enable switch.
+ * @details If set to @p TRUE the support for UART4 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(AT32_SERIAL_USE_UART4) || defined(__DOXYGEN__)
+#define AT32_SERIAL_USE_UART4 FALSE
+#endif
+
+/**
+ * @brief UART5 driver enable switch.
+ * @details If set to @p TRUE the support for UART5 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(AT32_SERIAL_USE_UART5) || defined(__DOXYGEN__)
+#define AT32_SERIAL_USE_UART5 FALSE
+#endif
+
+/**
+ * @brief USART6 driver enable switch.
+ * @details If set to @p TRUE the support for USART6 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(AT32_SERIAL_USE_USART6) || defined(__DOXYGEN__)
+#define AT32_SERIAL_USE_USART6 FALSE
+#endif
+
+/**
+ * @brief UART7 driver enable switch.
+ * @details If set to @p TRUE the support for UART7 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(AT32_SERIAL_USE_UART7) || defined(__DOXYGEN__)
+#define AT32_SERIAL_USE_UART7 FALSE
+#endif
+
+/**
+ * @brief UART8 driver enable switch.
+ * @details If set to @p TRUE the support for UART8 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(AT32_SERIAL_USE_UART8) || defined(__DOXYGEN__)
+#define AT32_SERIAL_USE_UART8 FALSE
+#endif
+
+/**
+ * @brief USART1 interrupt priority level setting.
+ */
+#if !defined(AT32_SERIAL_USART1_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_SERIAL_USART1_PRIORITY 12
+#endif
+
+/**
+ * @brief USART2 interrupt priority level setting.
+ */
+#if !defined(AT32_SERIAL_USART2_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_SERIAL_USART2_PRIORITY 12
+#endif
+
+/**
+ * @brief USART3 interrupt priority level setting.
+ */
+#if !defined(AT32_SERIAL_USART3_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_SERIAL_USART3_PRIORITY 12
+#endif
+
+/**
+ * @brief UART4 interrupt priority level setting.
+ */
+#if !defined(AT32_SERIAL_UART4_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_SERIAL_UART4_PRIORITY 12
+#endif
+
+/**
+ * @brief UART5 interrupt priority level setting.
+ */
+#if !defined(AT32_SERIAL_UART5_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_SERIAL_UART5_PRIORITY 12
+#endif
+
+/**
+ * @brief USART6 interrupt priority level setting.
+ */
+#if !defined(AT32_SERIAL_USART6_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_SERIAL_USART6_PRIORITY 12
+#endif
+
+/**
+ * @brief UART7 interrupt priority level setting.
+ */
+#if !defined(AT32_SERIAL_UART7_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_SERIAL_UART7_PRIORITY 12
+#endif
+
+/**
+ * @brief UART8 interrupt priority level setting.
+ */
+#if !defined(AT32_SERIAL_UART8_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_SERIAL_UART8_PRIORITY 12
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if AT32_SERIAL_USE_USART1 && !AT32_HAS_USART1
+#error "USART1 not present in the selected device"
+#endif
+
+#if AT32_SERIAL_USE_USART2 && !AT32_HAS_USART2
+#error "USART2 not present in the selected device"
+#endif
+
+#if AT32_SERIAL_USE_USART3 && !AT32_HAS_USART3
+#error "USART3 not present in the selected device"
+#endif
+
+#if AT32_SERIAL_USE_UART4 && !AT32_HAS_UART4
+#error "UART4 not present in the selected device"
+#endif
+
+#if AT32_SERIAL_USE_UART5 && !AT32_HAS_UART5
+#error "UART5 not present in the selected device"
+#endif
+
+#if AT32_SERIAL_USE_USART6 && !AT32_HAS_USART6
+#error "USART6 not present in the selected device"
+#endif
+
+#if AT32_SERIAL_USE_UART7 && !AT32_HAS_UART7
+#error "UART7 not present in the selected device"
+#endif
+
+#if AT32_SERIAL_USE_UART8 && !AT32_HAS_UART8
+#error "UART8 not present in the selected device"
+#endif
+
+#if !AT32_SERIAL_USE_USART1 && !AT32_SERIAL_USE_USART2 && \
+ !AT32_SERIAL_USE_USART3 && !AT32_SERIAL_USE_UART4 && \
+ !AT32_SERIAL_USE_UART5 && !AT32_SERIAL_USE_USART6 && \
+ !AT32_SERIAL_USE_UART7 && !AT32_SERIAL_USE_UART8
+#error "SERIAL driver activated but no USART/UART peripheral assigned"
+#endif
+
+#if AT32_SERIAL_USE_USART1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(AT32_SERIAL_USART1_PRIORITY)
+#error "Invalid IRQ priority assigned to USART1"
+#endif
+
+#if AT32_SERIAL_USE_USART2 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(AT32_SERIAL_USART2_PRIORITY)
+#error "Invalid IRQ priority assigned to USART2"
+#endif
+
+#if AT32_SERIAL_USE_USART3 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(AT32_SERIAL_USART3_PRIORITY)
+#error "Invalid IRQ priority assigned to USART3"
+#endif
+
+#if AT32_SERIAL_USE_UART4 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(AT32_SERIAL_UART4_PRIORITY)
+#error "Invalid IRQ priority assigned to UART4"
+#endif
+
+#if AT32_SERIAL_USE_UART5 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(AT32_SERIAL_UART5_PRIORITY)
+#error "Invalid IRQ priority assigned to UART5"
+#endif
+
+#if AT32_SERIAL_USE_USART6 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(AT32_SERIAL_USART6_PRIORITY)
+#error "Invalid IRQ priority assigned to USART6"
+#endif
+
+#if AT32_SERIAL_USE_UART7 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(AT32_SERIAL_UART7_PRIORITY)
+#error "Invalid IRQ priority assigned to UART7"
+#endif
+
+#if AT32_SERIAL_USE_UART8 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(AT32_SERIAL_UART8_PRIORITY)
+#error "Invalid IRQ priority assigned to UART8"
+#endif
+
+/* Checks on allocation of USARTx units.*/
+#if AT32_SERIAL_USE_USART1
+#if defined(AT32_USART1_IS_USED)
+#error "SD1 requires USART1 but it is already used"
+#else
+#define AT32_USART1_IS_USED
+#endif
+#endif
+
+#if AT32_SERIAL_USE_USART2
+#if defined(AT32_USART2_IS_USED)
+#error "SD2 requires USART2 but it is already used"
+#else
+#define AT32_USART2_IS_USED
+#endif
+#endif
+
+#if AT32_SERIAL_USE_USART3
+#if defined(AT32_USART3_IS_USED)
+#error "SD3 requires USART3 but it is already used"
+#else
+#define AT32_USART3_IS_USED
+#endif
+#endif
+
+#if AT32_SERIAL_USE_UART4
+#if defined(AT32_UART4_IS_USED)
+#error "SD4 requires UART4 but it is already used"
+#else
+#define AT32_UART4_IS_USED
+#endif
+#endif
+
+#if AT32_SERIAL_USE_UART5
+#if defined(AT32_UART5_IS_USED)
+#error "SD5 requires UART5 but it is already used"
+#else
+#define AT32_UART5_IS_USED
+#endif
+#endif
+
+#if AT32_SERIAL_USE_USART6
+#if defined(AT32_USART6_IS_USED)
+#error "SD6 requires USART6 but it is already used"
+#else
+#define AT32_USART6_IS_USED
+#endif
+#endif
+
+#if AT32_SERIAL_USE_UART7
+#if defined(AT32_UART7_IS_USED)
+#error "SD7 requires UART7 but it is already used"
+#else
+#define AT32_UART7_IS_USED
+#endif
+#endif
+
+#if AT32_SERIAL_USE_UART8
+#if defined(AT32_UART8_IS_USED)
+#error "SD8 requires UART8 but it is already used"
+#else
+#define AT32_UART8_IS_USED
+#endif
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief AT32 Serial Driver configuration structure.
+ * @details An instance of this structure must be passed to @p sdStart()
+ * in order to configure and start a serial driver operations.
+ * @note This structure content is architecture dependent, each driver
+ * implementation defines its own version and the custom static
+ * initializers.
+ */
+typedef struct hal_serial_config {
+ /**
+ * @brief Bit rate.
+ */
+ uint32_t speed;
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Initialization value for the CTRL1 register.
+ */
+ uint16_t ctrl1;
+ /**
+ * @brief Initialization value for the CTRL2 register.
+ */
+ uint16_t ctrl2;
+ /**
+ * @brief Initialization value for the CTRL3 register.
+ */
+ uint16_t ctrl3;
+} SerialConfig;
+
+/**
+ * @brief @p SerialDriver specific data.
+ */
+#define _serial_driver_data \
+ _base_asynchronous_channel_data \
+ /* Driver state.*/ \
+ sdstate_t state; \
+ /* Input queue.*/ \
+ input_queue_t iqueue; \
+ /* Output queue.*/ \
+ output_queue_t oqueue; \
+ /* Input circular buffer.*/ \
+ uint8_t ib[SERIAL_BUFFERS_SIZE]; \
+ /* Output circular buffer.*/ \
+ uint8_t ob[SERIAL_BUFFERS_SIZE]; \
+ /* End of the mandatory fields.*/ \
+ /* Pointer to the USART registers block.*/ \
+ USART_TypeDef *usart; \
+ /* Clock frequency for the associated USART/UART.*/ \
+ uint32_t clock; \
+ /* Mask to be applied on received frames.*/ \
+ uint8_t rxmask;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*
+ * Extra USARTs definitions here (missing from the AT header file).
+ */
+#define USART_CTRL2_STOPBN1_BITS (0 << 12) /**< @brief CTRL2 1 stop bit value.*/
+#define USART_CTRL2_STOPBN0P5_BITS (1 << 12) /**< @brief CTRL2 0.5 stop bit value.*/
+#define USART_CTRL2_STOPBN2_BITS (2 << 12) /**< @brief CTRL2 2 stop bit value.*/
+#define USART_CTRL2_STOPBN1P5_BITS (3 << 12) /**< @brief CTRL2 1.5 stop bit value.*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if AT32_SERIAL_USE_USART1 && !defined(__DOXYGEN__)
+extern SerialDriver SD1;
+#endif
+#if AT32_SERIAL_USE_USART2 && !defined(__DOXYGEN__)
+extern SerialDriver SD2;
+#endif
+#if AT32_SERIAL_USE_USART3 && !defined(__DOXYGEN__)
+extern SerialDriver SD3;
+#endif
+#if AT32_SERIAL_USE_UART4 && !defined(__DOXYGEN__)
+extern SerialDriver SD4;
+#endif
+#if AT32_SERIAL_USE_UART5 && !defined(__DOXYGEN__)
+extern SerialDriver SD5;
+#endif
+#if AT32_SERIAL_USE_USART6 && !defined(__DOXYGEN__)
+extern SerialDriver SD6;
+#endif
+#if AT32_SERIAL_USE_UART7 && !defined(__DOXYGEN__)
+extern SerialDriver SD7;
+#endif
+#if AT32_SERIAL_USE_UART8 && !defined(__DOXYGEN__)
+extern SerialDriver SD8;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void sd_lld_init(void);
+ void sd_lld_start(SerialDriver *sdp, const SerialConfig *config);
+ void sd_lld_stop(SerialDriver *sdp);
+ void sd_lld_serve_interrupt(SerialDriver *sdp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_SERIAL */
+
+#endif /* HAL_SERIAL_LLD_H */
+
+/** @} */
diff --git a/os/hal/ports/AT32/LLD/USARTv2/hal_uart_lld.c b/os/hal/ports/AT32/LLD/USARTv2/hal_uart_lld.c
new file mode 100644
index 0000000000..a8c507490c
--- /dev/null
+++ b/os/hal/ports/AT32/LLD/USARTv2/hal_uart_lld.c
@@ -0,0 +1,983 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+ ChibiOS - Copyright (C) 2023..2024 HorrorTroll
+ ChibiOS - Copyright (C) 2023..2024 Zhaqian
+ ChibiOS - Copyright (C) 2023..2024 Maxjta
+
+ Licensed 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.
+*/
+
+/**
+ * @file USARTv2/hal_uart_lld.c
+ * @brief AT32 low level UART driver code.
+ *
+ * @addtogroup UART
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_UART || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#define AT32_UART_CTRL2_CHECK_MASK \
+ (USART_CTRL2_STOP_0 | USART_CTRL2_CLKEN | USART_CTRL2_CLKPOL | \
+ USART_CTRL2_CLKPHA | USART_CTRL2_LBCP)
+
+#define AT32_UART_CTRL3_CHECK_MASK \
+ (USART_CTRL3_CTSCFIEN | USART_CTRL3_CTSEN | USART_CTRL3_RTSEN | \
+ USART_CTRL3_SCMEN | USART_CTRL3_SCNACKEN)
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief USART1 UART driver identifier.*/
+#if AT32_UART_USE_USART1 || defined(__DOXYGEN__)
+UARTDriver UARTD1;
+#endif
+
+/** @brief USART2 UART driver identifier.*/
+#if AT32_UART_USE_USART2 || defined(__DOXYGEN__)
+UARTDriver UARTD2;
+#endif
+
+/** @brief USART3 UART driver identifier.*/
+#if AT32_UART_USE_USART3 || defined(__DOXYGEN__)
+UARTDriver UARTD3;
+#endif
+
+/** @brief UART4 UART driver identifier.*/
+#if AT32_UART_USE_UART4 || defined(__DOXYGEN__)
+UARTDriver UARTD4;
+#endif
+
+/** @brief UART5 UART driver identifier.*/
+#if AT32_UART_USE_UART5 || defined(__DOXYGEN__)
+UARTDriver UARTD5;
+#endif
+
+/** @brief USART6 UART driver identifier.*/
+#if AT32_UART_USE_USART6 || defined(__DOXYGEN__)
+UARTDriver UARTD6;
+#endif
+
+/** @brief UART7 UART driver identifier.*/
+#if AT32_UART_USE_UART7 || defined(__DOXYGEN__)
+UARTDriver UARTD7;
+#endif
+
+/** @brief UART8 UART driver identifier.*/
+#if AT32_UART_USE_UART8 || defined(__DOXYGEN__)
+UARTDriver UARTD8;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Status bits translation.
+ *
+ * @param[in] sts USART STS register value
+ *
+ * @return The error flags.
+ */
+static uartflags_t translate_errors(uint16_t sts) {
+ uartflags_t status = 0;
+
+ if (sts & USART_STS_ROERR)
+ status |= UART_OVERRUN_ERROR;
+ if (sts & USART_STS_PERR)
+ status |= UART_PARITY_ERROR;
+ if (sts & USART_STS_FERR)
+ status |= UART_FRAMING_ERROR;
+ if (sts & USART_STS_NERR)
+ status |= UART_NOISE_ERROR;
+ if (sts & USART_STS_BFF)
+ status |= UART_BREAK_DETECTED;
+ return status;
+}
+
+/**
+ * @brief Puts the receiver in the UART_RX_IDLE state.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ */
+static void uart_enter_rx_idle_loop(UARTDriver *uartp) {
+ uint32_t mode;
+
+ /* RX DMA channel preparation, if the char callback is defined then the
+ FDTIEN interrupt is enabled too.*/
+ if (uartp->config->rxchar_cb == NULL)
+ mode = AT32_DMA_CCTRL_DTD_P2M | AT32_DMA_CCTRL_LM;
+ else
+ mode = AT32_DMA_CCTRL_DTD_P2M | AT32_DMA_CCTRL_LM | AT32_DMA_CCTRL_FDTIEN;
+ dmaStreamSetMemory0(uartp->dmarx, &uartp->rxbuf);
+ dmaStreamSetTransactionSize(uartp->dmarx, 1);
+ dmaStreamSetMode(uartp->dmarx, uartp->dmarxmode | mode);
+ dmaStreamEnable(uartp->dmarx);
+}
+
+/**
+ * @brief USART de-initialization.
+ * @details This function must be invoked with interrupts disabled.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ */
+static void usart_stop(UARTDriver *uartp) {
+
+ /* Stops RX and TX DMA channels.*/
+ dmaStreamDisable(uartp->dmarx);
+ dmaStreamDisable(uartp->dmatx);
+
+ /* Stops USART operations.*/
+ uartp->usart->CTRL1 = 0;
+ uartp->usart->CTRL2 = 0;
+ uartp->usart->CTRL3 = 0;
+}
+
+/**
+ * @brief USART initialization.
+ * @details This function must be invoked with interrupts disabled.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ */
+static void usart_start(UARTDriver *uartp) {
+ uint32_t baudr;
+ uint16_t ctrl1;
+ USART_TypeDef *u = uartp->usart;
+
+ /* Defensive programming, starting from a clean state.*/
+ usart_stop(uartp);
+
+ /* Baud rate setting.*/
+ baudr = (uint32_t)((uartp->clock + uartp->config->speed/2) / uartp->config->speed);
+ u->BAUDR = baudr;
+
+ /* Resetting eventual pending status flags.*/
+ (void)u->STS; /* STS reset step 1.*/
+ (void)u->DT; /* STS reset step 2.*/
+ u->STS = 0;
+
+ /* Note that some bits are enforced because required for correct driver
+ operations.*/
+ u->CTRL2 = uartp->config->ctrl2 | USART_CTRL2_BFIEN;
+ u->CTRL3 = uartp->config->ctrl3 | USART_CTRL3_DMATEN | USART_CTRL3_DMAREN |
+ USART_CTRL3_ERRIEN;
+
+ /* Mustn't ever set FDTIEN here - if done, it causes an immediate
+ interrupt.*/
+ ctrl1 = USART_CTRL1_UEN | USART_CTRL1_PERRIEN | USART_CTRL1_TEN | USART_CTRL1_REN;
+ u->CTRL1 = uartp->config->ctrl1 | ctrl1;
+
+ /* Starting the receiver idle loop.*/
+ uart_enter_rx_idle_loop(uartp);
+}
+
+/**
+ * @brief RX DMA common service routine.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void uart_lld_serve_rx_end_irq(UARTDriver *uartp, uint32_t flags) {
+
+ /* DMA errors handling.*/
+#if defined(AT32_UART_DMA_ERROR_HOOK)
+ if ((flags & AT32_DMA_STS_DTERRF) != 0) {
+ AT32_UART_DMA_ERROR_HOOK(uartp);
+ }
+#else
+ (void)flags;
+#endif
+
+ if (uartp->rxstate == UART_RX_IDLE) {
+ /* Receiver in idle state, a callback is generated, if enabled, for each
+ received character and then the driver stays in the same state.*/
+ _uart_rx_idle_code(uartp);
+ }
+ else {
+ /* Receiver in active state, a callback is generated, if enabled, after
+ a completed transfer.*/
+ dmaStreamDisable(uartp->dmarx);
+ _uart_rx_complete_isr_code(uartp);
+ }
+}
+
+/**
+ * @brief TX DMA common service routine.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void uart_lld_serve_tx_end_irq(UARTDriver *uartp, uint32_t flags) {
+
+ /* DMA errors handling.*/
+#if defined(AT32_UART_DMA_ERROR_HOOK)
+ if ((flags & AT32_DMA_STS_DTERRF) != 0) {
+ AT32_UART_DMA_ERROR_HOOK(uartp);
+ }
+#else
+ (void)flags;
+#endif
+
+ dmaStreamDisable(uartp->dmatx);
+
+ /* A callback is generated, if enabled, after a completed transfer.*/
+ _uart_tx1_isr_code(uartp);
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if AT32_UART_USE_USART1 || defined(__DOXYGEN__)
+#if !defined(AT32_USART1_SUPPRESS_ISR)
+#if !defined(AT32_USART1_HANDLER)
+#error "AT32_USART1_HANDLER not defined"
+#endif
+/**
+ * @brief USART1 IRQ handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_USART1_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ uart_lld_serve_interrupt(&UARTD1);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif /* AT32_UART_USE_USART1 */
+
+#if AT32_UART_USE_USART2 || defined(__DOXYGEN__)
+#if !defined(AT32_USART2_SUPPRESS_ISR)
+#if !defined(AT32_USART2_HANDLER)
+#error "AT32_USART2_HANDLER not defined"
+#endif
+/**
+ * @brief USART2 IRQ handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_USART2_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ uart_lld_serve_interrupt(&UARTD2);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif /* AT32_UART_USE_USART2 */
+
+#if AT32_UART_USE_USART3 || defined(__DOXYGEN__)
+#if !defined(AT32_USART3_SUPPRESS_ISR)
+#if !defined(AT32_USART3_HANDLER)
+#error "AT32_USART3_HANDLER not defined"
+#endif
+/**
+ * @brief USART3 IRQ handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_USART3_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ uart_lld_serve_interrupt(&UARTD3);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif /* AT32_UART_USE_USART3 */
+
+#if AT32_UART_USE_UART4 || defined(__DOXYGEN__)
+#if !defined(AT32_UART4_SUPPRESS_ISR)
+#if !defined(AT32_UART4_HANDLER)
+#error "AT32_UART4_HANDLER not defined"
+#endif
+/**
+ * @brief UART4 IRQ handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_UART4_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ uart_lld_serve_interrupt(&UARTD4);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif /* AT32_UART_USE_UART4 */
+
+#if AT32_UART_USE_UART5 || defined(__DOXYGEN__)
+#if !defined(AT32_UART5_SUPPRESS_ISR)
+#if !defined(AT32_UART5_HANDLER)
+#error "AT32_UART5_HANDLER not defined"
+#endif
+/**
+ * @brief UART5 IRQ handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_UART5_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ uart_lld_serve_interrupt(&UARTD5);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif /* AT32_UART_USE_UART5 */
+
+#if AT32_UART_USE_USART6 || defined(__DOXYGEN__)
+#if !defined(AT32_USART6_SUPPRESS_ISR)
+#if !defined(AT32_USART6_HANDLER)
+#error "AT32_USART6_HANDLER not defined"
+#endif
+/**
+ * @brief USART6 IRQ handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_USART6_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ uart_lld_serve_interrupt(&UARTD6);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif /* AT32_UART_USE_USART6 */
+
+#if AT32_UART_USE_UART7 || defined(__DOXYGEN__)
+#if !defined(AT32_UART7_SUPPRESS_ISR)
+#if !defined(AT32_UART7_HANDLER)
+#error "AT32_UART7_HANDLER not defined"
+#endif
+/**
+ * @brief UART7 IRQ handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_UART7_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ uart_lld_serve_interrupt(&UARTD7);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif /* AT32_UART_USE_UART7 */
+
+#if AT32_UART_USE_UART8 || defined(__DOXYGEN__)
+#if !defined(AT32_UART8_SUPPRESS_ISR)
+#if !defined(AT32_UART8_HANDLER)
+#error "AT32_UART8_HANDLER not defined"
+#endif
+/**
+ * @brief UART5 IRQ handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(AT32_UART8_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ uart_lld_serve_interrupt(&UARTD8);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif /* AT32_UART_USE_UART5 */
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level UART driver initialization.
+ *
+ * @notapi
+ */
+void uart_lld_init(void) {
+
+#if AT32_UART_USE_USART1
+ uartObjectInit(&UARTD1);
+ UARTD1.usart = USART1;
+ UARTD1.clock = AT32_PCLK2;
+ UARTD1.dmarxmode = AT32_DMA_CCTRL_DTERRIEN;
+ UARTD1.dmatxmode = AT32_DMA_CCTRL_DTERRIEN;
+ UARTD1.dmarx = NULL;
+ UARTD1.dmatx = NULL;
+#endif
+
+#if AT32_UART_USE_USART2
+ uartObjectInit(&UARTD2);
+ UARTD2.usart = USART2;
+ UARTD2.clock = AT32_PCLK1;
+ UARTD2.dmarxmode = AT32_DMA_CCTRL_DTERRIEN;
+ UARTD2.dmatxmode = AT32_DMA_CCTRL_DTERRIEN;
+ UARTD2.dmarx = NULL;
+ UARTD2.dmatx = NULL;
+#endif
+
+#if AT32_UART_USE_USART3
+ uartObjectInit(&UARTD3);
+ UARTD3.usart = USART3;
+ UARTD3.clock = AT32_PCLK1;
+ UARTD3.dmarxmode = AT32_DMA_CCTRL_DTERRIEN;
+ UARTD3.dmatxmode = AT32_DMA_CCTRL_DTERRIEN;
+ UARTD3.dmarx = NULL;
+ UARTD3.dmatx = NULL;
+#endif
+
+#if AT32_UART_USE_UART4
+ uartObjectInit(&UARTD4);
+ UARTD4.usart = UART4;
+ UARTD4.clock = AT32_PCLK1;
+ UARTD4.dmarxmode = AT32_DMA_CCTRL_DTERRIEN;
+ UARTD4.dmatxmode = AT32_DMA_CCTRL_DTERRIEN;
+ UARTD4.dmarx = NULL;
+ UARTD4.dmatx = NULL;
+#endif
+
+#if AT32_UART_USE_UART5
+ uartObjectInit(&UARTD5);
+ UARTD5.usart = UART5;
+ UARTD5.clock = AT32_PCLK1;
+ UARTD5.dmarxmode = AT32_DMA_CCTRL_DTERRIEN;
+ UARTD5.dmatxmode = AT32_DMA_CCTRL_DTERRIEN;
+ UARTD5.dmarx = NULL;
+ UARTD5.dmatx = NULL;
+#endif
+
+#if AT32_UART_USE_USART6
+ uartObjectInit(&UARTD6);
+ UARTD6.usart = USART6;
+ UARTD6.clock = AT32_PCLK2;
+ UARTD6.dmarxmode = AT32_DMA_CCTRL_DTERRIEN;
+ UARTD6.dmatxmode = AT32_DMA_CCTRL_DTERRIEN;
+ UARTD6.dmarx = NULL;
+ UARTD6.dmatx = NULL;
+#endif
+
+#if AT32_UART_USE_UART7
+ uartObjectInit(&UARTD7);
+ UARTD7.usart = UART7;
+ UARTD7.clock = AT32_PCLK1;
+ UARTD7.dmarxmode = AT32_DMA_CCTRL_DTERRIEN;
+ UARTD7.dmatxmode = AT32_DMA_CCTRL_DTERRIEN;
+ UARTD7.dmarx = NULL;
+ UARTD7.dmatx = NULL;
+#endif
+
+#if AT32_UART_USE_UART8
+ uartObjectInit(&UARTD8);
+ UARTD8.usart = UART8;
+ UARTD8.clock = AT32_PCLK1;
+ UARTD8.dmarxmode = AT32_DMA_CCTRL_DTERRIEN;
+ UARTD8.dmatxmode = AT32_DMA_CCTRL_DTERRIEN;
+ UARTD8.dmarx = NULL;
+ UARTD8.dmatx = NULL;
+#endif
+}
+
+/**
+ * @brief Configures and activates the UART peripheral.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ *
+ * @notapi
+ */
+void uart_lld_start(UARTDriver *uartp) {
+
+ if (uartp->state == UART_STOP) {
+#if AT32_UART_USE_USART1
+ if (&UARTD1 == uartp) {
+ uartp->dmarx = dmaStreamAllocI(AT32_UART_USART1_RX_DMA_STREAM,
+ AT32_UART_USART1_IRQ_PRIORITY,
+ (at32_dmasts_t)uart_lld_serve_rx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream");
+ uartp->dmatx = dmaStreamAllocI(AT32_UART_USART1_TX_DMA_STREAM,
+ AT32_UART_USART1_IRQ_PRIORITY,
+ (at32_dmasts_t)uart_lld_serve_tx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream");
+
+#if AT32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(uartp->dmarx, AT32_DMAMUX_USART1_RX);
+ dmaSetRequestSource(uartp->dmatx, AT32_DMAMUX_USART1_TX);
+#endif
+
+ crmEnableUSART1(true);
+ nvicEnableVector(AT32_USART1_NUMBER, AT32_UART_USART1_IRQ_PRIORITY);
+ uartp->dmarxmode |= AT32_DMA_CCTRL_CHPL(AT32_UART_USART1_DMA_PRIORITY);
+ uartp->dmatxmode |= AT32_DMA_CCTRL_CHPL(AT32_UART_USART1_DMA_PRIORITY);
+ }
+#endif
+
+#if AT32_UART_USE_USART2
+ if (&UARTD2 == uartp) {
+ uartp->dmarx = dmaStreamAllocI(AT32_UART_USART2_RX_DMA_STREAM,
+ AT32_UART_USART2_IRQ_PRIORITY,
+ (at32_dmasts_t)uart_lld_serve_rx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream");
+ uartp->dmatx = dmaStreamAllocI(AT32_UART_USART2_TX_DMA_STREAM,
+ AT32_UART_USART2_IRQ_PRIORITY,
+ (at32_dmasts_t)uart_lld_serve_tx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream");
+
+#if AT32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(uartp->dmarx, AT32_DMAMUX_USART2_RX);
+ dmaSetRequestSource(uartp->dmatx, AT32_DMAMUX_USART2_TX);
+#endif
+
+ crmEnableUSART2(true);
+ nvicEnableVector(AT32_USART2_NUMBER, AT32_UART_USART2_IRQ_PRIORITY);
+ uartp->dmarxmode |= AT32_DMA_CCTRL_CHPL(AT32_UART_USART2_DMA_PRIORITY);
+ uartp->dmatxmode |= AT32_DMA_CCTRL_CHPL(AT32_UART_USART2_DMA_PRIORITY);
+ }
+#endif
+
+#if AT32_UART_USE_USART3
+ if (&UARTD3 == uartp) {
+ uartp->dmarx = dmaStreamAllocI(AT32_UART_USART3_RX_DMA_STREAM,
+ AT32_UART_USART3_IRQ_PRIORITY,
+ (at32_dmasts_t)uart_lld_serve_rx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream");
+ uartp->dmatx = dmaStreamAllocI(AT32_UART_USART3_TX_DMA_STREAM,
+ AT32_UART_USART3_IRQ_PRIORITY,
+ (at32_dmasts_t)uart_lld_serve_tx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream");
+
+#if AT32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(uartp->dmarx, AT32_DMAMUX_USART3_RX);
+ dmaSetRequestSource(uartp->dmatx, AT32_DMAMUX_USART3_TX);
+#endif
+
+ crmEnableUSART3(true);
+ nvicEnableVector(AT32_USART3_NUMBER, AT32_UART_USART3_IRQ_PRIORITY);
+ uartp->dmarxmode |= AT32_DMA_CCTRL_CHPL(AT32_UART_USART3_DMA_PRIORITY);
+ uartp->dmatxmode |= AT32_DMA_CCTRL_CHPL(AT32_UART_USART3_DMA_PRIORITY);
+ }
+#endif
+
+#if AT32_UART_USE_UART4
+ if (&UARTD4 == uartp) {
+
+ osalDbgAssert((uartp->config->ctrl2 & AT32_UART_CTRL2_CHECK_MASK) == 0,
+ "specified invalid bits in UART4 CTRL2 register settings");
+ osalDbgAssert((uartp->config->ctrl3 & AT32_UART_CTRL3_CHECK_MASK) == 0,
+ "specified invalid bits in UART4 CTRL3 register settings");
+
+ uartp->dmarx = dmaStreamAllocI(AT32_UART_UART4_RX_DMA_STREAM,
+ AT32_UART_UART4_IRQ_PRIORITY,
+ (at32_dmasts_t)uart_lld_serve_rx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream");
+ uartp->dmatx = dmaStreamAllocI(AT32_UART_UART4_TX_DMA_STREAM,
+ AT32_UART_UART4_IRQ_PRIORITY,
+ (at32_dmasts_t)uart_lld_serve_tx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream");
+
+#if AT32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(uartp->dmarx, AT32_DMAMUX_UART4_RX);
+ dmaSetRequestSource(uartp->dmatx, AT32_DMAMUX_UART4_TX);
+#endif
+
+ crmEnableUART4(true);
+ nvicEnableVector(AT32_UART4_NUMBER, AT32_UART_UART4_IRQ_PRIORITY);
+ uartp->dmarxmode |= AT32_DMA_CCTRL_CHPL(AT32_UART_UART4_DMA_PRIORITY);
+ uartp->dmatxmode |= AT32_DMA_CCTRL_CHPL(AT32_UART_UART4_DMA_PRIORITY);
+ }
+#endif
+
+#if AT32_UART_USE_UART5
+ if (&UARTD5 == uartp) {
+
+ osalDbgAssert((uartp->config->ctrl2 & AT32_UART_CTRL2_CHECK_MASK) == 0,
+ "specified invalid bits in UART5 CTRL2 register settings");
+ osalDbgAssert((uartp->config->ctrl3 & AT32_UART_CTRL3_CHECK_MASK) == 0,
+ "specified invalid bits in UART5 CTRL3 register settings");
+
+ uartp->dmarx = dmaStreamAllocI(AT32_UART_UART5_RX_DMA_STREAM,
+ AT32_UART_UART5_IRQ_PRIORITY,
+ (at32_dmasts_t)uart_lld_serve_rx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream");
+ uartp->dmatx = dmaStreamAllocI(AT32_UART_UART5_TX_DMA_STREAM,
+ AT32_UART_UART5_IRQ_PRIORITY,
+ (at32_dmasts_t)uart_lld_serve_tx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream");
+
+#if AT32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(uartp->dmarx, AT32_DMAMUX_UART5_RX);
+ dmaSetRequestSource(uartp->dmatx, AT32_DMAMUX_UART5_TX);
+#endif
+
+ crmEnableUART5(true);
+ nvicEnableVector(AT32_UART5_NUMBER, AT32_UART_UART5_IRQ_PRIORITY);
+ uartp->dmarxmode |= AT32_DMA_CCTRL_CHPL(AT32_UART_UART5_DMA_PRIORITY);
+ uartp->dmatxmode |= AT32_DMA_CCTRL_CHPL(AT32_UART_UART5_DMA_PRIORITY);
+ }
+#endif
+
+#if AT32_UART_USE_USART6
+ if (&UARTD6 == uartp) {
+ uartp->dmarx = dmaStreamAllocI(AT32_UART_USART6_RX_DMA_STREAM,
+ AT32_UART_USART6_IRQ_PRIORITY,
+ (at32_dmasts_t)uart_lld_serve_rx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream");
+ uartp->dmatx = dmaStreamAllocI(AT32_UART_USART6_TX_DMA_STREAM,
+ AT32_UART_USART6_IRQ_PRIORITY,
+ (at32_dmasts_t)uart_lld_serve_tx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream");
+
+#if AT32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(uartp->dmarx, AT32_DMAMUX_USART6_RX);
+ dmaSetRequestSource(uartp->dmatx, AT32_DMAMUX_USART6_TX);
+#endif
+
+ crmEnableUSART6(true);
+ nvicEnableVector(AT32_USART6_NUMBER, AT32_UART_USART6_IRQ_PRIORITY);
+ uartp->dmarxmode |= AT32_DMA_CCTRL_CHPL(AT32_UART_USART6_DMA_PRIORITY);
+ uartp->dmatxmode |= AT32_DMA_CCTRL_CHPL(AT32_UART_USART6_DMA_PRIORITY);
+ }
+#endif
+
+#if AT32_UART_USE_UART7
+ if (&UARTD7 == uartp) {
+
+ osalDbgAssert((uartp->config->ctrl2 & AT32_UART_CTRL2_CHECK_MASK) == 0,
+ "specified invalid bits in UART7 CTRL2 register settings");
+ osalDbgAssert((uartp->config->ctrl3 & AT32_UART_CTRL3_CHECK_MASK) == 0,
+ "specified invalid bits in UART7 CTRL3 register settings");
+
+ uartp->dmarx = dmaStreamAllocI(AT32_UART_UART7_RX_DMA_STREAM,
+ AT32_UART_UART7_IRQ_PRIORITY,
+ (at32_dmasts_t)uart_lld_serve_rx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream");
+ uartp->dmatx = dmaStreamAllocI(AT32_UART_UART7_TX_DMA_STREAM,
+ AT32_UART_UART7_IRQ_PRIORITY,
+ (at32_dmasts_t)uart_lld_serve_tx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream");
+
+#if AT32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(uartp->dmarx, AT32_DMAMUX_UART7_RX);
+ dmaSetRequestSource(uartp->dmatx, AT32_DMAMUX_UART7_TX);
+#endif
+
+ crmEnableUART7(true);
+ nvicEnableVector(AT32_UART7_NUMBER, AT32_UART_UART7_IRQ_PRIORITY);
+ uartp->dmarxmode |= AT32_DMA_CCTRL_CHPL(AT32_UART_UART7_DMA_PRIORITY);
+ uartp->dmatxmode |= AT32_DMA_CCTRL_CHPL(AT32_UART_UART7_DMA_PRIORITY);
+ }
+#endif
+
+#if AT32_UART_USE_UART8
+ if (&UARTD8 == uartp) {
+
+ osalDbgAssert((uartp->config->ctrl2 & AT32_UART_CTRL2_CHECK_MASK) == 0,
+ "specified invalid bits in UART8 CTRL2 register settings");
+ osalDbgAssert((uartp->config->ctrl3 & AT32_UART_CTRL3_CHECK_MASK) == 0,
+ "specified invalid bits in UART8 CTRL3 register settings");
+
+ uartp->dmarx = dmaStreamAllocI(AT32_UART_UART8_RX_DMA_STREAM,
+ AT32_UART_UART8_IRQ_PRIORITY,
+ (at32_dmasts_t)uart_lld_serve_rx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream");
+ uartp->dmatx = dmaStreamAllocI(AT32_UART_UART8_TX_DMA_STREAM,
+ AT32_UART_UART8_IRQ_PRIORITY,
+ (at32_dmasts_t)uart_lld_serve_tx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream");
+
+#if AT32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(uartp->dmarx, AT32_DMAMUX_UART8_RX);
+ dmaSetRequestSource(uartp->dmatx, AT32_DMAMUX_UART8_TX);
+#endif
+
+ crmEnableUART8(true);
+ nvicEnableVector(AT32_UART5_NUMBER, AT32_UART_UART8_IRQ_PRIORITY);
+ uartp->dmarxmode |= AT32_DMA_CCTRL_CHPL(AT32_UART_UART8_DMA_PRIORITY);
+ uartp->dmatxmode |= AT32_DMA_CCTRL_CHPL(AT32_UART_UART8_DMA_PRIORITY);
+ }
+#endif
+
+ /* Static DMA setup, the transfer size depends on the USART settings,
+ it is 16 bits if M=1 and PEN=0 else it is 8 bits.*/
+ if ((uartp->config->ctrl1 & (USART_CTRL1_DBN | USART_CTRL1_PEN)) == USART_CTRL1_DBN) {
+ uartp->dmarxmode |= AT32_DMA_CCTRL_PWIDTH_HWORD | AT32_DMA_CCTRL_MWIDTH_HWORD;
+ uartp->dmatxmode |= AT32_DMA_CCTRL_PWIDTH_HWORD | AT32_DMA_CCTRL_MWIDTH_HWORD;
+ }
+ dmaStreamSetPeripheral(uartp->dmarx, &uartp->usart->DT);
+ dmaStreamSetPeripheral(uartp->dmatx, &uartp->usart->DT);
+ uartp->rxbuf = 0;
+ }
+
+ uartp->rxstate = UART_RX_IDLE;
+ uartp->txstate = UART_TX_IDLE;
+ usart_start(uartp);
+}
+
+/**
+ * @brief Deactivates the UART peripheral.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ *
+ * @notapi
+ */
+void uart_lld_stop(UARTDriver *uartp) {
+
+ if (uartp->state == UART_READY) {
+ usart_stop(uartp);
+ dmaStreamFreeI(uartp->dmarx);
+ dmaStreamFreeI(uartp->dmatx);
+ uartp->dmarx = NULL;
+ uartp->dmatx = NULL;
+
+#if AT32_UART_USE_USART1
+ if (&UARTD1 == uartp) {
+ nvicDisableVector(AT32_USART1_NUMBER);
+ crmDisableUSART1();
+ return;
+ }
+#endif
+
+#if AT32_UART_USE_USART2
+ if (&UARTD2 == uartp) {
+ nvicDisableVector(AT32_USART2_NUMBER);
+ crmDisableUSART2();
+ return;
+ }
+#endif
+
+#if AT32_UART_USE_USART3
+ if (&UARTD3 == uartp) {
+ nvicDisableVector(AT32_USART3_NUMBER);
+ crmDisableUSART3();
+ return;
+ }
+#endif
+
+#if AT32_UART_USE_UART4
+ if (&UARTD4 == uartp) {
+ nvicDisableVector(AT32_UART4_NUMBER);
+ crmDisableUART4();
+ return;
+ }
+#endif
+
+#if AT32_UART_USE_UART5
+ if (&UARTD5 == uartp) {
+ nvicDisableVector(AT32_UART5_NUMBER);
+ crmDisableUART5();
+ return;
+ }
+#endif
+
+#if AT32_UART_USE_USART6
+ if (&UARTD6 == uartp) {
+ nvicDisableVector(AT32_USART6_NUMBER);
+ crmDisableUSART6();
+ return;
+ }
+#endif
+
+#if AT32_UART_USE_UART7
+ if (&UARTD7 == uartp) {
+ nvicDisableVector(AT32_UART7_NUMBER);
+ crmDisableUART7();
+ return;
+ }
+#endif
+
+#if AT32_UART_USE_UART8
+ if (&UARTD8 == uartp) {
+ nvicDisableVector(AT32_UART8_NUMBER);
+ crmDisableUART8();
+ return;
+ }
+#endif
+
+ }
+}
+
+/**
+ * @brief Starts a transmission on the UART peripheral.
+ * @note The buffers are organized as uint8_t arrays for data sizes below
+ * or equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ * @param[in] n number of data frames to send
+ * @param[in] txbuf the pointer to the transmit buffer
+ *
+ * @notapi
+ */
+void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf) {
+
+ /* TX DMA channel preparation.*/
+ dmaStreamSetMemory0(uartp->dmatx, txbuf);
+ dmaStreamSetTransactionSize(uartp->dmatx, n);
+ dmaStreamSetMode(uartp->dmatx, uartp->dmatxmode | AT32_DMA_CCTRL_DTD_M2P |
+ AT32_DMA_CCTRL_MINCM | AT32_DMA_CCTRL_FDTIEN);
+
+ /* Only enable TDC interrupt if there's a callback attached to it or
+ if called from uartSendFullTimeout(). Also we need to clear TDC flag
+ which could be set before.*/
+#if UART_USE_WAIT == TRUE
+ if ((uartp->config->txend2_cb != NULL) || (uartp->early == false)) {
+#else
+ if (uartp->config->txend2_cb != NULL) {
+#endif
+ uartp->usart->STS = ~USART_STS_TDC;
+ uartp->usart->CTRL1 |= USART_CTRL1_TDCIEN;
+ }
+
+ /* Starting transfer.*/
+ dmaStreamEnable(uartp->dmatx);
+}
+
+/**
+ * @brief Stops any ongoing transmission.
+ * @note Stopping a transmission also suppresses the transmission callbacks.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ *
+ * @return The number of data frames not transmitted by the
+ * stopped transmit operation.
+ *
+ * @notapi
+ */
+size_t uart_lld_stop_send(UARTDriver *uartp) {
+
+ dmaStreamDisable(uartp->dmatx);
+
+ return dmaStreamGetTransactionSize(uartp->dmatx);
+}
+
+/**
+ * @brief Starts a receive operation on the UART peripheral.
+ * @note The buffers are organized as uint8_t arrays for data sizes below
+ * or equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ * @param[in] n number of data frames to send
+ * @param[out] rxbuf the pointer to the receive buffer
+ *
+ * @notapi
+ */
+void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf) {
+
+ /* Stopping previous activity (idle state).*/
+ dmaStreamDisable(uartp->dmarx);
+
+ /* RX DMA channel preparation.*/
+ dmaStreamSetMemory0(uartp->dmarx, rxbuf);
+ dmaStreamSetTransactionSize(uartp->dmarx, n);
+ dmaStreamSetMode(uartp->dmarx, uartp->dmarxmode | AT32_DMA_CCTRL_DTD_P2M |
+ AT32_DMA_CCTRL_MINCM | AT32_DMA_CCTRL_FDTIEN);
+
+ /* Starting transfer.*/
+ dmaStreamEnable(uartp->dmarx);
+}
+
+/**
+ * @brief Stops any ongoing receive operation.
+ * @note Stopping a receive operation also suppresses the receive callbacks.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ *
+ * @return The number of data frames not received by the
+ * stopped receive operation.
+ *
+ * @notapi
+ */
+size_t uart_lld_stop_receive(UARTDriver *uartp) {
+ size_t n;
+
+ dmaStreamDisable(uartp->dmarx);
+ n = dmaStreamGetTransactionSize(uartp->dmarx);
+ uart_enter_rx_idle_loop(uartp);
+
+ return n;
+}
+
+/**
+ * @brief USART common service routine.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ */
+void uart_lld_serve_interrupt(UARTDriver *uartp) {
+ uint16_t sts;
+ USART_TypeDef *u = uartp->usart;
+ uint32_t ctrl1 = u->CTRL1;
+
+ sts = u->STS; /* STS reset step 1.*/
+
+ if (sts & (USART_STS_BFF | USART_STS_ROERR | USART_STS_NERR |
+ USART_STS_FERR | USART_STS_PERR)) {
+
+ (void)u->DT; /* STS reset step 2 - clear ROERR.*/
+
+ u->STS = ~USART_STS_BFF;
+ _uart_rx_error_isr_code(uartp, translate_errors(sts));
+ }
+
+ if ((sts & USART_STS_TDC) && (ctrl1 & USART_CTRL1_TDCIEN)) {
+ /* TDC interrupt cleared and disabled.*/
+ u->STS = ~USART_STS_TDC;
+ u->CTRL1 = ctrl1 & ~USART_CTRL1_TDCIEN;
+
+ /* End of transmission, a callback is generated.*/
+ _uart_tx2_isr_code(uartp);
+ }
+
+ /* Timeout interrupt sources are only checked if enabled in CTRL1.*/
+ if ((ctrl1 & USART_CTRL1_IDLEIEN) && (sts & USART_STS_IDLEF)) {
+ _uart_timeout_isr_code(uartp);
+ }
+}
+
+#endif /* HAL_USE_UART */
+
+/** @} */
diff --git a/os/hal/ports/AT32/LLD/USARTv2/hal_uart_lld.h b/os/hal/ports/AT32/LLD/USARTv2/hal_uart_lld.h
new file mode 100644
index 0000000000..4c808717cd
--- /dev/null
+++ b/os/hal/ports/AT32/LLD/USARTv2/hal_uart_lld.h
@@ -0,0 +1,675 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+ ChibiOS - Copyright (C) 2023..2024 HorrorTroll
+ ChibiOS - Copyright (C) 2023..2024 Zhaqian
+ ChibiOS - Copyright (C) 2023..2024 Maxjta
+
+ Licensed 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.
+*/
+
+/**
+ * @file USARTv2/hal_uart_lld.h
+ * @brief AT32 low level UART driver header.
+ *
+ * @addtogroup UART
+ * @{
+ */
+
+#ifndef HAL_UART_LLD_H
+#define HAL_UART_LLD_H
+
+#if HAL_USE_UART || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief UART driver on USART1 enable switch.
+ * @details If set to @p TRUE the support for USART1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(AT32_UART_USE_USART1) || defined(__DOXYGEN__)
+#define AT32_UART_USE_USART1 FALSE
+#endif
+
+/**
+ * @brief UART driver on USART2 enable switch.
+ * @details If set to @p TRUE the support for USART2 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(AT32_UART_USE_USART2) || defined(__DOXYGEN__)
+#define AT32_UART_USE_USART2 FALSE
+#endif
+
+/**
+ * @brief UART driver on USART3 enable switch.
+ * @details If set to @p TRUE the support for USART3 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(AT32_UART_USE_USART3) || defined(__DOXYGEN__)
+#define AT32_UART_USE_USART3 FALSE
+#endif
+
+/**
+ * @brief UART driver on UART4 enable switch.
+ * @details If set to @p TRUE the support for UART4 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(AT32_UART_USE_UART4) || defined(__DOXYGEN__)
+#define AT32_UART_USE_UART4 FALSE
+#endif
+
+/**
+ * @brief UART driver on UART5 enable switch.
+ * @details If set to @p TRUE the support for UART5 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(AT32_UART_USE_UART5) || defined(__DOXYGEN__)
+#define AT32_UART_USE_UART5 FALSE
+#endif
+
+/**
+ * @brief UART driver on USART6 enable switch.
+ * @details If set to @p TRUE the support for USART6 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(AT32_UART_USE_USART6) || defined(__DOXYGEN__)
+#define AT32_UART_USE_USART6 FALSE
+#endif
+
+/**
+ * @brief UART driver on UART7 enable switch.
+ * @details If set to @p TRUE the support for UART7 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(AT32_UART_USE_UART7) || defined(__DOXYGEN__)
+#define AT32_UART_USE_UART7 FALSE
+#endif
+
+/**
+ * @brief UART driver on UART8 enable switch.
+ * @details If set to @p TRUE the support for UART8 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(AT32_UART_USE_UART8) || defined(__DOXYGEN__)
+#define AT32_UART_USE_UART8 FALSE
+#endif
+
+/**
+ * @brief USART1 interrupt priority level setting.
+ */
+#if !defined(AT32_UART_USART1_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_UART_USART1_IRQ_PRIORITY 12
+#endif
+
+/**
+ * @brief USART2 interrupt priority level setting.
+ */
+#if !defined(AT32_UART_USART2_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_UART_USART2_IRQ_PRIORITY 12
+#endif
+
+/**
+ * @brief USART3 interrupt priority level setting.
+ */
+#if !defined(AT32_UART_USART3_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_UART_USART3_IRQ_PRIORITY 12
+#endif
+
+/**
+ * @brief UART4 interrupt priority level setting.
+ */
+#if !defined(AT32_UART_UART4_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_UART_UART4_IRQ_PRIORITY 12
+#endif
+
+/**
+ * @brief UART5 interrupt priority level setting.
+ */
+#if !defined(AT32_UART_UART5_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_UART_UART5_IRQ_PRIORITY 12
+#endif
+
+/**
+ * @brief USART6 interrupt priority level setting.
+ */
+#if !defined(AT32_UART_USART6_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_UART_USART6_IRQ_PRIORITY 12
+#endif
+
+/**
+ * @brief UART7 interrupt priority level setting.
+ */
+#if !defined(AT32_UART_UART7_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_UART_UART7_IRQ_PRIORITY 12
+#endif
+
+/**
+ * @brief UART8 interrupt priority level setting.
+ */
+#if !defined(AT32_UART_UART8_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_UART_UART8_IRQ_PRIORITY 12
+#endif
+
+/**
+ * @brief USART1 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA channels but
+ * because of the channels ordering the RX channel has always priority
+ * over the TX channel.
+ */
+#if !defined(AT32_UART_USART1_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_UART_USART1_DMA_PRIORITY 0
+#endif
+
+/**
+ * @brief USART2 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA channels but
+ * because of the channels ordering the RX channel has always priority
+ * over the TX channel.
+ */
+#if !defined(AT32_UART_USART2_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_UART_USART2_DMA_PRIORITY 0
+#endif
+
+/**
+ * @brief USART3 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA channels but
+ * because of the channels ordering the RX channel has always priority
+ * over the TX channel.
+ */
+#if !defined(AT32_UART_USART3_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_UART_USART3_DMA_PRIORITY 0
+#endif
+
+/**
+ * @brief UART4 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA channels but
+ * because of the channels ordering the RX channel has always priority
+ * over the TX channel.
+ */
+#if !defined(AT32_UART_UART4_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_UART_UART4_DMA_PRIORITY 0
+#endif
+
+/**
+ * @brief UART5 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA channels but
+ * because of the channels ordering the RX channel has always priority
+ * over the TX channel.
+ */
+#if !defined(AT32_UART_UART5_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_UART_UART5_DMA_PRIORITY 0
+#endif
+
+/**
+ * @brief USART6 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA channels but
+ * because of the channels ordering the RX channel has always priority
+ * over the TX channel.
+ */
+#if !defined(AT32_UART_USART6_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_UART_USART6_DMA_PRIORITY 0
+#endif
+
+/**
+ * @brief UART7 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA channels but
+ * because of the channels ordering the RX channel has always priority
+ * over the TX channel.
+ */
+#if !defined(AT32_UART_UART7_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_UART_UART7_DMA_PRIORITY 0
+#endif
+
+/**
+ * @brief UART8 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA channels but
+ * because of the channels ordering the RX channel has always priority
+ * over the TX channel.
+ */
+#if !defined(AT32_UART_UART8_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define AT32_UART_UART8_DMA_PRIORITY 0
+#endif
+
+/**
+ * @brief USART DMA error hook.
+ * @note The default action for DMA errors is a system halt because DMA
+ * error can only happen because programming errors.
+ */
+#if !defined(AT32_UART_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
+#define AT32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure")
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if AT32_UART_USE_USART1 && !AT32_HAS_USART1
+#error "USART1 not present in the selected device"
+#endif
+
+#if AT32_UART_USE_USART2 && !AT32_HAS_USART2
+#error "USART2 not present in the selected device"
+#endif
+
+#if AT32_UART_USE_USART3 && !AT32_HAS_USART3
+#error "USART3 not present in the selected device"
+#endif
+
+#if AT32_UART_USE_UART4 && !AT32_HAS_UART4
+#error "UART4 not present in the selected device"
+#endif
+
+#if AT32_UART_USE_UART5 && !AT32_HAS_UART5
+#error "UART5 not present in the selected device"
+#endif
+
+#if AT32_UART_USE_USART6 && !AT32_HAS_USART6
+#error "USART6 not present in the selected device"
+#endif
+
+#if AT32_UART_USE_UART7 && !AT32_HAS_UART7
+#error "UART7 not present in the selected device"
+#endif
+
+#if AT32_UART_USE_UART8 && !AT32_HAS_UART8
+#error "UART8 not present in the selected device"
+#endif
+
+#if !AT32_UART_USE_USART1 && !AT32_UART_USE_USART2 && \
+ !AT32_UART_USE_USART3 && !AT32_UART_USE_UART4 && \
+ !AT32_UART_USE_UART5 && !AT32_UART_USE_USART6 && \
+ !AT32_UART_USE_UART7 && !AT32_UART_USE_UART8
+#error "UART driver activated but no USART/UART peripheral assigned"
+#endif
+
+#if AT32_UART_USE_USART1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(AT32_UART_USART1_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to USART1"
+#endif
+
+#if AT32_UART_USE_USART2 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(AT32_UART_USART2_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to USART2"
+#endif
+
+#if AT32_UART_USE_USART3 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(AT32_UART_USART3_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to USART3"
+#endif
+
+#if AT32_UART_USE_UART4 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(AT32_UART_UART4_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to UART4"
+#endif
+
+#if AT32_UART_USE_UART5 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(AT32_UART_UART5_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to UART5"
+#endif
+
+#if AT32_UART_USE_USART6 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(AT32_UART_USART6_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to USART6"
+#endif
+
+#if AT32_UART_USE_UART7 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(AT32_UART_UART7_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to UART7"
+#endif
+
+#if AT32_UART_USE_UART8 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(AT32_UART_UART8_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to UART8"
+#endif
+
+#if AT32_UART_USE_USART1 && \
+ !AT32_DMA_IS_VALID_PRIORITY(AT32_UART_USART1_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to USART1"
+#endif
+
+#if AT32_UART_USE_USART2 && \
+ !AT32_DMA_IS_VALID_PRIORITY(AT32_UART_USART2_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to USART2"
+#endif
+
+#if AT32_UART_USE_USART3 && \
+ !AT32_DMA_IS_VALID_PRIORITY(AT32_UART_USART3_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to USART3"
+#endif
+
+#if AT32_UART_USE_UART4 && \
+ !AT32_DMA_IS_VALID_PRIORITY(AT32_UART_UART4_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to UART4"
+#endif
+
+#if AT32_UART_USE_UART5 && \
+ !AT32_DMA_IS_VALID_PRIORITY(AT32_UART_UART5_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to UART5"
+#endif
+
+#if AT32_UART_USE_USART6 && \
+ !AT32_DMA_IS_VALID_PRIORITY(AT32_UART_USART6_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to USART6"
+#endif
+
+#if AT32_UART_USE_UART7 && \
+ !AT32_DMA_IS_VALID_PRIORITY(AT32_UART_UART7_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to UART7"
+#endif
+
+#if AT32_UART_USE_UART8 && \
+ !AT32_DMA_IS_VALID_PRIORITY(AT32_UART_UART8_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to UART8"
+#endif
+
+#if !defined(AT32_DMA_REQUIRED)
+#define AT32_DMA_REQUIRED
+#endif
+
+/* Checks on allocation of USARTx units.*/
+#if AT32_UART_USE_USART1
+#if defined(AT32_USART1_IS_USED)
+#error "UARTD1 requires USART1 but it is already used"
+#else
+#define AT32_USART1_IS_USED
+#endif
+#endif
+
+#if AT32_UART_USE_USART2
+#if defined(AT32_USART2_IS_USED)
+#error "UARTD2 requires USART2 but it is already used"
+#else
+#define AT32_USART2_IS_USED
+#endif
+#endif
+
+#if AT32_UART_USE_USART3
+#if defined(AT32_USART3_IS_USED)
+#error "UARTD3 requires USART3 but it is already used"
+#else
+#define AT32_USART3_IS_USED
+#endif
+#endif
+
+#if AT32_UART_USE_UART4
+#if defined(AT32_UART4_IS_USED)
+#error "UARTD4 requires UART4 but it is already used"
+#else
+#define AT32_UART4_IS_USED
+#endif
+#endif
+
+#if AT32_UART_USE_UART5
+#if defined(AT32_UART5_IS_USED)
+#error "UARTD5 requires UART5 but it is already used"
+#else
+#define AT32_UART5_IS_USED
+#endif
+#endif
+
+#if AT32_UART_USE_USART6
+#if defined(AT32_USART6_IS_USED)
+#error "UARTD6 requires USART6 but it is already used"
+#else
+#define AT32_USART6_IS_USED
+#endif
+#endif
+
+#if AT32_UART_USE_UART7
+#if defined(AT32_UART7_IS_USED)
+#error "UARTD7 requires UART7 but it is already used"
+#else
+#define AT32_UART7_IS_USED
+#endif
+#endif
+
+#if AT32_UART_USE_UART8
+#if defined(AT32_UART8_IS_USED)
+#error "UARTD8 requires UART8 but it is already used"
+#else
+#define AT32_UART8_IS_USED
+#endif
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief UART driver condition flags type.
+ */
+typedef uint32_t uartflags_t;
+
+/**
+ * @brief Type of an UART driver.
+ */
+typedef struct hal_uart_driver UARTDriver;
+
+/**
+ * @brief Generic UART notification callback type.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ */
+typedef void (*uartcb_t)(UARTDriver *uartp);
+
+/**
+ * @brief Character received UART notification callback type.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ * @param[in] c received character
+ */
+typedef void (*uartccb_t)(UARTDriver *uartp, uint16_t c);
+
+/**
+ * @brief Receive error UART notification callback type.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ * @param[in] e receive error mask
+ */
+typedef void (*uartecb_t)(UARTDriver *uartp, uartflags_t e);
+
+/**
+ * @brief Type of an UART configuration structure.
+ * @note It could be empty on some architectures.
+ */
+typedef struct hal_uart_config {
+ /**
+ * @brief End of transmission buffer callback.
+ */
+ uartcb_t txend1_cb;
+ /**
+ * @brief Physical end of transmission callback.
+ */
+ uartcb_t txend2_cb;
+ /**
+ * @brief Receive buffer filled callback.
+ */
+ uartcb_t rxend_cb;
+ /**
+ * @brief Character received while out if the @p UART_RECEIVE state.
+ */
+ uartccb_t rxchar_cb;
+ /**
+ * @brief Receive error callback.
+ */
+ uartecb_t rxerr_cb;
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Receiver timeout callback.
+ * @details Handles idle interrupts depending on configured
+ * flags in CR registers and supported hardware features.
+ */
+ uartcb_t timeout_cb;
+ /**
+ * @brief Bit rate.
+ */
+ uint32_t speed;
+ /**
+ * @brief Initialization value for the CTRL1 register.
+ */
+ uint16_t ctrl1;
+ /**
+ * @brief Initialization value for the CTRL2 register.
+ */
+ uint16_t ctrl2;
+ /**
+ * @brief Initialization value for the CTRL3 register.
+ */
+ uint16_t ctrl3;
+} UARTConfig;
+
+/**
+ * @brief Structure representing an UART driver.
+ */
+struct hal_uart_driver {
+ /**
+ * @brief Driver state.
+ */
+ uartstate_t state;
+ /**
+ * @brief Transmitter state.
+ */
+ uarttxstate_t txstate;
+ /**
+ * @brief Receiver state.
+ */
+ uartrxstate_t rxstate;
+ /**
+ * @brief Current configuration data.
+ */
+ const UARTConfig *config;
+#if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Synchronization flag for transmit operations.
+ */
+ bool early;
+ /**
+ * @brief Waiting thread on RX.
+ */
+ thread_reference_t threadrx;
+ /**
+ * @brief Waiting thread on TX.
+ */
+ thread_reference_t threadtx;
+#endif /* UART_USE_WAIT */
+#if (UART_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Mutex protecting the peripheral.
+ */
+ mutex_t mutex;
+#endif /* UART_USE_MUTUAL_EXCLUSION */
+#if defined(UART_DRIVER_EXT_FIELDS)
+ UART_DRIVER_EXT_FIELDS
+#endif
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Pointer to the USART registers block.
+ */
+ USART_TypeDef *usart;
+ /**
+ * @brief Clock frequency for the associated USART/UART.
+ */
+ uint32_t clock;
+ /**
+ * @brief Receive DMA mode bit mask.
+ */
+ uint32_t dmarxmode;
+ /**
+ * @brief Send DMA mode bit mask.
+ */
+ uint32_t dmatxmode;
+ /**
+ * @brief Receive DMA channel.
+ */
+ const at32_dma_stream_t *dmarx;
+ /**
+ * @brief Transmit DMA channel.
+ */
+ const at32_dma_stream_t *dmatx;
+ /**
+ * @brief Default receive buffer while into @p UART_RX_IDLE state.
+ */
+ volatile uint16_t rxbuf;
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if AT32_UART_USE_USART1 && !defined(__DOXYGEN__)
+extern UARTDriver UARTD1;
+#endif
+
+#if AT32_UART_USE_USART2 && !defined(__DOXYGEN__)
+extern UARTDriver UARTD2;
+#endif
+
+#if AT32_UART_USE_USART3 && !defined(__DOXYGEN__)
+extern UARTDriver UARTD3;
+#endif
+
+#if AT32_UART_USE_UART4 && !defined(__DOXYGEN__)
+extern UARTDriver UARTD4;
+#endif
+
+#if AT32_UART_USE_UART5 && !defined(__DOXYGEN__)
+extern UARTDriver UARTD5;
+#endif
+
+#if AT32_UART_USE_USART6 && !defined(__DOXYGEN__)
+extern UARTDriver UARTD6;
+#endif
+
+#if AT32_UART_USE_UART7 && !defined(__DOXYGEN__)
+extern UARTDriver UARTD7;
+#endif
+
+#if AT32_UART_USE_UART8 && !defined(__DOXYGEN__)
+extern UARTDriver UARTD8;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void uart_lld_init(void);
+ void uart_lld_start(UARTDriver *uartp);
+ void uart_lld_stop(UARTDriver *uartp);
+ void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf);
+ size_t uart_lld_stop_send(UARTDriver *uartp);
+ void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf);
+ size_t uart_lld_stop_receive(UARTDriver *uartp);
+ void uart_lld_serve_interrupt(UARTDriver *uartp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_UART */
+
+#endif /* HAL_UART_LLD_H */
+
+/** @} */