[HAL/HT32]: Initial HT32 Support with a USB-DFU Demo

This commit is contained in:
codetector 2020-12-31 02:27:13 -05:00
parent a9c5088165
commit 7230eb96cc
No known key found for this signature in database
GPG Key ID: 7D42AB4D2C7B40A4
64 changed files with 10738 additions and 0 deletions

View File

@ -50,6 +50,10 @@ jobs:
run: |
$CHC_PATH/tools/chbuild.sh $CHC_PATH/testhal/LPC
$CHC_PATH/tools/chbuild.sh $CHC_PATH/demos/LPC
- name: build HT32
run: |
$CHC_PATH/tools/chbuild.sh $CHC_PATH/testhal/HT32
$CHC_PATH/tools/chbuild.sh $CHC_PATH/demos/HT32
- name: build NUMICRO
run: |
$CHC_PATH/tools/chbuild.sh $CHC_PATH/testhal/NUMICRO

View File

@ -0,0 +1,5 @@
.dep/
build/
.vscode/
.idea/

View File

@ -0,0 +1,192 @@
##############################################################################
# Build global options
# NOTE: Can be overridden externally.
#
# Compiler options here.
ifeq ($(USE_OPT),)
USE_OPT = -Os -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 = 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 =
endif
#
# Architecture or project specific options
##############################################################################
##############################################################################
# Project, target, sources and paths
#
# Define project name here
PROJECT = usbdfu
# Target settings.
MCU = cortex-m3
# Imported source files and paths.
CHIBIOS = ../../../../ChibiOS
CHIBIOS_CONTRIB = $(CHIBIOS)/../ChibiOS-Contrib
CONFDIR := ./cfg
BUILDDIR := ./build
DEPDIR := ./.dep
BOARDDIR := ./board
# Licensing files.
include $(CHIBIOS)/os/license/license.mk
# Startup files.
include $(CHIBIOS_CONTRIB)/os/common/startup/ARMCMx/compilers/GCC/mk/startup_ht32f165x.mk
# HAL-OSAL files (optional).
include $(CHIBIOS)/os/hal/hal.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/HT32/HT32F165x/platform.mk
include $(BOARDDIR)/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/ARMCMx/compilers/GCC/mk/port_v7m.mk
# Auto-build files in ./source recursively.
include $(CHIBIOS)/tools/mk/autobuild.mk
# Other files (optional).
#include $(CHIBIOS)/test/lib/test.mk
#include $(CHIBIOS)/test/rt/rt_test.mk
#include $(CHIBIOS)/test/oslib/oslib_test.mk
# Define linker script file here
# We used the 1653 config, because this is the smaller device of the two
LDSCRIPT= $(STARTUPLD_CONTRIB)/HT32F1653.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 -Wno-unused-function
# Define C++ warning options here.
CPPWARN = -Wall -Wextra -Wundef -Werror -Wno-unused-function
#
# Project, target, sources and paths
##############################################################################
##############################################################################
# Start of user section
#
# List all user C define here, like -D_DEBUG=1
UDEFS = -DPORT_IGNORE_GCC_VERSION_CHECK
# Define ASM defines here
UADEFS = -DPORT_IGNORE_GCC_VERSION_CHECK
# 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
##############################################################################

View File

@ -0,0 +1,88 @@
#include "board.h"
#include "hal.h"
#define PBIT(PORT, LINE) ((PAL_PORT(LINE) == PORT) ? (1 << PAL_PAD(LINE)) : 0)
#define PAFIO_L(PORT, LINE, AF) (((PAL_PORT(LINE) == PORT) && (PAL_PAD(LINE) < 8)) ? (AF << (PAL_PAD(LINE) << 2)) : 0)
#define PAFIO_H(PORT, LINE, AF) (((PAL_PORT(LINE) == PORT) && (PAL_PAD(LINE) >= 8)) ? (AF << ((PAL_PAD(LINE) - 8) << 2)) : 0)
#define PAFIO(PORT, N, LINE, AF) ((N) ? PAFIO_H(PORT, LINE, AF) : PAFIO_L(PORT, LINE, AF))
#define OPEN_DRAIN(PORT) (\
0)
#define OUT_BITS(PORT) (\
0)
#define IN_BITS(PORT) (\
0)
// Alternate Functions
#define AF_BITS(PORT, N) (\
0)
/**
* @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.
*/
const PALConfig pal_default_config = {
// GPIO A
.setup[0] = {
.DIR = OUT_BITS(IOPORTA),
.INE = IN_BITS(IOPORTA),
.PU = IN_BITS(IOPORTA),
.PD = 0x0000,
.OD = OPEN_DRAIN(IOPORTA),
.DRV = 0x0000,
.LOCK = 0x0000,
.OUT = 0x0000,
.CFG[0] = AF_BITS(IOPORTA, 0),
.CFG[1] = AF_BITS(IOPORTA, 1),
},
// GPIO B
.setup[1] = {
.DIR = OUT_BITS(IOPORTB),
.INE = IN_BITS(IOPORTB),
.PU = IN_BITS(IOPORTB),
.PD = 0x0000,
.OD = OPEN_DRAIN(IOPORTB),
.DRV = 0x0000,
.LOCK = 0x0000,
.OUT = 0x0000,
.CFG[0] = AF_BITS(IOPORTB, 0),
.CFG[1] = AF_BITS(IOPORTB, 1),
},
// GPIO C
.setup[2] = {
.DIR = OUT_BITS(IOPORTC),
.INE = IN_BITS(IOPORTC),
.PU = IN_BITS(IOPORTC),
.PD = 0x0000,
.OD = OPEN_DRAIN(IOPORTC),
.DRV = 0x0000,
.LOCK = 0x0000,
.OUT = 0x0000,
.CFG[0] = AF_BITS(IOPORTC, 0),
.CFG[1] = AF_BITS(IOPORTC, 1),
},
// GPIO D
.setup[3] = {
.DIR = OUT_BITS(IOPORTD),
.INE = IN_BITS(IOPORTD),
.PU = IN_BITS(IOPORTD),
.PD = 0x0000,
.OD = OPEN_DRAIN(IOPORTD),
.DRV = 0x0000,
.LOCK = 0x0000,
.OUT = 0x0000,
.CFG[0] = AF_BITS(IOPORTD, 0),
.CFG[1] = AF_BITS(IOPORTD, 1),
},
.ESSR[0] = 0x00000000,
.ESSR[1] = 0x00000000,
};
void boardInit(void) {
}

View File

@ -0,0 +1,56 @@
#pragma once
/*
ChibiOS - Copyright (C) 2006..2020 Giovanni Di Sirio
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.
*/
/*
* This file has been automatically generated using ChibiStudio board
* generator plugin. Do not edit manually.
*/
#ifndef BOARD_H
#define BOARD_H
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/*
* Setup board.
*/
/*
* Board identifier.
*/
#ifndef HT32F165x
#define HT32F1653
#endif
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#if !defined(_FROM_ASM_)
#ifdef __cplusplus
extern "C" {
#endif
void boardInit(void);
#ifdef __cplusplus
}
#endif
#endif /* _FROM_ASM_ */
#endif /* BOARD_H */

View File

@ -0,0 +1,9 @@
# List of all the board related files.
BOARDSRC = $(BOARDDIR)/board.c
# Required include directories
BOARDINC = $(BOARDDIR)
# Shared variables
ALLCSRC += $(BOARDSRC)
ALLINC += $(BOARDINC)

View File

@ -0,0 +1,757 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
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_6_1_
/*===========================================================================*/
/**
* @name System timers settings
* @{
*/
/*===========================================================================*/
/**
* @brief System time counter resolution.
* @note Allowed values are 16 or 32 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 0
#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
/** @} */
/*===========================================================================*/
/**
* @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 FALSE
#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 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 FALSE
#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 FALSE
#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 FALSE
#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_DISABLED
#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 FALSE
#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 FALSE
#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 threads 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 threads 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.
*/
#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.
*/
#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.
*/
#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.*/ \
}
/** @} */
/*===========================================================================*/
/* Port-specific settings (override port settings defaulted in chcore.h). */
/*===========================================================================*/
#endif /* CHCONF_H */
/** @} */

View File

@ -0,0 +1,532 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
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_7_1_
#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 FALSE
#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 FALSE
#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 FALSE
#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 FALSE
#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 FALSE
#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 FALSE
#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 FALSE
#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 FALSE
#endif
/*===========================================================================*/
/* MMC_SPI driver related settings. */
/*===========================================================================*/
/**
* @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.
* This option is recommended also if the SPI driver does not
* use a DMA channel and heavily loads the CPU.
*/
#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__)
#define MMC_NICE_WAITING FALSE
#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
/*===========================================================================*/
/* 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 Enables circular transfers APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__)
#define SPI_USE_CIRCULAR FALSE
#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 TRUE
#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 */
/** @} */

View File

@ -0,0 +1,35 @@
#ifndef MCUCONF_H
#define MCUCONF_H
#define HT32F1654_MCUCONF
/*
* HAL driver system settings.
*/
/*
* Clock configuration.
*/
#define HT32_CK_HSE_FREQUENCY 8000000UL // 8 MHz
#define HT32_CKCU_SW CKCU_GCCR_SW_PLL
#define HT32_PLL_USE_HSE TRUE
#define HT32_PLL_FBDIV 18 // 8 MHz -> 144 MHz
#define HT32_PLL_OTDIV 0
#define HT32_AHB_PRESCALER 2 // 144 MHz -> 72 MHz
#define HT32_USART_PRESCALER 1 // 72 MHz
#define HT32_USB_PRESCALER 3 // 144 MHz -> 48 MHz
// SysTick uses processor clock at 72MHz
#define HT32_ST_USE_HCLK TRUE
#define HT32_GPT_USE_BFTM0 FALSE
#define HT32_GPT_BFTM0_IRQ_PRIORITY 4
/*
* USB driver settings
*/
#define HT32_USB_USE_USB0 TRUE
#define HT32_USB_USB0_IRQ_PRIORITY 5
#define HT32_PWM_USE_GPTM1 FALSE
#endif

View File

@ -0,0 +1,66 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
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 "usbdfu.h"
#include <string.h>
#define CM_RESET_VECTOR_OFFSET 4
static void jump_to_application(void) __attribute__ ((noreturn));
static void jump_to_application(void) {
/* Use the application's vector table */
// Copy Vector Table to RAM_START(0x10000000)
memcpy((void*) 0x10000000, (void*)APP_BASE, 512);
/* Initialize the application's stack pointer */
__set_MSP(*((volatile uint32_t*)(APP_BASE)));
uint32_t target_start = *((volatile uint32_t*)(APP_BASE + CM_RESET_VECTOR_OFFSET));
uint32_t initial_sp = *((volatile uint32_t*)(APP_BASE));
/* Jump to the application entry point */
__ASM volatile ("mov sp, %0\n" "bx %1" : : "r" (initial_sp), "r" (target_start) : );
while (1) {}
}
/*
* Application entry point.
*/
int main(void) {
halInit();
/*
* System initializations.
* - Kernel initialization, the main() function becomes a thread and the
* RTOS is active.
*/
chSysInit();
/*
* Normal main() thread activity, in this demo it does nothing except
* increasing the minutes counter.
*/
usbDisconnectBus(&USBD1);
chThdSleepMilliseconds(1500);
usbStart(&USBD1, &usbcfg);
usbConnectBus(&USBD1);
while(1){
chThdSleepSeconds(600);
}
}

View File

@ -0,0 +1,20 @@
adapter driver jlink
transport select swd
set WORKAREASIZE 0x400
set HT32_SRAM_SIZE 8192
set HT32_FLASH_SIZE 65536
source [find target/ht32f165x.cfg]
adapter speed 5000
proc program {file} {
init
reset halt
flash write_image erase $file 0x00000000
reset run
echo "\n PROGRAM COMPLETE!!!"
}

View File

@ -0,0 +1,8 @@
# USB DFU Demo
This is an example software bootloader implementing the USB-DFU 1.1 standard.
You can customize the USB Vendor ID / Product ID in the `source/usbdfu.c` file.
The VID:PID is default to `04d9:F00D`
It expect that your actual code to be loaded at `0x2000` (APP_BASE)

View File

@ -0,0 +1,34 @@
#include "usbdfu.h"
#include "ch.h"
#include "hal.h"
#include <string.h>
size_t target_get_max_fw_size(void) {
return (MAX_FLASH_ADDR - APP_BASE);
}
uint16_t target_get_timeout(void) {
return 5;
}
void target_flash_unlock(void) {
chSysLock();
}
bool target_flash_write(uint8_t* dst, uint8_t* src, size_t len) {
// TODO: Write flash
return true;
}
bool target_prepare_flash(void) {
// TODO: Erase All Flash Pages
return true;
}
void target_flash_lock(void) {
chSysUnlock();
}
void target_complete_programming(void) {
// Do nothing
}

View File

@ -0,0 +1,19 @@
#pragma once
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#define MAX_FLASH_ADDR 0x10000
#define FLASH_BASE 0x0
#define BL_SIZE 0x2000
#define APP_BASE (FLASH_BASE + BL_SIZE)
#define FLASH_PAGE_SIZE 1024
size_t target_get_max_fw_size(void);
uint16_t target_get_timeout(void);
void target_flash_unlock(void);
bool target_flash_write(uint8_t* dst, uint8_t* src, size_t len);
bool target_prepare_flash(void);
void target_flash_lock(void);
void target_complete_programming(void);

View File

@ -0,0 +1,302 @@
#include "hal.h"
#include "usbdfu.h"
#include "dfu_target.h"
uint8_t fw_buffer[FW_BUFFER_SIZE];
/*
* USB Device Descriptor.
*/
static const uint8_t dfu_device_descriptor_data[18] = {
USB_DESC_DEVICE (0x0200, /* bcdUSB (1.1). */
0x00, /* bDeviceClass */
0x00, /* bDeviceSubClass. */
0x00, /* bDeviceProtocol. */
64, /* bMaxPacketSize. */
0x04d9, /* idVendor (ST). */
0xf00d, /* idProduct. */
0x0200, /* bcdDevice. */
1, /* iManufacturer. */
2, /* iProduct. */
3, /* iSerialNumber. */
1) /* bNumConfigurations. */
};
static const USBDescriptor dfu_device_descriptor = {
sizeof dfu_device_descriptor_data,
dfu_device_descriptor_data
};
/* Configuration Descriptor tree for a DFU.*/
static const uint8_t dfu_configuration_descriptor_data[27] = {
/* Configuration Descriptor.*/
USB_DESC_CONFIGURATION(27, /* wTotalLength. */
0x01, /* bNumInterfaces. */
0x01, /* bConfigurationValue. */
0, /* iConfiguration. */
0xC0, /* bmAttributes (self powered). */
50), /* bMaxPower (100mA). */
/* Interface Descriptor.*/
USB_DESC_INTERFACE (0x00, /* bInterfaceNumber. */
0x00, /* bAlternateSetting. */
0x00, /* bNumEndpoints. */
0xFE, /* bInterfaceClass (DFU Class
*/
0x01, /* bInterfaceSubClass */
0x02, /* bInterfaceProtocol */
2), /* iInterface. */
/* DFU Class Descriptor.*/
USB_DESC_BYTE (9), /* bLength. */
USB_DESC_BYTE (0x21), /* bDescriptorType (DFU_FCUNTION). */
USB_DESC_BYTE (0b1011), /* bmAttributes (DETACH | DOWNLOAD) */
USB_DESC_WORD ( 1000), /* DetachTimeout. */
USB_DESC_WORD ( 64),
USB_DESC_BCD (0x0110)
};
static const USBDescriptor dfu_configuration_descriptor = {
sizeof dfu_configuration_descriptor_data,
dfu_configuration_descriptor_data
};
static const uint8_t dfu_string0[] = {
USB_DESC_BYTE(4), /* bLength. */
USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */
USB_DESC_WORD(0x0409) /* wLANGID (U.S. English). */
};
static const uint8_t dfu_string1[] = {
USB_DESC_BYTE(14), /* bLength. */
USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */
'H', 0, 'o', 0, 'l', 0, 't', 0, 'e', 0, 'k', 0
};
/*
* Device Description string.
*/
static const uint8_t dfu_string2[] = {
USB_DESC_BYTE(16), /* bLength. */
USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */
'U', 0, 'S', 0, 'B', 0, ' ', 0 , 'D', 0, 'F', 0, 'U', 0
};
/*
* Serial Number string.
*/
static const uint8_t dfu_string3[] = {
USB_DESC_BYTE(8), /* bLength. */
USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */
'1', 0, '.', 0, '1', 0
};
/*
* Strings wrappers array.
*/
static const USBDescriptor dfu_strings[] = {
{sizeof dfu_string0, dfu_string0},
{sizeof dfu_string1, dfu_string1},
{sizeof dfu_string2, dfu_string2},
{sizeof dfu_string3, dfu_string3}
};
/*
* Handles the GET_DESCRIPTOR callback. All required descriptors must be
* handled here.
*/
static const USBDescriptor *get_descriptor(USBDriver *usbp,
uint8_t dtype,
uint8_t dindex,
uint16_t lang) {
(void)usbp;
(void)lang;
switch (dtype) {
case USB_DESCRIPTOR_DEVICE:
return &dfu_device_descriptor;
case USB_DESCRIPTOR_CONFIGURATION:
return &dfu_configuration_descriptor;
case USB_DESCRIPTOR_STRING:
if (dindex < 4)
return &dfu_strings[dindex];
}
return NULL;
}
volatile enum dfu_state currentState = STATE_DFU_IDLE;
volatile enum dfu_status currentStatus = DFU_STATUS_OK;
size_t current_dfu_offset = 0;
size_t dfu_download_size = 0;
static void dfu_on_download_request(USBDriver *usbp) {
(void)usbp;
uint8_t *dest = (uint8_t*)(APP_BASE + current_dfu_offset);
bool ok = true;
target_flash_unlock();
if (current_dfu_offset == 0) {
ok = target_prepare_flash();
}
if (ok) {
ok = target_flash_write(dest, fw_buffer, dfu_download_size);
}
target_flash_lock();
if (ok) {
current_dfu_offset += dfu_download_size;
currentState = STATE_DFU_DNLOAD_IDLE;
} else {
currentState = STATE_DFU_ERROR;
currentStatus = DFU_STATUS_ERR_VERIFY;
}
}
static void dfu_on_download_complete(USBDriver *usbp) {
(void)usbp;
currentState = STATE_DFU_MANIFEST_SYNC;
}
static void dfu_on_manifest_request(USBDriver *usbp) {
(void)usbp;
target_complete_programming();
currentState = STATE_DFU_MANIFEST_WAIT_RESET;
}
static void dfu_on_detach_complete(USBDriver *usbp) {
(void)usbp;
__asm__ __volatile__("dsb");
SCB->AIRCR = 0x05FA0004; // System Reset
__asm__ __volatile__("dsb");
while(1){};
}
static inline void dfu_status_req(USBDriver *usbp) {
static uint8_t status_response_buffer[6] = {};
uint32_t pollTime = 10;
usbcallback_t cb = NULL;
switch(currentState) {
case STATE_DFU_DNLOAD_SYNC: {
currentState = STATE_DFU_DNBUSY;
pollTime = target_get_timeout();
cb = &dfu_on_download_request;
break;
}
case STATE_DFU_MANIFEST_SYNC: {
currentState = STATE_DFU_MANIFEST;
cb = &dfu_on_manifest_request;
break;
}
case STATE_DFU_MANIFEST_WAIT_RESET: {
cb = &dfu_on_detach_complete;
break;
}
default:
break;
}
// Response Construction
status_response_buffer[0] = (uint8_t) currentStatus;
status_response_buffer[1] = (uint8_t) (pollTime & 0xFFU);
status_response_buffer[2] = (uint8_t) ((pollTime >> 8U) & 0xFFU);
status_response_buffer[3] = (uint8_t) ((pollTime >> 16U) & 0xFFU);
status_response_buffer[4] = (uint8_t) currentState;
status_response_buffer[5] = 0; // No Index
usbSetupTransfer(usbp, status_response_buffer, 6, cb);
}
static bool request_handler(USBDriver *usbp) {
struct usb_setup* setup = (struct usb_setup*) usbp->setup;
if((setup->bmRequestType & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_CLASS) {
switch (setup->bRequest) {
case DFU_GETSTATUS: {
dfu_status_req(usbp);
return true;
}
case DFU_GETSTATE: {
usbSetupTransfer(usbp, (uint8_t *)&currentState, 1, NULL);
return true;
}
case DFU_UPLOAD: {
switch (currentState) {
case STATE_DFU_IDLE: {
current_dfu_offset = 0;
__attribute__((fallthrough));
}
case STATE_DFU_UPLOAD_IDLE: {
uint16_t copy_len = setup->wLength;
size_t fw_size = target_get_max_fw_size();
if (current_dfu_offset + setup->wLength > fw_size) {
copy_len = fw_size - current_dfu_offset;
currentState = STATE_DFU_IDLE;
} else {
currentState = STATE_DFU_UPLOAD_IDLE;
}
usbSetupTransfer(usbp, (uint8_t *)(APP_BASE + current_dfu_offset), copy_len, NULL );
current_dfu_offset += copy_len;
break;
}
default:
usbSetupTransfer(usbp, NULL, 0, NULL);
break;
}
return true;
}
case DFU_CLRSTATUS: {
currentStatus = DFU_STATUS_OK;
if (currentState != STATE_DFU_ERROR) {
usbSetupTransfer(usbp, NULL, 0, NULL);
break;
}
__attribute__((fallthrough));
}
case DFU_ABORT: {
currentState = STATE_DFU_IDLE;
usbSetupTransfer(usbp, NULL, 0, NULL);
return true;
}
case DFU_DETACH: {
usbSetupTransfer(usbp, NULL, 0, &dfu_on_detach_complete);
return true;
}
case DFU_DNLOAD: {
switch (currentState) {
case STATE_DFU_IDLE: {
current_dfu_offset = 0;
dfu_download_size = setup->wLength;
currentState = STATE_DFU_DNLOAD_SYNC;
usbSetupTransfer(usbp, &fw_buffer[0], dfu_download_size, NULL);
break;
}
case STATE_DFU_DNLOAD_IDLE: {
if (setup->wLength > 0) {
dfu_download_size = setup->wLength;
usbSetupTransfer(usbp, &fw_buffer[0], dfu_download_size, NULL);
currentState = STATE_DFU_DNLOAD_SYNC;
} else {
usbSetupTransfer(usbp, NULL, 0, &dfu_on_download_complete);
}
break;
}
default: {
usbSetupTransfer(usbp, NULL, 0, NULL);
break;
}
}
return true;
}
}
}
return false;
}
/*
* USB driver configuration.
*/
const USBConfig usbcfg = {
NULL,
get_descriptor,
request_handler,
NULL
};

View File

@ -0,0 +1,61 @@
#pragma once
#include "stdint.h"
#include "hal.h"
#include "dfu_target.h"
extern const USBConfig usbcfg;
#define FW_BUFFER_SIZE 256
enum dfu_req {
DFU_DETACH,
DFU_DNLOAD,
DFU_UPLOAD,
DFU_GETSTATUS,
DFU_CLRSTATUS,
DFU_GETSTATE,
DFU_ABORT,
};
enum dfu_state {
STATE_APP_IDLE,
STATE_APP_DETACH,
STATE_DFU_IDLE,
STATE_DFU_DNLOAD_SYNC,
STATE_DFU_DNBUSY,
STATE_DFU_DNLOAD_IDLE,
STATE_DFU_MANIFEST_SYNC,
STATE_DFU_MANIFEST,
STATE_DFU_MANIFEST_WAIT_RESET,
STATE_DFU_UPLOAD_IDLE,
STATE_DFU_ERROR,
};
enum dfu_status {
DFU_STATUS_OK,
DFU_STATUS_ERR_TARGET,
DFU_STATUS_ERR_FILE,
DFU_STATUS_ERR_WRITE,
DFU_STATUS_ERR_ERASE,
DFU_STATUS_ERR_CHECK_ERASED,
DFU_STATUS_ERR_PROG,
DFU_STATUS_ERR_VERIFY,
DFU_STATUS_ERR_ADDRESS,
DFU_STATUS_ERR_NOTDONE,
DFU_STATUS_ERR_FIRMWARE,
DFU_STATUS_ERR_VENDOR,
DFU_STATUS_ERR_USBR,
DFU_STATUS_ERR_POR,
DFU_STATUS_ERR_UNKNOWN,
DFU_STATUS_ERR_STALLEDPKT,
};
struct usb_setup {
uint8_t bmRequestType;
uint8_t bRequest;
uint16_t wValue;
uint16_t wIndex;
uint16_t wLength;
} __attribute__((packed));

View File

@ -0,0 +1,254 @@
/*
* Copyright (C) 2014-2016 Fabio Utzig, http://fabioutzig.com
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef _HT32F165x_H_
#define _HT32F165x_H_
#if defined(HT32F1653) || defined(HT32F1654)
#define HT32F1653_4
#elif defined(HT32F1655) || defined(HT32F1656)
#define HT32F1655_6
#else
#error "Unknown HT32 device"
#endif
#if defined(HT32F1653_4) || defined(HT32F1655_6)
#define HT32
#define HT32F165x
#endif
/*
* ==============================================================
* ---------- Interrupt Number Definition -----------------------
* ==============================================================
*/
typedef enum IRQn
{
/****** Cortex-M3 Processor Exceptions Numbers ****************/
InitialSP_IRQn = -16,
InitialPC_IRQn = -15,
NonMaskableInt_IRQn = -14,
HardFault_IRQn = -13,
MemoryManagement_IRQn = -12,
BusFault_IRQn = -11,
UsageFault_IRQn = -10,
SVCall_IRQn = -5,
DebugMonitor_IRQn = -4,
PendSV_IRQn = -2,
SysTick_IRQn = -1,
/****** HT32F165x Specific Interrupt Numbers ***********************/
CKRDY_IRQn = 0,
LVD_IRQn = 1,
BOD_IRQn = 2,
WDT_IRQn = 3,
RTC_IRQn = 4,
FMC_IRQn = 5,
EVWUP_IRQn = 6,
LPWUP_IRQn = 7,
EXTI0_IRQn = 8,
EXTI1_IRQn = 9,
EXTI2_IRQn = 10,
EXTI3_IRQn = 11,
EXTI4_IRQn = 12,
EXTI5_IRQn = 13,
EXTI6_IRQn = 14,
EXTI7_IRQn = 15,
EXTI8_IRQn = 16,
EXTI9_IRQn = 17,
EXTI10_IRQn = 18,
EXTI11_IRQn = 19,
EXTI12_IRQn = 20,
EXTI13_IRQn = 21,
EXTI14_IRQn = 22,
EXTI15_IRQn = 23,
COMP_IRQn = 24,
ADC_IRQn = 25,
MCTM0_BRK_IRQn = 27,
MCTM0_UP_IRQn = 28,
MCTM0_TR_UP2_IRQn = 29,
MCTM0_CC_IRQn = 30,
MCTM1_BRK_IRQn = 31,
MCTM1_UP_IRQn = 32,
MCTM1_TR_UP2_IRQn = 33,
MCTM1_CC_IRQn = 34,
GPTM0_IRQn = 35,
GPTM1_IRQn = 36,
BFTM0_IRQn = 41,
BFTM1_IRQn = 42,
I2C0_IRQn = 43,
I2C1_IRQn = 44,
SPI0_IRQn = 45,
SPI1_IRQn = 46,
USART0_IRQn = 47,
USART1_IRQn = 48,
UART0_IRQn = 49,
UART1_IRQn = 50,
SCI_IRQn = 51,
I2C_IRQn = 52,
USB_IRQn = 53,
PDMA_CH0_IRQn = 55,
PDMA_CH1_IRQn = 56,
PDMA_CH2_IRQn = 57,
PDMA_CH3_IRQn = 58,
PDMA_CH4_IRQn = 59,
PDMA_CH5_IRQn = 60,
PDMA_CH6_IRQn = 61,
PDMA_CH7_IRQn = 62,
EBI_IRQn = 68,
} IRQn_Type;
/*
* ==========================================================================
* ----------- Processor and Core Peripheral Section ------------------------
* ==========================================================================
*/
/**
* @brief HT32F165x Interrupt Number Definition, according to the selected device
* in @ref Library_configuration_section
*/
#define __FPU_PRESENT 0
#define __MPU_PRESENT 0
#define __NVIC_PRIO_BITS 4
#define __Vendor_SysTickConfig 0
#define __CM3_REV 0x0201
#include "core_cm3.h" /* Cortex-M3 processor and core peripherals */
/****************************************************************/
/* Peripheral memory map */
/****************************************************************/
#define USART0_BASE ((uint32_t)0x40000000)
#define UART0_BASE ((uint32_t)0x40001000)
#define SPI0_BASE ((uint32_t)0x40004000)
#define ADC_BASE ((uint32_t)0x40010000)
#if defined(HT32F1655_6)
#define OPACMP0_BASE ((uint32_t)0x40018000)
#define OPACMP1_BASE ((uint32_t)0x40018100)
#endif
#define AFIO_BASE ((uint32_t)0x40022000)
#define EXTI_BASE ((uint32_t)0x40024000)
#define I2S_BASE ((uint32_t)0x40026000)
#define MCTM0_BASE ((uint32_t)0x4002C000)
#define MCTM1_BASE ((uint32_t)0x4002D000)
#define USART1_BASE ((uint32_t)0x40040000)
#define UART1_BASE ((uint32_t)0x40041000)
#define SCI_BASE ((uint32_t)0x40043000)
#define SPI1_BASE ((uint32_t)0x40044000)
#define I2C0_BASE ((uint32_t)0x40048000)
#define I2C1_BASE ((uint32_t)0x40049000)
#if defined(HT32F1653_4)
#define CMP0_BASE ((uint32_t)0x40058000)
#define CMP1_BASE ((uint32_t)0x40058100)
#endif
#define WDT_BASE ((uint32_t)0x40068000)
#define RTC_BASE ((uint32_t)0x4006A000)
#define PWRCU_BASE ((uint32_t)0x4006A000)
#define GPTM0_BASE ((uint32_t)0x4006E000)
#define GPTM1_BASE ((uint32_t)0x4006F000)
#define BFTM0_BASE ((uint32_t)0x40076000)
#define BFTM1_BASE ((uint32_t)0x40077000)
#define FMC_BASE ((uint32_t)0x40080000)
#define CKCU_BASE ((uint32_t)0x40088000)
#define RSTCU_BASE ((uint32_t)0x40088000)
#define CRC_BASE ((uint32_t)0x4008A000)
#define PDMA_BASE ((uint32_t)0x40090000)
#define EBI_BASE ((uint32_t)0x40098000)
#define USB_BASE ((uint32_t)0x400A8000)
#define USB_SRAM_BASE ((uint32_t)0x400AA000)
#define GPIO_A_BASE ((uint32_t)0x400B0000)
#define GPIO_B_BASE ((uint32_t)0x400B2000)
#define GPIO_C_BASE ((uint32_t)0x400B4000)
#define GPIO_D_BASE ((uint32_t)0x400B6000)
#if defined(HT32F1655_6)
#define GPIO_E_BASE ((uint32_t)0x400B8000)
#endif
// Registers Headers
#include "ht32f165x_reg.h"
/****************************************************************/
/* Peripheral declaration */
/****************************************************************/
#define USART0 ((USART_TypeDef *) USART0_BASE)
#define UART0 ((USART_TypeDef *) UART0_BASE)
#define SPI0 ((SPI_TypeDef *) SPI0_BASE)
#define ADC ((ADC_TypeDef *) ADC_BASE)
#if defined(HT32F1655_6)
#define OPACMP0 ((OPACMP_TypeDef *) OPACMP0_BASE)
#define OPACMP1 ((OPACMP_TypeDef *) OPACMP1_BASE)
#endif
#define AFIO ((AFIO_TypeDef *) AFIO_BASE)
#define EXTI ((EXTI_TypeDef *) EXTI_BASE)
#define I2S ((I2S_TypeDef *) I2S_BASE)
#define MCTM0 ((TM_TypeDef *) MCTM0_BASE)
#define MCTM1 ((TM_TypeDef *) MCTM1_BASE)
#define USART1 ((USART_TypeDef *) USART1_BASE)
#define UART1 ((USART_TypeDef *) UART1_BASE)
#define SCI ((SCI_TypeDef *) SCI_BASE)
#define SPI1 ((SPI_TypeDef *) SPI1_BASE)
#define I2C0 ((I2C_TypeDef *) I2C0_BASE)
#define I2C1 ((I2C_TypeDef *) I2C1_BASE)
#if defined(HT32F1653_4)
#define CMP0 ((CMP_TypeDef *) CMP0_BASE)
#define CMP1 ((CMP_TypeDef *) CMP1_BASE)
#endif
#define WDT ((WDT_TypeDef *) WDT_BASE)
#define RTC ((RTC_TypeDef *) RTC_BASE)
#define PWRCU ((PWRCU_TypeDef *) PWRCU_BASE)
#define GPTM0 ((TM_TypeDef *) GPTM0_BASE)
#define GPTM1 ((TM_TypeDef *) GPTM1_BASE)
#define BFTM0 ((BFTM_TypeDef *) BFTM0_BASE)
#define BFTM1 ((BFTM_TypeDef *) BFTM1_BASE)
#define FMC ((FMC_TypeDef *) FMC_BASE)
#define CKCU ((CKCU_TypeDef *) CKCU_BASE)
#define RSTCU ((RSTCU_TypeDef *) RSTCU_BASE)
#define CRC ((CRC_TypeDef *) CRC_BASE)
#define PDMA ((PDMA_TypeDef *) PDMA_BASE)
#define EBI ((EBI_TypeDef *) EBI_BASE)
#define USB ((USB_TypeDef *) USB_BASE)
#define GPIOA ((GPIO_TypeDef *) GPIO_A_BASE)
#define GPIO_A GPIOA
#define GPIOB ((GPIO_TypeDef *) GPIO_B_BASE)
#define GPIO_B GPIOB
#define GPIOC ((GPIO_TypeDef *) GPIO_C_BASE)
#define GPIO_C GPIOC
#define GPIOD ((GPIO_TypeDef *) GPIO_D_BASE)
#define GPIO_D GPIOD
#if defined(HT32F1655_6)
#define GPIOE ((GPIO_TypeDef *) GPIO_E_BASE)
#define GPIO_E GPIOE
#endif
#endif

View File

@ -0,0 +1,679 @@
#ifndef HT32F165x_REG_H
#define HT32F165x_REG_H
#ifndef __IO
#define __IO volatile
#endif
// Constants
// /////////////////////////////////////////////////////////////////////////////
#define AFIO_DEFAULT 0
#define AFIO_GPIO 1
#define AFIO_ADC 2
#define AFIO_CMP 3
#define AFIO_TM 4
#define AFIO_SPI 5
#define AFIO_USART 6
#define AFIO_I2C 7
#define AFIO_SMC 8
#define AFIO_EBI 9
#define AFIO_I2S 10
#define AFIO_OTHER 15
// Flash Memory Controller
// /////////////////////////////////////////////////////////////////////////////
typedef struct {
__IO uint32_t TADR; //!< 0x000 Flash Target Address Register
__IO uint32_t WRDR; //!< 0x004 Flash Write Data Register
uint32_t RESERVED0[1]; //!< 0x008 Reserved
__IO uint32_t OCMR; //!< 0x00C Flash Operation Command Register
__IO uint32_t OPCR; //!< 0x010 Flash Operation Control Register
__IO uint32_t OIER; //!< 0x014 Flash Operation Interrupt Enable Register
__IO uint32_t OISR; //!< 0x018 Flash Operation Interrupt and Status Register
uint32_t RESERVED1[1]; //!< 0x01C Reserved
__IO uint32_t PPSR[4]; //!< 0x020 ~ 0x02C Flash Page Erase/Program Protection Status Register
__IO uint32_t CPSR; //!< 0x030 Flash Security Protection Status Register
uint32_t RESERVED2[51]; //!< 0x034 ~ 0x0FC Reserved
__IO uint32_t VMCR; //!< 0x100 Flash Vector Mapping Control Register
uint32_t RESERVED3[31]; //!< 0x104 ~ 0x17C Reserved
__IO uint32_t MDID; //!< 0x180 Manufacturer and Device ID Register
__IO uint32_t PNSR; //!< 0x184 Flash Page Number Status Register
__IO uint32_t PSSR; //!< 0x188 Flash Page Size Status Register
#if defined(HT32F165x)
uint32_t RESERVED4[29]; //!< 0x18C ~ 0x1FC Reserved
#else
__IO uint32_t DID; //!< 0x18C Device ID Register
uint32_t RESERVED4[28]; //!< 0x190 ~ 0x1FC Reserved
#endif
__IO uint32_t CFCR; //!< 0x200 Flash Cache and Pre-fetch Control Register
uint32_t RESERVED5[63]; //!< 0x204 ~ 0x2FC Reserved
__IO uint32_t SBVT[4]; //!< 0x300 ~ 0x30C SRAM Booting Vector (4x32Bit)
#if defined(HT32F165x)
#else
__IO uint32_t CID[4]; //!< 0x310 ~ 0x31C Custom ID Register
#endif
} FMC_TypeDef;
#define FMC_OCMR_CMD_MASK (0xF << 0)
#define FMC_OCMR_CMD_IDLE (0x0 << 0)
#define FMC_OCMR_CMD_WORD_PROGRAM (0x4 << 0)
#define FMC_OCMR_CMD_PAGE_ERASE (0x8 << 0)
#define FMC_OCMR_CMD_MASS_ERASE (0xA << 0)
#define FMC_OPCR_OPM_MASK (0xF << 1)
#define FMC_OPCR_OPM_IDLE (0x6 << 1)
#define FMC_OPCR_OPM_COMMIT (0xA << 1)
#define FMC_OPCR_OPM_FINISHED (0xE << 1)
#define FMC_CFCR_CE (1U << 12)
#define FMC_CFCR_WAIT_MASK (7U << 0)
#define FMC_CFCR_WAIT_0 (1U)
#define FMC_CFCR_WAIT_1 (2U)
#define FMC_CFCR_WAIT_2 (3U)
// Power Control Unit
// /////////////////////////////////////////////////////////////////////////////
typedef struct {
uint32_t RESERVE0[64];
__IO uint32_t BAKSR; //!< 0x000 Status Register
__IO uint32_t BAKCR; //!< 0x004 Control Register
__IO uint32_t BAKTEST; //!< 0x008 Test Register
__IO uint32_t HSIRCR; //!< 0x00C HSI Ready Counter Control Register
__IO uint32_t LVDCSR; //!< 0x010 Low Voltage/Brown Out Detect Control and Status Register
uint32_t RESERVE1[59]; //!< 0x014 ~ 0x0FC Reserved
__IO uint32_t BAKREG[10]; //!< 0x100 ~ 0x124 Backup Register 0 ~ 9
} PWRCU_TypeDef;
// Clock Control Unit
// /////////////////////////////////////////////////////////////////////////////
typedef struct {
__IO uint32_t GCFGR; //!< 0x000 Global Clock Configuration Register
__IO uint32_t GCCR; //!< 0x004 Global Clock Control Register
__IO uint32_t GCSR; //!< 0x008 Global Clock Status Register
__IO uint32_t GCIR; //!< 0x00C Global Clock Interrupt Register
uint32_t RESERVED0[2]; //!< 0x010 ~ 0x014 Reserved
__IO uint32_t PLLCFGR; //!< 0x018 PLL Configuration Register
__IO uint32_t PLLCR; //!< 0x01C PLL Control Register
__IO uint32_t AHBCFGR; //!< 0x020 AHB Configuration Register
__IO uint32_t AHBCCR; //!< 0x024 AHB Clock Control Register
__IO uint32_t APBCFGR; //!< 0x028 APB Configuration Register
__IO uint32_t APBCCR0; //!< 0x02C APB Clock Control Register 0
__IO uint32_t APBCCR1; //!< 0x030 APB Clock Control Register 1
__IO uint32_t CKST; //!< 0x034 Clock source status Register
#if defined(HT32F1653_4)
__IO uint32_t APBPCSR0; //!< 0x038 APB Peripheral Clock Selection Register 0
__IO uint32_t APBPCSR1; //!< 0x03C APB Peripheral Clock Selection Register 1
__IO uint32_t HSICR; //!< 0x040 HSI Control Register
__IO uint32_t HSIATCR; //!< 0x044 HSI Auto Trimming Counter Register
#else
uint32_t RESERVED1[4]; //!< 0x038 ~ 0x044 Reserved
#endif
uint32_t RESERVED2[174]; //!< 0x048 ~ 0x2FC Reserved
__IO uint32_t LPCR; //!< 0x300 Low Power Control Register
__IO uint32_t MCUDBGCR; //!< 0x304 MCU Debug Control Register
} CKCU_TypeDef;
#define CKCU_GCFGR_LPMOD_MASK (7U << 29)
#define CKCU_GCFGR_USBPRE_MASK (3U << 22)
#define CKCU_GCFGR_URPRE_MASK (3U << 20)
#define CKCU_GCFGR_PLLSRC (1U << 8)
#define CKCU_GCFGR_CKOUTSRC_MASK (7U << 0)
#define CKCU_GCFGR_CKOUTSRC_CK_REF (0U << 0)
#define CKCU_GCFGR_CKOUTSRC_CK_AHB (1U << 0)
#define CKCU_GCFGR_CKOUTSRC_CK_SYS (2U << 0)
#define CKCU_GCFGR_CKOUTSRC_CK_HSE (3U << 0)
#define CKCU_GCFGR_CKOUTSRC_CK_HSI (4U << 0)
#define CKCU_GCFGR_CKOUTSRC_CK_LSE (5U << 0)
#define CKCU_GCFGR_CKOUTSRC_CK_LSI (6U << 0)
#define CKCU_GCCR_PSRCEN (1U << 17)
#define CKCU_GCCR_CKMEN (1U << 16)
#define CKCU_GCCR_HSIEN (1U << 11)
#define CKCU_GCCR_HSEEN (1U << 10)
#define CKCU_GCCR_PLLEN (1U << 9)
#define CKCU_GCCR_SW_MASK (3U << 0)
#define CKCU_GCCR_SW_PLL (1U << 0)
#define CKCU_GCCR_SW_HSE (2U << 0)
#define CKCU_GCCR_SW_HSI (3U << 0)
#define CKCU_GCSR_LSIRDY (1U << 5)
#define CKCU_GCSR_LSERDY (1U << 4)
#define CKCU_GCSR_HSIRDY (1U << 3)
#define CKCU_GCSR_HSERDY (1U << 2)
#define CKCU_GCSR_PLLRDY (1U << 1)
#define CKCU_PLLCFGR_PFBD_MASK (0x3fU << 23)
#define CKCU_PLLCFGR_POTD_MASK (3U << 21)
#define CKCU_PLLCR_PLLBPS (1U << 31)
#define CKCU_AHBCFGR_AHBPRE_MASK (3U << 0)
#define CKCU_AHBCCR_PAEN (1U << 16)
#define CKCU_AHBCCR_CRCEN (1U << 13)
#define CKCU_AHBCCR_EBIEN (1U << 12)
#define CKCU_AHBCCR_CKREFEN (1U << 11)
#define CKCU_AHBCCR_USBEN (1U << 10)
#define CKCU_APBCFGR_ADCDIV_MASK (7U << 16)
#define CKCU_APBCCR0_I2SEN (1U << 25)
#define CKCU_APBCCR0_SCIEN (1U << 24)
#define CKCU_APBCCR0_EXTIEN (1U << 15)
#define CKCU_APBCCR0_AFIOEN (1U << 14)
#define CKCU_APBCCR0_UR1EN (1U << 11)
#define CKCU_APBCCR0_UR0EN (1U << 10)
#define CKCU_APBCCR0_USR1EN (1U << 9)
#define CKCU_APBCCR0_USR0EN (1U << 8)
#define CKCU_APBCCR0_SPI1EN (1U << 5)
#define CKCU_APBCCR0_SPI0EN (1U << 4)
#define CKCU_APBCCR0_I2C1EN (1U << 1)
#define CKCU_APBCCR0_I2C0EN (1U << 0)
#define CKCU_APBCCR1_ADCEN (1U << 24)
#define CKCU_APBCCR1_OPA1EN (1U << 23)
#define CKCU_APBCCR1_OPA0EN (1U << 22)
#define CKCU_APBCCR1_BFTM1EN (1U << 17)
#define CKCU_APBCCR1_BFTM0EN (1U << 16)
#define CKCU_APBCCR1_GPTM1EN (1U << 9)
#define CKCU_APBCCR1_GPTM0EN (1U << 8)
#define CKCU_APBCCR1_BKPREN (1U << 6)
#define CKCU_APBCCR1_WDTREN (1U << 4)
#define CKCU_APBCCR1_MCTM1EN (1U << 1)
#define CKCU_APBCCR1_MCTM0EN (1U << 0)
#define CKCU_CKST_CKSWST_MASK (3U << 30)
#define CKCU_CKST_HSIST_MASK (7U << 24)
#define CKCU_CKST_HSEST_MASK (3U << 16)
#define CKCU_CKST_PLLST_MASK (0xfU << 8)
#define CKCU_LPCR_USBSLEEP (1U << 8)
#define CKCU_LPCR_BKISO (1U << 0)
// Reset Control Unit
// /////////////////////////////////////////////////////////////////////////////
typedef struct {
__IO uint32_t GRSR; //!< 0x000 Global Reset Status Register
__IO uint32_t AHBPRSTR; //!< 0x004 AHB Peripheral Reset Register
__IO uint32_t APBPRSTR0; //!< 0x008 APB Peripheral Reset Register 0
__IO uint32_t APBPRSTR1; //!< 0x00C APB Peripheral Reset Register 1
} RSTCU_TypeDef;
#define RSTCU_GRSR_PORSTF (1U << 3)
#define RSTCU_GRSR_WDTRSTF (1U << 2)
#define RSTCU_GRSR_EXTRSTF (1U << 1)
#define RSTCU_GRSR_SYSRSTF (1U << 0)
#define RSTCU_AHBPRSTR_PxRST(n) ((1U << 8) << (n))
#define RSTCU_AHBPRSTR_CRCRST (1U << 7)
#define RSTCU_AHBPRSTR_EBIRST (1U << 6)
#define RSTCU_AHBPRSTR_USBRST (1U << 5)
#define RSTCU_AHBPRSTR_DMARST (1U << 0)
#define RSTCU_APBPRSTR0_I2SRST (1U << 25)
#define RSTCU_APBPRSTR0_SCIRST (1U << 24)
#define RSTCU_APBPRSTR0_EXTIRST (1U << 15)
#define RSTCU_APBPRSTR0_AFIORST (1U << 14)
#define RSTCU_APBPRSTR0_UR1RST (1U << 11)
#define RSTCU_APBPRSTR0_UR0RST (1U << 10)
#define RSTCU_APBPRSTR0_USR1RST (1U << 9)
#define RSTCU_APBPRSTR0_USR0RST (1U << 8)
#define RSTCU_APBPRSTR0_SPI1RST (1U << 5)
#define RSTCU_APBPRSTR0_SPI0RST (1U << 4)
#define RSTCU_APBPRSTR0_I2C1RST (1U << 1)
#define RSTCU_APBPRSTR0_I2C0RST (1U << 0)
#define RSTCU_APBPRSTR1_ADCRST (1U << 24)
#define RSTCU_APBPRSTR1_OPA1RST (1U << 23)
#define RSTCU_APBPRSTR1_OPA0RST (1U << 22)
#define RSTCU_APBPRSTR1_BFTM1RST (1U << 17)
#define RSTCU_APBPRSTR1_BFTM0RST (1U << 16)
#define RSTCU_APBPRSTR1_GPTM1RST (1U << 9)
#define RSTCU_APBPRSTR1_GPTM0RST (1U << 8)
#define RSTCU_APBPRSTR1_WDTRST (1U << 4)
#define RSTCU_APBPRSTR1_MCTM1RST (1U << 1)
#define RSTCU_APBPRSTR1_MCTM0RST (1U << 0)
// General Purpose I/O
// /////////////////////////////////////////////////////////////////////////////
typedef struct {
__IO uint32_t DIRCR; //!< 0x000 Data Direction Control Register
__IO uint32_t INER; //!< 0x004 Input function enable register
__IO uint32_t PUR; //!< 0x008 Pull-Up Selection Register
__IO uint32_t PDR; //!< 0x00C Pull-Down Selection Register
__IO uint32_t ODR; //!< 0x010 Open Drain Selection Register
__IO uint32_t DRVR; //!< 0x014 Drive Current Selection Register
__IO uint32_t LOCKR; //!< 0x018 Lock Register
__IO uint32_t DINR; //!< 0x01c Data Input Register
__IO uint32_t DOUTR; //!< 0x020 Data Output Register
__IO uint32_t SRR; //!< 0x024 Output Set and Reset Control Register
__IO uint32_t RR; //!< 0x028 Output Reset Control Register
} GPIO_TypeDef;
// Alternate Function Input/Output
// /////////////////////////////////////////////////////////////////////////////
typedef struct {
__IO uint32_t ESSR[2]; //!< 0x000 ~ 0x004 EXTI Source Selection Register 0 ~ 1
uint32_t RESERVE0[6]; //!< 0x008 ~ 0x01C Reserved
union {
struct {
__IO uint32_t GPACFGR[2]; //!< 0x020 ~ 0x024 GPIO Port A Configuration Register 0 ~ 1
__IO uint32_t GPBCFGR[2]; //!< 0x028 ~ 0x02C GPIO Port B Configuration Register 0 ~ 1
__IO uint32_t GPCCFGR[2]; //!< 0x030 ~ 0x034 GPIO Port C Configuration Register 0 ~ 1
__IO uint32_t GPDCFGR[2]; //!< 0x038 ~ 0x03C GPIO Port D Configuration Register 0 ~ 1
#if defined(HT32F1655_6)
__IO uint32_t GPECFGR[2]; //!< 0x040 ~ 0x044 GPIO Port E Configuration Register 0 ~ 1
#endif
};
// alternate mapping
struct {
__IO uint32_t GPxCFGR[0][2]; //!< 0x020 ~ 0x044 GPIO Port x Configuration Register 0 ~ 1
};
};
} AFIO_TypeDef;
// Nested Vectored Interrupt Controller
// /////////////////////////////////////////////////////////////////////////////
// Implemented in Cortex-M3 Headers
// External Interrupt/Event Controller
// /////////////////////////////////////////////////////////////////////////////
typedef struct {
__IO uint32_t CFGR0; //!< 0x000 EXTI Interrupt 0 Configuration Register
__IO uint32_t CFGR1; //!< 0x004 EXTI Interrupt 1 Configuration Register
__IO uint32_t CFGR2; //!< 0x008 EXTI Interrupt 2 Configuration Register
__IO uint32_t CFGR3; //!< 0x00C EXTI Interrupt 3 Configuration Register
__IO uint32_t CFGR4; //!< 0x010 EXTI Interrupt 4 Configuration Register
__IO uint32_t CFGR5; //!< 0x014 EXTI Interrupt 5 Configuration Register
__IO uint32_t CFGR6; //!< 0x018 EXTI Interrupt 6 Configuration Register
__IO uint32_t CFGR7; //!< 0x01C EXTI Interrupt 7 Configuration Register
__IO uint32_t CFGR8; //!< 0x020 EXTI Interrupt 8 Configuration Register
__IO uint32_t CFGR9; //!< 0x024 EXTI Interrupt 9 Configuration Register
__IO uint32_t CFGR10; //!< 0x028 EXTI Interrupt 10 Configuration Register
__IO uint32_t CFGR11; //!< 0x02C EXTI Interrupt 11 Configuration Register
__IO uint32_t CFGR12; //!< 0x030 EXTI Interrupt 12 Configuration Register
__IO uint32_t CFGR13; //!< 0x034 EXTI Interrupt 13 Configuration Register
__IO uint32_t CFGR14; //!< 0x038 EXTI Interrupt 14 Configuration Register
__IO uint32_t CFGR15; //!< 0x03C EXTI Interrupt 15 Configuration Register
__IO uint32_t CR; //!< 0x040 EXTI Interrupt Control Register
__IO uint32_t EDGEFLGR; //!< 0x044 EXTI Interrupt Edge Flag Register
__IO uint32_t EDGESR; //!< 0x048 EXTI Interrupt Edge Status Register
__IO uint32_t SSCR; //!< 0x04C EXTI Interrupt Software Set Command Register
__IO uint32_t WAKUPCR; //!< 0x050 EXTI Interrupt Wakeup Control Register
__IO uint32_t WAKUPPOLR; //!< 0x054 EXTI Interrupt Wakeup Polarity Register
__IO uint32_t WAKUPFLG; //!< 0x058 EXTI Interrupt Wakeup Flag Register
} EXTI_TypeDef;
// Analog To Digital Converter
// /////////////////////////////////////////////////////////////////////////////
// Operational Amplifier / Comparator
// /////////////////////////////////////////////////////////////////////////////
#if defined(HT32F1653_4)
typedef struct {
__IO uint32_t CR; //!< 0x000 Comparator Control Register
__IO uint32_t VALR; //!< 0x004 Comparator Voltage Reference Register
__IO uint32_t IER; //!< 0x008 Comparator Interrupt Enable Register
__IO uint32_t TFR; //!< 0x00C Comparator Transition Flag Register
} CMP_TypeDef;
#else
typedef struct {
__IO uint32_t OPACR; //!< 0x000 Operational Amplifier Control Register
__IO uint32_t OFVCR; //!< 0x004 Comparator Input Offset Voltage Cancellation Register
__IO uint32_t CMPIER; //!< 0x008 Comparator Interrupt Enable Register
__IO uint32_t CMPRSR; //!< 0x00C Comparator Raw Status Register
__IO uint32_t CMPISR; //!< 0x010 Comparator Masked Interrupt Status Register
__IO uint32_t CMPICLR; //!< 0x014 Comparator Interrupt Clear Register
} OPACMP_TypeDef;
#endif
// Basic Function Timers
// /////////////////////////////////////////////////////////////////////////////
typedef struct {
__IO uint32_t CR; //!< 0x000 Control Register
__IO uint32_t SR; //!< 0x004 Status Register
__IO uint32_t CNTR; //!< 0x008 Counter Value Register
__IO uint32_t CMP; //!< 0x00C Compare Value Register
} BFTM_TypeDef;
#define BFTM_CR_CEN (1U << 2)
#define BFTM_CR_OSM (1U << 1)
#define BFTM_CR_MIEN (1U << 0)
#define BFTM_SR_MIF (1U << 0)
// General Purpose Timers
// Motor Control Timers
// /////////////////////////////////////////////////////////////////////////////
typedef struct {
__IO uint32_t CNTCFR; //!< 0x000 Timer Counter Configuaration Register
__IO uint32_t MDCFR; //!< 0x004 Timer Mode Configuration Register
__IO uint32_t TRCFR; //!< 0x008 Timer Trigger Configuration Register
uint32_t RESERVED0[1]; //!< 0x00C Reserved
__IO uint32_t CTR; //!< 0x010 Timer Counter Register
uint32_t RESERVED1[3]; //!< 0x014 ~ 0x01C Reserved
__IO uint32_t CHnICFR[4]; //!< 0x020 ~ 0x02C Channel n Input Configuration Register
uint32_t RESERVED2[4]; //!< 0x030 ~ 0x03C Reserved
__IO uint32_t CHnOCFR[4]; //!< 0x040 ~ 0x04C Channel n Output Configuration Register
__IO uint32_t CHCTR; //!< 0x050 Channel Control Register
__IO uint32_t CHPOLR; //!< 0x054 Channel Polarity Control Register
uint32_t RESERVED3[5]; //!< 0x058 ~ 0x068 Reserved
// note: only available as MCTM
__IO uint32_t CHBRKCFR; //!< 0x06C Channel Break Configuration Register
__IO uint32_t CHBRKCTR; //!< 0x070 Channel Break Control Register
// end note
__IO uint32_t DICTR; //!< 0x074 Timer PDMA/Interrupt Control Register
__IO uint32_t EVGR; //!< 0x078 Timer Event Generator Register
__IO uint32_t INTSR; //!< 0x07C Timer Interrupt Status Register
__IO uint32_t CNTR; //!< 0x080 Timer Counter Register
__IO uint32_t PSCR; //!< 0x084 Timer Prescaler Register
__IO uint32_t CRR; //!< 0x088 Timer Counter Reload Register
// note: only available as MCTM
__IO uint32_t REPR; //!< 0x08C Timer Repetition Register
// end note
__IO uint32_t CHnCCR[4]; //!< 0x090 ~ 0x09C Channel n Capture/Compare Register
__IO uint32_t CHnACR[4]; //!< 0x0A0 ~ 0x0AC Channel n Asymmentric Compare Register
} TM_TypeDef;
#define TM_CNTCFR_CMSEL_MASK (3U << 16)
#define TM_CNTCFR_CMSEL_MODE_3 (3U << 16)
#define TM_CNTCFR_CMSEL_MODE_2 (2U << 16)
#define TM_CNTCFR_CMSEL_MODE_1 (1U << 16)
#define TM_CNTCFR_CMSEL_MODE_0 (0U << 16)
#define TM_CTR_CHCCDS (1U << 16)
#define TM_CTR_COMUS (1U << 9)
#define TM_CTR_COMPRE (1U << 8)
#define TM_CTR_CRBE (1U << 1)
#define TM_CTR_TME (1U << 0)
#define TM_CHnOCFR_CHnPRE (1U << 4)
#define TM_CHnOCFR_REFnCE (1U << 3)
#define TM_CHnOCFR_CHnOM(n) ((((n)>>0)&7)|((((n)>>3)&1)<<8))
#define TM_CHBRKCTR_CHMOE (1U << 4)
// Real Time Clock
// /////////////////////////////////////////////////////////////////////////////
// Watchdog Timer
// /////////////////////////////////////////////////////////////////////////////
// I2C
// /////////////////////////////////////////////////////////////////////////////
typedef struct {
__IO uint32_t CR; //!< 0x000 Control Register
__IO uint32_t IER; //!< 0x004 Interrupt Enable Register
__IO uint32_t ADDR; //!< 0x008 Address Register
__IO uint32_t SR; //!< 0x00C Status Register
__IO uint32_t SHPGR; //!< 0x010 SCL High Period Generation Register
__IO uint32_t SLPGR; //!< 0x014 SCL Low Period Generation Register
__IO uint32_t DR; //!< 0x018 Data Register
__IO uint32_t TAR; //!< 0x01C Target Register
__IO uint32_t ADDMR; //!< 0x020 Address Mask Register
__IO uint32_t ADDSR; //!< 0x024 Address Snoop Register
__IO uint32_t TOUT; //!< 0x028 Timeout Register
} I2C_TypeDef;
#define I2C_CR_SEQ_FILTER_MASK (3U << 14)
#define I2C_CR_SEQ_FILTER_2_PCLK (2U << 14)
#define I2C_CR_SEQ_FILTER_1_PCLK (1U << 14)
#define I2C_CR_SEQ_FILTER_DISABLE (0U << 14)
#define I2C_CR_COMB_FILTER_En (1U << 13)
#define I2C_CR_ENTOUT (1U << 12)
#define I2C_CR_DMANACK (1U << 10)
#define I2C_CR_RXDMAE (1U << 9)
#define I2C_CR_TXDMAE (1U << 8)
#define I2C_CR_ADRM (1U << 7)
#define I2C_CR_I2CEN (1U << 3)
#define I2C_CR_GCEN (1U << 2)
#define I2C_CR_STOP (1U << 1)
#define I2C_CR_AA (1U << 0)
#define I2C_IER_RXBFIE (1U << 18)
#define I2C_IER_TXDEIE (1U << 17)
#define I2C_IER_RXDNEIE (1U << 16)
#define I2C_IER_TOUTIE (1U << 11)
#define I2C_IER_BUSERRIE (1U << 10)
#define I2C_IER_RXNACKIE (1U << 9)
#define I2C_IER_ARBLOSIE (1U << 8)
#define I2C_IER_GCSIE (1U << 3)
#define I2C_IER_ADRSIE (1U << 2)
#define I2C_IER_STOIE (1U << 1)
#define I2C_IER_STAIE (1U << 0)
#define I2C_SR_TXNRX (1U << 21)
#define I2C_SR_MASTER (1U << 20)
#define I2C_SR_BUSBUSY (1U << 19)
#define I2C_SR_RXBF (1U << 18)
#define I2C_SR_TXDE (1U << 17)
#define I2C_SR_RXDNE (1U << 16)
#define I2C_SR_TOUTF (1U << 11)
#define I2C_SR_BUSERR (1U << 10)
#define I2C_SR_RXNACK (1U << 9)
#define I2C_SR_ARBLOS (1U << 8)
#define I2C_SR_GCS (1U << 3)
#define I2C_SR_ADRS (1U << 2)
#define I2C_SR_STO (1U << 1)
#define I2C_SR_STA (1U << 0)
#define I2C_TAR_RWD (1U << 10)
// SPI
// /////////////////////////////////////////////////////////////////////////////
typedef struct {
__IO uint32_t CR0; //!< 0x000 Control Register 0
__IO uint32_t CR1; //!< 0x004 Control Register 1
__IO uint32_t IER; //!< 0x008 Interrupt Enable Register
__IO uint32_t CPR; //!< 0x00C Clock Prescaler Register
__IO uint32_t DR; //!< 0x010 Data Register
__IO uint32_t SR; //!< 0x014 Status Register
__IO uint32_t FCR; //!< 0x018 FIFO Control Register
__IO uint32_t FSR; //!< 0x01C FIFO Status Register
__IO uint32_t FTOCR; //!< 0x020 FIFO Time Out Counter Register
} SPI_TypeDef;
#define SPI_CR0_GUADTEN (1U << 7)
#define SPI_CR0_DUALEN (1U << 6)
#define SPI_CR0_SSELC (1U << 4)
#define SPI_CR0_SELOEN (1U << 3)
#define SPI_CR0_SPIEN (1U << 0)
#define SPI_CR1_MODE (1U << 14)
#define SPI_CR1_SELM (1U << 13)
#define SPI_CR1_FIRSTBIT (1U << 12)
#define SPI_CR1_SELAP (1U << 11)
#define SPI_CR1_FORMAT_MASK (7U << 8)
#define SPI_CR1_FORMAT_MODE0 (0x1U << 8)
#define SPI_CR1_FORMAT_MODE1 (0x2U << 8)
#define SPI_CR1_FORMAT_MODE2 (0x6U << 8)
#define SPI_CR1_FORMAT_MODE3 (0x5U << 8)
#define SPI_IER_RXBNEIEN (1U << 2)
#define SPI_IER_TXBEIEN (1U << 0)
#define SPI_SR_RXBNE (1U << 2)
#define SPI_SR_TXE (1U << 1)
#define SPI_SR_TXBE (1U << 0)
#define SPI_FCR_FIFOEN (1U << 10)
#define SPI_FSR_TXFS_MASK (0xfU << 0)
#define SPI_FSR_RXFS_MASK (0xfU << 4)
// USART
// UART
// /////////////////////////////////////////////////////////////////////////////
typedef struct {
union {
__IO uint32_t RBR; //!< 0x000 Receive Buffer Register
__IO uint32_t TBR; //!< 0x000 Transmit Holding Register
__IO uint32_t DR; //!< 0x000 Data Register
};
__IO uint32_t IER; //!< 0x004 Interrupt Enable Register
__IO uint32_t IIR; //!< 0x008 Interrupt Identification Register/FIFO Control Register
__IO uint32_t FCR; //!< 0x00C FIFO Control Register
__IO uint32_t LCR; //!< 0x010 Line Control Register
// note: only available as USART
__IO uint32_t MODCR; //!< 0x014 Modem Control Register
// end note
__IO uint32_t LSR; //!< 0x018 Line Status Register
// note: only available as USART
__IO uint32_t MODSR; //!< 0x01C Modem Status Register
// end note
__IO uint32_t TPR; //!< 0x020 Timing Parameter Register
__IO uint32_t MDR; //!< 0x024 Mode Register
// note: only available as USART
__IO uint32_t IrDACR; //!< 0x028 IrDA Control Register
__IO uint32_t RS485CR; //!< 0x02C RS485 Control Register
__IO uint32_t SYNCR; //!< 0x030 Synchronous Control Register
// end note
__IO uint32_t FSR; //!< 0x034 FIFO Status Register
__IO uint32_t DLR; //!< 0x038 Divisor Latch Register
uint32_t RESERVED0; //!< 0x03C Reserved
__IO uint32_t DEGTSTR; //!< 0x040 Debug/Test Register
} USART_TypeDef;
#define USART_FCR_FME (1 << 0)
#define USART_FCR_RFR (1 << 1)
#define USART_FCR_TFR (1 << 2)
#define USART_FCR_TFTL_MASK (0x3 << 4)
#define USART_FCR_TFTL_0BYTE (0x0 << 4)
#define USART_FCR_TFTL_2BYTE (0x1 << 4)
#define USART_FCR_TFTL_4BYTE (0x2 << 4)
#define USART_FCR_TFTL_8BYTE (0x3 << 4)
#define USART_FCR_RFTL_MASK (0x3 << 6)
#define USART_FCR_RFTL_1BYTE (0x0 << 6)
#define USART_FCR_RFTL_4BYTE (0x1 << 6)
#define USART_FCR_RFTL_8BYTE (0x2 << 6)
#define USART_FCR_RFTL_14BYTE (0x3 << 6)
#define USART_FCR_URTXEN (1 << 8)
#define USART_FCR_URRXEN (1 << 9)
#define USART_LCR_WLS_MASK (0x3 << 0)
#define USART_LCR_WLS_7BIT (0x0 << 0)
#define USART_LCR_WLS_8BIT (0x1 << 0)
#define USART_LCR_WLS_9BIT (0x2 << 0)
#define USART_LCR_NSB (1 << 2)
#define USART_LCR_PBE (1 << 3)
#define USART_LCR_EPE (1 << 4)
#define USART_LCR_SPE (1 << 5)
#define USART_LCR_BCB (1 << 6)
#define USART_LSR_RFDR (1 << 0)
#define USART_LSR_OEI (1 << 1)
#define USART_LSR_PEI (1 << 2)
#define USART_LSR_FEI (1 << 3)
#define USART_LSR_BII (1 << 4)
#define USART_LSR_TXFEMPT (1 << 5)
#define USART_LSR_TXEMPT (1 << 6)
#define USART_LSR_ERRRX (1 << 7)
#define USART_LSR_RSADDEF (1 << 8)
#define USART_MDR_MODE_MASK (0x3 << 0)
#define USART_MDR_MODE_NORMAL (0x0 << 0)
#define USART_MDR_MODE_IRDA (0x1 << 0)
#define USART_MDR_MODE_RS485 (0x2 << 0)
#define USART_MDR_MODE_SYNCHRONOUS (0x3 << 0)
#define USART_MDR_TRSM (1 << 2)
#define USART_MDR_TXDMAEN (1 << 4)
#define USART_MDR_RXDMAEN (1 << 5)
// Smart Card Interface
// /////////////////////////////////////////////////////////////////////////////
// USB
// /////////////////////////////////////////////////////////////////////////////
typedef struct {
__IO uint32_t CSR; //!< 0x000 USB Control and Status Register
__IO uint32_t IER; //!< 0x004 USB Interrupt Enable Register
__IO uint32_t ISR; //!< 0x008 USB Interrupt Status Register
__IO uint32_t FCR; //!< 0x00C USB Frame Count Register
__IO uint32_t DEVAR; //!< 0x010 USB Device Address Register
struct {
__IO uint32_t CSR; //!< 0x014 USB Endpoint n Control and Status Register
__IO uint32_t IER; //!< 0x018 USB Endpoint n Interrupt Enable Register
__IO uint32_t ISR; //!< 0x01C USB Endpoint n Interrupt Status Register
__IO uint32_t TCR; //!< 0x020 USB Endpoint n Transfer Count Register
__IO uint32_t CFGR; //!< 0x024 USB Endpoint n Configuration Register
} EP[8];
} USB_TypeDef;
// USBCSR
#define USBCSR_FRES (0x002) // Force USB Reset Control
#define USBCSR_PDWN (0x004) // Power Down Mode Control
#define USBCSR_LPMODE (0x008) // Low-Power Mode Control
#define USBCSR_GENRSM (0x020) // Resume Request Generation Control
#define USBCSR_RXDP (0x040) // Received DP Line Status
#define USBCSR_RXDM (0x080) // Received DM Line Status
#define USBCSR_ADRSET (0x100) // Device Address Setting Control
#define USBCSR_SRAMRSTC (0x200) // USB SRAM Reset Condition
#define USBCSR_DPPUEN (0x400) // DP Pull Up Enable
#define USBCSR_DPWKEN (0x800) // DP Wake Up Enable
// USBIER
#define USBIER_UGIE (0x0001) // USB global Interrupt Enable
#define USBIER_SOFIE (0x0002) // Start Of Frame Interrupt Enable
#define USBIER_URSTIE (0x0004) // USB Reset Interrupt Enable
#define USBIER_RSMIE (0x0008) // Resume Interrupt Enable
#define USBIER_SUSPIE (0x0010) // Suspend Interrupt Enable
#define USBIER_ESOFIE (0x0020) // Expected Start Of Frame Enable
#define USBIER_EP0IE (0x0100) // Endpoint 0 Interrupt Enable
#define USBIER_EP1IE (0x0200) // Endpoint 1 Interrupt Enable
#define USBIER_EP2IE (0x0400) // Endpoint 2 Interrupt Enable
#define USBIER_EP3IE (0x0800) // Endpoint 3 Interrupt Enable
#define USBIER_EP4IE (0x1000) // Endpoint 4 Interrupt Enable
#define USBIER_EP5IE (0x2000) // Endpoint 5 Interrupt Enable
#define USBIER_EP6IE (0x4000) // Endpoint 6 Interrupt Enable
#define USBIER_EP7IE (0x8000) // Endpoint 7 Interrupt Enable
// USBISR
#define USBISR_SOFIF (0x0002) // Start Of Frame Interrupt Flag
#define USBISR_URSTIF (0x0004) // USB Reset Interrupt Flag
#define USBISR_RSMIF (0x0008) // Resume Interrupt Flag
#define USBISR_SUSPIF (0x0010) // Suspend Interrupt Flag
#define USBISR_ESOFIF (0x0020) // Expected Start Of Frame Interrupt
#define USBISR_EP0IF (1U << 8) // Endpoint 0 Interrupt Flag
#define USBISR_EP1IF (1U << 9) // Endpoint 1 Interrupt Flag
#define USBISR_EP2IF (1U << 10) // Endpoint 2 Interrupt Flag
#define USBISR_EP3IF (1U << 11) // Endpoint 3 Interrupt Flag
#define USBISR_EP4IF (1U << 12) // Endpoint 4 Interrupt Flag
#define USBISR_EP5IF (1U << 13) // Endpoint 5 Interrupt Flag
#define USBISR_EP6IF (1U << 14) // Endpoint 6 Interrupt Flag
#define USBISR_EP7IF (1U << 15) // Endpoint 7 Interrupt Flag
#define USBISR_EPnIF (0xFF00) // Endpoint Interrupt Mask
// USBFCR
#define USBFCR_FRNUM (0x7FF) // Frame Number
#define USBFCR_SOFLCK (1U << 16) // Start-of-Frame Lock Flag
#define USBFCR_LSOF (0x3U << 17) // Lost Start-of-Frame Number
// USBEPnCSR
#define USBEPnCSR_DTGTX (0x01) // Data Toggle Status, for IN transfer
#define USBEPnCSR_NAKTX (0x02) // NAK Status, for IN transfer
#define USBEPnCSR_STLTX (0x04) // STALL Status, for IN transfer
#define USBEPnCSR_DTGRX (0x08) // Data Toggle Status, for OUT transfer
#define USBEPnCSR_NAKRX (0x10) // NAK Status, for OUT transfer
#define USBEPnCSR_STLRX (0x20) // STALL Status, for OUT transfer
// USBEPnIER
#define USBEPnIER_OTRXIE (0x001) // OUT Token Received Interrupt Enable
#define USBEPnIER_ODRXIE (0x002) // OUT Data Received Interrupt Enable
#define USBEPnIER_ODOVIE (0x004) // OUT Data Buffer Overrun Interrupt Enable
#define USBEPnIER_ITRXIE (0x008) // IN Token Received Interrupt Enable
#define USBEPnIER_IDTXIE (0x010) // IN Data Transmitted Interrupt Enable
#define USBEPnIER_NAKIE (0x020) // NAK Transmitted Interrupt Enable
#define USBEPnIER_STLIE (0x040) // STALL Transmitted Interrupt Enable
#define USBEPnIER_UERIE (0x080) // USB Error Interrupt Enable
#define USBEPnIER_STRXIE (0x100) // SETUP Token Received Interrupt Enable
#define USBEPnIER_SDRXIE (0x200) // SETUP Data Received Interrupt Enable
#define USBEPnIER_SDERIE (0x400) // SETUP Data Error Interrupt Enable
#define USBEPnIER_ZLRXIE (0x800) // Zero Length Data Received Interrupt Enable
// USBEPnISR
#define USBEPnISR_OTRXIF (0x001) // OUT Token Received Interrupt Flag
#define USBEPnISR_ODRXIF (0x002) // OUT Data Received Interrupt Flag
#define USBEPnISR_ODOVIF (0x004) // OUT Data Buffer Overrun Interrupt Flag
#define USBEPnISR_ITRXIF (0x008) // IN Token Received Interrupt Flag
#define USBEPnISR_IDTXIF (0x010) // IN Data Transmitted Interrupt Flag
#define USBEPnISR_NAKIF (0x020) // NAK Transmitted Interrupt Flag
#define USBEPnISR_STLIF (0x040) // STALL Transmitted Interrupt Flag
#define USBEPnISR_UERIF (0x080) // USB Error Interrupt Flag
#define USBEPnISR_STRXIF (0x100) // SETUP Token Received Interrupt Flag
#define USBEPnISR_SDRXIF (0x200) // SETUP Data Received Interrupt Flag
#define USBEPnISR_SDERIF (0x400) // SETUP Data Error Interrupt Flag
#define USBEPnISR_ZLRXIF (0x800) // Zero Length Data Received Interrupt Flag
// USBEPnTCR
#define USBEPnTCR_TCNT (0x1FF) // Transfer Byte Count
// USBEPnCFGR
#define USBEPnCFGR_EPEN (1U << 31) // Endpoint Enable
#define USBEPnCFGR_EPTYPE (1U << 29) // Transfer Type
#define USBEPnCFGR_EPDIR (1U << 28) // Transfer Direction
#define USBEPnCFGR_EPADR (0xFU << 24) // Endpoint Address
#define USBEPnCFGR_EPLEN (0x7FU << 10) // Buffer Length
#define USBEPnCFGR_EPBUFA (0x3FF) // Endpoint Buffer Address
// Peripheral Direct Memory Access
// /////////////////////////////////////////////////////////////////////////////
// Extend Bus Interface
// /////////////////////////////////////////////////////////////////////////////
// Inter-IC Sound
// /////////////////////////////////////////////////////////////////////////////
// CRC
// /////////////////////////////////////////////////////////////////////////////
#endif // HT32F165x_REG_H

View File

@ -0,0 +1,199 @@
/*
* Copyright (C) 2020 Codetector <codetector@codetector.cn>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#pragma once
#if defined(HT32F52342) || defined(HT32F52352)
#define HT32F523x2
#else
#error "Unknown HT32 device"
#endif
#if defined(HT32F523x2)
#define HT32
#endif
/*
* ==============================================================
* ---------- Interrupt Number Definition -----------------------
* ==============================================================
*/
typedef enum IRQn
{
/****** Cortex-M3 Processor Exceptions Numbers ****************/
InitialSP_IRQn = -16,
InitialPC_IRQn = -15,
NonMaskableInt_IRQn = -14,
HardFault_IRQn = -13,
SVCall_IRQn = -5,
PendSV_IRQn = -2,
SysTick_IRQn = -1,
/****** HT32F165x Specific Interrupt Numbers ***********************/
LVD_IRQn = 0,
RTC_IRQn = 1,
FMC_IRQn = 2,
WKUP_IRQn = 3,
EXTI0_1_IRQn = 4,
EXTI2_3_IRQn = 5,
EXTI4_15_IRQn = 6,
CMP_IRQn = 7,
ADC_IRQn = 8,
MCTM_IRQn = 10,
GPTM1_IRQn = 11,
GPTM0_IRQn = 12,
SCTM0_IRQn = 13,
SCTM1_IRQn = 14,
BFTM0_IRQn = 17,
BFTM1_IRQn = 18,
I2C0_IRQn = 19,
I2C1_IRQn = 20,
SPI0_IRQn = 21,
SPI1_IRQn = 22,
USART0_IRQn = 23,
USART1_IRQn = 24,
UART0_IRQn = 25,
UART1_IRQn = 26,
SCI_IRQn = 27,
I2S_IRQn = 28,
USB_IRQn = 29,
PDMA_CH0_1_IRQn = 30,
PDMA_CH2_5_IRQn = 31
} IRQn_Type;
/*
* ==========================================================================
* ----------- Processor and Core Peripheral Section ------------------------
* ==========================================================================
*/
/**
* @brief HT32F165x Interrupt Number Definition, according to the selected device
* in @ref Library_configuration_section
*/
#define __FPU_PRESENT 0
#define __MPU_PRESENT 0
#define __NVIC_PRIO_BITS 8
#define __Vendor_SysTickConfig 0
#include "core_cm0plus.h" /* Cortex-M0+ processor and core peripherals */
/****************************************************************/
/* Peripheral memory map */
/****************************************************************/
#define USART0_BASE ((uint32_t)0x40000000)
#define UART0_BASE ((uint32_t)0x40001000)
#define SPI0_BASE ((uint32_t)0x40004000)
#define ADC_BASE ((uint32_t)0x40010000)
#define AFIO_BASE ((uint32_t)0x40022000)
#define EXTI_BASE ((uint32_t)0x40024000)
#define I2S_BASE ((uint32_t)0x40026000)
#define MCTM0_BASE ((uint32_t)0x4002C000)
#define MCTM1_BASE ((uint32_t)0x4002D000)
#define USART1_BASE ((uint32_t)0x40040000)
#define UART1_BASE ((uint32_t)0x40041000)
#define SCI_BASE ((uint32_t)0x40043000)
#define SPI1_BASE ((uint32_t)0x40044000)
#define I2C0_BASE ((uint32_t)0x40048000)
#define I2C1_BASE ((uint32_t)0x40049000)
#define CMP0_BASE ((uint32_t)0x40058000)
#define CMP1_BASE ((uint32_t)0x40058100)
#define WDT_BASE ((uint32_t)0x40068000)
#define RTC_BASE ((uint32_t)0x4006A000)
#define PWRCU_BASE ((uint32_t)0x4006A000)
#define GPTM0_BASE ((uint32_t)0x4006E000)
#define GPTM1_BASE ((uint32_t)0x4006F000)
#define BFTM0_BASE ((uint32_t)0x40076000)
#define BFTM1_BASE ((uint32_t)0x40077000)
#define FMC_BASE ((uint32_t)0x40080000)
#define CKCU_BASE ((uint32_t)0x40088000)
#define RSTCU_BASE ((uint32_t)0x40088000)
#define CRC_BASE ((uint32_t)0x4008A000)
#define PDMA_BASE ((uint32_t)0x40090000)
#define EBI_BASE ((uint32_t)0x40098000)
#define USB_BASE ((uint32_t)0x400A8000)
#define USB_SRAM_BASE ((uint32_t)0x400AA000)
#define GPIO_A_BASE ((uint32_t)0x400B0000)
#define GPIO_B_BASE ((uint32_t)0x400B2000)
#define GPIO_C_BASE ((uint32_t)0x400B4000)
#define GPIO_D_BASE ((uint32_t)0x400B6000)
// Registers Headers
#include "ht32f523x2_reg.h"
/****************************************************************/
/* Peripheral declaration */
/****************************************************************/
#define USART0 ((USART_TypeDef *) USART0_BASE)
#define UART0 ((USART_TypeDef *) UART0_BASE)
#define SPI0 ((SPI_TypeDef *) SPI0_BASE)
#define ADC ((ADC_TypeDef *) ADC_BASE)
#define AFIO ((AFIO_TypeDef *) AFIO_BASE)
#define EXTI ((EXTI_TypeDef *) EXTI_BASE)
#define I2S ((I2S_TypeDef *) I2S_BASE)
#define MCTM0 ((TM_TypeDef *) MCTM0_BASE)
#define MCTM1 ((TM_TypeDef *) MCTM1_BASE)
#define USART1 ((USART_TypeDef *) USART1_BASE)
#define UART1 ((USART_TypeDef *) UART1_BASE)
#define SCI ((SCI_TypeDef *) SCI_BASE)
#define SPI1 ((SPI_TypeDef *) SPI1_BASE)
#define I2C0 ((I2C_TypeDef *) I2C0_BASE)
#define I2C1 ((I2C_TypeDef *) I2C1_BASE)
#define CMP0 ((CMP_TypeDef *) CMP0_BASE)
#define CMP1 ((CMP_TypeDef *) CMP1_BASE)
#define WDT ((WDT_TypeDef *) WDT_BASE)
#define RTC ((RTC_TypeDef *) RTC_BASE)
#define PWRCU ((PWRCU_TypeDef *) PWRCU_BASE)
#define GPTM0 ((TM_TypeDef *) GPTM0_BASE)
#define GPTM1 ((TM_TypeDef *) GPTM1_BASE)
#define BFTM0 ((BFTM_TypeDef *) BFTM0_BASE)
#define BFTM1 ((BFTM_TypeDef *) BFTM1_BASE)
#define FMC ((FMC_TypeDef *) FMC_BASE)
#define CKCU ((CKCU_TypeDef *) CKCU_BASE)
#define RSTCU ((RSTCU_TypeDef *) RSTCU_BASE)
#define CRC ((CRC_TypeDef *) CRC_BASE)
#define PDMA ((PDMA_TypeDef *) PDMA_BASE)
#define EBI ((EBI_TypeDef *) EBI_BASE)
#define USB ((USB_TypeDef *) USB_BASE)
#define GPIOA ((GPIO_TypeDef *) GPIO_A_BASE)
#define GPIO_A GPIOA
#define GPIOB ((GPIO_TypeDef *) GPIO_B_BASE)
#define GPIO_B GPIOB
#define GPIOC ((GPIO_TypeDef *) GPIO_C_BASE)
#define GPIO_C GPIOC
#define GPIOD ((GPIO_TypeDef *) GPIO_D_BASE)
#define GPIO_D GPIOD

View File

@ -0,0 +1,657 @@
#pragma once
#ifndef __IO
#define __IO volatile
#endif
// Constants
// /////////////////////////////////////////////////////////////////////////////
#define AFIO_DEFAULT 0
#define AFIO_GPIO 1
#define AFIO_ADC 2
#define AFIO_CMP 3
#define AFIO_TM 4
#define AFIO_SPI 5
#define AFIO_USART 6
#define AFIO_I2C 7
#define AFIO_SMC 8
#define AFIO_EBI 9
#define AFIO_I2S 10
#define AFIO_OTHER 15
// Flash Memory Controller
// /////////////////////////////////////////////////////////////////////////////
typedef struct {
__IO uint32_t TADR; //!< 0x000 Flash Target Address Register
__IO uint32_t WRDR; //!< 0x004 Flash Write Data Register
uint32_t RESERVED0[1]; //!< 0x008 Reserved
__IO uint32_t OCMR; //!< 0x00C Flash Operation Command Register
__IO uint32_t OPCR; //!< 0x010 Flash Operation Control Register
__IO uint32_t OIER; //!< 0x014 Flash Operation Interrupt Enable Register
__IO uint32_t OISR; //!< 0x018 Flash Operation Interrupt and Status Register
uint32_t RESERVED1[1]; //!< 0x01C Reserved
__IO uint32_t PPSR[4]; //!< 0x020 ~ 0x02C Flash Page Erase/Program Protection Status Register
__IO uint32_t CPSR; //!< 0x030 Flash Security Protection Status Register
uint32_t RESERVED2[51]; //!< 0x034 ~ 0x0FC Reserved
__IO uint32_t VMCR; //!< 0x100 Flash Vector Mapping Control Register
uint32_t RESERVED3[31]; //!< 0x104 ~ 0x17C Reserved
__IO uint32_t MDID; //!< 0x180 Manufacturer and Device ID Register
__IO uint32_t PNSR; //!< 0x184 Flash Page Number Status Register
__IO uint32_t PSSR; //!< 0x188 Flash Page Size Status Register
#if defined(HT32F165x)
uint32_t RESERVED4[29]; //!< 0x18C ~ 0x1FC Reserved
#else
__IO uint32_t DID; //!< 0x18C Device ID Register
uint32_t RESERVED4[28]; //!< 0x190 ~ 0x1FC Reserved
#endif
__IO uint32_t CFCR; //!< 0x200 Flash Cache and Pre-fetch Control Register
uint32_t RESERVED5[63]; //!< 0x204 ~ 0x2FC Reserved
__IO uint32_t SBVT[4]; //!< 0x300 ~ 0x30C SRAM Booting Vector (4x32Bit)
#if defined(HT32F165x)
#else
__IO uint32_t CID[4]; //!< 0x310 ~ 0x31C Custom ID Register
#endif
} FMC_TypeDef;
#define FMC_OCMR_CMD_MASK (0xF << 0)
#define FMC_OCMR_CMD_IDLE (0x0 << 0)
#define FMC_OCMR_CMD_WORD_PROGRAM (0x4 << 0)
#define FMC_OCMR_CMD_PAGE_ERASE (0x8 << 0)
#define FMC_OCMR_CMD_MASS_ERASE (0xA << 0)
#define FMC_OPCR_OPM_MASK (0xF << 1)
#define FMC_OPCR_OPM_IDLE (0x6 << 1)
#define FMC_OPCR_OPM_COMMIT (0xA << 1)
#define FMC_OPCR_OPM_FINISHED (0xE << 1)
#define FMC_CFCR_CE (1U << 12)
#define FMC_CFCR_WAIT_MASK (7U << 0)
#define FMC_CFCR_WAIT_0 (1U)
#define FMC_CFCR_WAIT_1 (2U)
// Power Control Unit
// /////////////////////////////////////////////////////////////////////////////
typedef struct {
uint32_t RESERVE0[64];
__IO uint32_t BAKSR; //!< 0x000 Status Register
__IO uint32_t BAKCR; //!< 0x004 Control Register
__IO uint32_t BAKTEST; //!< 0x008 Test Register
__IO uint32_t HSIRCR; //!< 0x00C HSI Ready Counter Control Register
__IO uint32_t LVDCSR; //!< 0x010 Low Voltage/Brown Out Detect Control and Status Register
uint32_t RESERVE1[59]; //!< 0x014 ~ 0x0FC Reserved
__IO uint32_t BAKREG[10]; //!< 0x100 ~ 0x124 Backup Register 0 ~ 9
} PWRCU_TypeDef;
// Clock Control Unit
// /////////////////////////////////////////////////////////////////////////////
typedef struct {
__IO uint32_t GCFGR; //!< 0x000 Global Clock Configuration Register
__IO uint32_t GCCR; //!< 0x004 Global Clock Control Register
__IO uint32_t GCSR; //!< 0x008 Global Clock Status Register
__IO uint32_t GCIR; //!< 0x00C Global Clock Interrupt Register
uint32_t RESERVED0[2]; //!< 0x010 ~ 0x014 Reserved
__IO uint32_t PLLCFGR; //!< 0x018 PLL Configuration Register
__IO uint32_t PLLCR; //!< 0x01C PLL Control Register
__IO uint32_t AHBCFGR; //!< 0x020 AHB Configuration Register
__IO uint32_t AHBCCR; //!< 0x024 AHB Clock Control Register
__IO uint32_t APBCFGR; //!< 0x028 APB Configuration Register
__IO uint32_t APBCCR0; //!< 0x02C APB Clock Control Register 0
__IO uint32_t APBCCR1; //!< 0x030 APB Clock Control Register 1
__IO uint32_t CKST; //!< 0x034 Clock source status Register
__IO uint32_t APBPCSR0; //!< 0x038 APB Peripheral Clock Selection Register 0
__IO uint32_t APBPCSR1; //!< 0x03C APB Peripheral Clock Selection Register 1
__IO uint32_t HSICR; //!< 0x040 HSI Control Register
__IO uint32_t HSIATCR; //!< 0x044 HSI Auto Trimming Counter Register
uint32_t RESERVED2[174]; //!< 0x048 ~ 0x2FC Reserved
__IO uint32_t LPCR; //!< 0x300 Low Power Control Register
__IO uint32_t MCUDBGCR; //!< 0x304 MCU Debug Control Register
} CKCU_TypeDef;
#define CKCU_GCFGR_LPMOD_MASK (7U << 29)
#define CKCU_GCFGR_USBPRE_MASK (3U << 22)
#define CKCU_GCFGR_PLLSRC (1U << 8)
#define CKCU_GCFGR_CKOUTSRC_MASK (7U << 0)
#define CKCU_GCFGR_CKOUTSRC_CK_REF (0U << 0)
#define CKCU_GCFGR_CKOUTSRC_CK_AHB (1U << 0)
#define CKCU_GCFGR_CKOUTSRC_CK_SYS (2U << 0)
#define CKCU_GCFGR_CKOUTSRC_CK_HSE (3U << 0)
#define CKCU_GCFGR_CKOUTSRC_CK_HSI (4U << 0)
#define CKCU_GCFGR_CKOUTSRC_CK_LSE (5U << 0)
#define CKCU_GCFGR_CKOUTSRC_CK_LSI (6U << 0)
#define CKCU_GCCR_PSRCEN (1U << 17)
#define CKCU_GCCR_CKMEN (1U << 16)
#define CKCU_GCCR_HSIEN (1U << 11)
#define CKCU_GCCR_HSEEN (1U << 10)
#define CKCU_GCCR_PLLEN (1U << 9)
#define CKCU_GCCR_SW_MASK (3U << 0)
#define CKCU_GCCR_SW_PLL (1U << 0)
#define CKCU_GCCR_SW_HSE (2U << 0)
#define CKCU_GCCR_SW_HSI (3U << 0)
#define CKCU_GCSR_LSIRDY (1U << 5)
#define CKCU_GCSR_LSERDY (1U << 4)
#define CKCU_GCSR_HSIRDY (1U << 3)
#define CKCU_GCSR_HSERDY (1U << 2)
#define CKCU_GCSR_PLLRDY (1U << 1)
#define CKCU_PLLCFGR_PFBD_MASK (0x3fU << 23)
#define CKCU_PLLCFGR_POTD_MASK (3U << 21)
#define CKCU_PLLCR_PLLBPS (1U << 31)
#define CKCU_AHBCFGR_AHBPRE_MASK (3U << 0)
#define CKCU_AHBCCR_PAEN (1U << 16)
#define CKCU_AHBCCR_CRCEN (1U << 13)
#define CKCU_AHBCCR_EBIEN (1U << 12)
#define CKCU_AHBCCR_CKREFEN (1U << 11)
#define CKCU_AHBCCR_USBEN (1U << 10)
#define CKCU_APBCFGR_ADCDIV_MASK (7U << 16)
#define CKCU_APBCCR0_I2SEN (1U << 25)
#define CKCU_APBCCR0_SCIEN (1U << 24)
#define CKCU_APBCCR0_EXTIEN (1U << 15)
#define CKCU_APBCCR0_AFIOEN (1U << 14)
#define CKCU_APBCCR0_UR1EN (1U << 11)
#define CKCU_APBCCR0_UR0EN (1U << 10)
#define CKCU_APBCCR0_USR1EN (1U << 9)
#define CKCU_APBCCR0_USR0EN (1U << 8)
#define CKCU_APBCCR0_SPI1EN (1U << 5)
#define CKCU_APBCCR0_SPI0EN (1U << 4)
#define CKCU_APBCCR0_I2C1EN (1U << 1)
#define CKCU_APBCCR0_I2C0EN (1U << 0)
#define CKCU_APBCCR1_ADCEN (1U << 24)
#define CKCU_APBCCR1_OPA1EN (1U << 23)
#define CKCU_APBCCR1_OPA0EN (1U << 22)
#define CKCU_APBCCR1_BFTM1EN (1U << 17)
#define CKCU_APBCCR1_BFTM0EN (1U << 16)
#define CKCU_APBCCR1_GPTM1EN (1U << 9)
#define CKCU_APBCCR1_GPTM0EN (1U << 8)
#define CKCU_APBCCR1_BKPREN (1U << 6)
#define CKCU_APBCCR1_WDTREN (1U << 4)
#define CKCU_APBCCR1_MCTM1EN (1U << 1)
#define CKCU_APBCCR1_MCTM0EN (1U << 0)
#define CKCU_CKST_CKSWST_MASK (3U << 30)
#define CKCU_CKST_HSIST_MASK (7U << 24)
#define CKCU_CKST_HSEST_MASK (3U << 16)
#define CKCU_CKST_PLLST_MASK (0xfU << 8)
#define CKCU_LPCR_USBSLEEP (1U << 8)
#define CKCU_LPCR_BKISO (1U << 0)
// Reset Control Unit
// /////////////////////////////////////////////////////////////////////////////
typedef struct {
__IO uint32_t GRSR; //!< 0x000 Global Reset Status Register
__IO uint32_t AHBPRSTR; //!< 0x004 AHB Peripheral Reset Register
__IO uint32_t APBPRSTR0; //!< 0x008 APB Peripheral Reset Register 0
__IO uint32_t APBPRSTR1; //!< 0x00C APB Peripheral Reset Register 1
} RSTCU_TypeDef;
#define RSTCU_GRSR_PORSTF (1U << 3)
#define RSTCU_GRSR_WDTRSTF (1U << 2)
#define RSTCU_GRSR_EXTRSTF (1U << 1)
#define RSTCU_GRSR_SYSRSTF (1U << 0)
#define RSTCU_AHBPRSTR_PxRST(n) ((1U << 8) << (n))
#define RSTCU_AHBPRSTR_CRCRST (1U << 7)
#define RSTCU_AHBPRSTR_EBIRST (1U << 6)
#define RSTCU_AHBPRSTR_USBRST (1U << 5)
#define RSTCU_AHBPRSTR_DMARST (1U << 0)
#define RSTCU_APBPRSTR0_I2SRST (1U << 25)
#define RSTCU_APBPRSTR0_SCIRST (1U << 24)
#define RSTCU_APBPRSTR0_EXTIRST (1U << 15)
#define RSTCU_APBPRSTR0_AFIORST (1U << 14)
#define RSTCU_APBPRSTR0_UR1RST (1U << 11)
#define RSTCU_APBPRSTR0_UR0RST (1U << 10)
#define RSTCU_APBPRSTR0_USR1RST (1U << 9)
#define RSTCU_APBPRSTR0_USR0RST (1U << 8)
#define RSTCU_APBPRSTR0_SPI1RST (1U << 5)
#define RSTCU_APBPRSTR0_SPI0RST (1U << 4)
#define RSTCU_APBPRSTR0_I2C1RST (1U << 1)
#define RSTCU_APBPRSTR0_I2C0RST (1U << 0)
#define RSTCU_APBPRSTR1_ADCRST (1U << 24)
#define RSTCU_APBPRSTR1_OPA1RST (1U << 23)
#define RSTCU_APBPRSTR1_OPA0RST (1U << 22)
#define RSTCU_APBPRSTR1_BFTM1RST (1U << 17)
#define RSTCU_APBPRSTR1_BFTM0RST (1U << 16)
#define RSTCU_APBPRSTR1_GPTM1RST (1U << 9)
#define RSTCU_APBPRSTR1_GPTM0RST (1U << 8)
#define RSTCU_APBPRSTR1_WDTRST (1U << 4)
#define RSTCU_APBPRSTR1_MCTM1RST (1U << 1)
#define RSTCU_APBPRSTR1_MCTM0RST (1U << 0)
// General Purpose I/O
// /////////////////////////////////////////////////////////////////////////////
typedef struct {
__IO uint32_t DIRCR; //!< 0x000 Data Direction Control Register
__IO uint32_t INER; //!< 0x004 Input function enable register
__IO uint32_t PUR; //!< 0x008 Pull-Up Selection Register
__IO uint32_t PDR; //!< 0x00C Pull-Down Selection Register
__IO uint32_t ODR; //!< 0x010 Open Drain Selection Register
__IO uint32_t DRVR; //!< 0x014 Drive Current Selection Register
__IO uint32_t LOCKR; //!< 0x018 Lock Register
__IO uint32_t DINR; //!< 0x01c Data Input Register
__IO uint32_t DOUTR; //!< 0x020 Data Output Register
__IO uint32_t SRR; //!< 0x024 Output Set and Reset Control Register
__IO uint32_t RR; //!< 0x028 Output Reset Control Register
} GPIO_TypeDef;
// Alternate Function Input/Output
// /////////////////////////////////////////////////////////////////////////////
typedef struct {
__IO uint32_t ESSR[2]; //!< 0x000 ~ 0x004 EXTI Source Selection Register 0 ~ 1
uint32_t RESERVE0[6]; //!< 0x008 ~ 0x01C Reserved
union {
struct {
__IO uint32_t GPACFGR[2]; //!< 0x020 ~ 0x024 GPIO Port A Configuration Register 0 ~ 1
__IO uint32_t GPBCFGR[2]; //!< 0x028 ~ 0x02C GPIO Port B Configuration Register 0 ~ 1
__IO uint32_t GPCCFGR[2]; //!< 0x030 ~ 0x034 GPIO Port C Configuration Register 0 ~ 1
__IO uint32_t GPDCFGR[2]; //!< 0x038 ~ 0x03C GPIO Port D Configuration Register 0 ~ 1
};
// alternate mapping
struct {
__IO uint32_t GPxCFGR[0][2]; //!< 0x020 ~ 0x03C GPIO Port x Configuration Register 0 ~ 1
};
};
} AFIO_TypeDef;
// Nested Vectored Interrupt Controller
// /////////////////////////////////////////////////////////////////////////////
// Implemented in Cortex-M3 Headers
// External Interrupt/Event Controller
// /////////////////////////////////////////////////////////////////////////////
typedef struct {
__IO uint32_t CFGR0; //!< 0x000 EXTI Interrupt 0 Configuration Register
__IO uint32_t CFGR1; //!< 0x004 EXTI Interrupt 1 Configuration Register
__IO uint32_t CFGR2; //!< 0x008 EXTI Interrupt 2 Configuration Register
__IO uint32_t CFGR3; //!< 0x00C EXTI Interrupt 3 Configuration Register
__IO uint32_t CFGR4; //!< 0x010 EXTI Interrupt 4 Configuration Register
__IO uint32_t CFGR5; //!< 0x014 EXTI Interrupt 5 Configuration Register
__IO uint32_t CFGR6; //!< 0x018 EXTI Interrupt 6 Configuration Register
__IO uint32_t CFGR7; //!< 0x01C EXTI Interrupt 7 Configuration Register
__IO uint32_t CFGR8; //!< 0x020 EXTI Interrupt 8 Configuration Register
__IO uint32_t CFGR9; //!< 0x024 EXTI Interrupt 9 Configuration Register
__IO uint32_t CFGR10; //!< 0x028 EXTI Interrupt 10 Configuration Register
__IO uint32_t CFGR11; //!< 0x02C EXTI Interrupt 11 Configuration Register
__IO uint32_t CFGR12; //!< 0x030 EXTI Interrupt 12 Configuration Register
__IO uint32_t CFGR13; //!< 0x034 EXTI Interrupt 13 Configuration Register
__IO uint32_t CFGR14; //!< 0x038 EXTI Interrupt 14 Configuration Register
__IO uint32_t CFGR15; //!< 0x03C EXTI Interrupt 15 Configuration Register
__IO uint32_t CR; //!< 0x040 EXTI Interrupt Control Register
__IO uint32_t EDGEFLGR; //!< 0x044 EXTI Interrupt Edge Flag Register
__IO uint32_t EDGESR; //!< 0x048 EXTI Interrupt Edge Status Register
__IO uint32_t SSCR; //!< 0x04C EXTI Interrupt Software Set Command Register
__IO uint32_t WAKUPCR; //!< 0x050 EXTI Interrupt Wakeup Control Register
__IO uint32_t WAKUPPOLR; //!< 0x054 EXTI Interrupt Wakeup Polarity Register
__IO uint32_t WAKUPFLG; //!< 0x058 EXTI Interrupt Wakeup Flag Register
} EXTI_TypeDef;
// Analog To Digital Converter
// /////////////////////////////////////////////////////////////////////////////
// Operational Amplifier / Comparator
// /////////////////////////////////////////////////////////////////////////////
typedef struct {
__IO uint32_t CR; //!< 0x000 Comparator Control Register
__IO uint32_t VALR; //!< 0x004 Comparator Voltage Reference Register
__IO uint32_t IER; //!< 0x008 Comparator Interrupt Enable Register
__IO uint32_t TFR; //!< 0x00C Comparator Transition Flag Register
} CMP_TypeDef;
// Basic Function Timers
// /////////////////////////////////////////////////////////////////////////////
typedef struct {
__IO uint32_t CR; //!< 0x000 Control Register
__IO uint32_t SR; //!< 0x004 Status Register
__IO uint32_t CNTR; //!< 0x008 Counter Value Register
__IO uint32_t CMP; //!< 0x00C Compare Value Register
} BFTM_TypeDef;
#define BFTM_CR_CEN (1U << 2)
#define BFTM_CR_OSM (1U << 1)
#define BFTM_CR_MIEN (1U << 0)
#define BFTM_SR_MIF (1U << 0)
// General Purpose Timers
// Motor Control Timers
// /////////////////////////////////////////////////////////////////////////////
typedef struct {
__IO uint32_t CNTCFR; //!< 0x000 Timer Counter Configuaration Register
__IO uint32_t MDCFR; //!< 0x004 Timer Mode Configuration Register
__IO uint32_t TRCFR; //!< 0x008 Timer Trigger Configuration Register
uint32_t RESERVED0[1]; //!< 0x00C Reserved
__IO uint32_t CTR; //!< 0x010 Timer Counter Register
uint32_t RESERVED1[3]; //!< 0x014 ~ 0x01C Reserved
__IO uint32_t CHnICFR[4]; //!< 0x020 ~ 0x02C Channel n Input Configuration Register
uint32_t RESERVED2[4]; //!< 0x030 ~ 0x03C Reserved
__IO uint32_t CHnOCFR[4]; //!< 0x040 ~ 0x04C Channel n Output Configuration Register
__IO uint32_t CHCTR; //!< 0x050 Channel Control Register
__IO uint32_t CHPOLR; //!< 0x054 Channel Polarity Control Register
uint32_t RESERVED3[5]; //!< 0x058 ~ 0x068 Reserved
// note: only available as MCTM
__IO uint32_t CHBRKCFR; //!< 0x06C Channel Break Configuration Register
__IO uint32_t CHBRKCTR; //!< 0x070 Channel Break Control Register
// end note
__IO uint32_t DICTR; //!< 0x074 Timer PDMA/Interrupt Control Register
__IO uint32_t EVGR; //!< 0x078 Timer Event Generator Register
__IO uint32_t INTSR; //!< 0x07C Timer Interrupt Status Register
__IO uint32_t CNTR; //!< 0x080 Timer Counter Register
__IO uint32_t PSCR; //!< 0x084 Timer Prescaler Register
__IO uint32_t CRR; //!< 0x088 Timer Counter Reload Register
// note: only available as MCTM
__IO uint32_t REPR; //!< 0x08C Timer Repetition Register
// end note
__IO uint32_t CHnCCR[4]; //!< 0x090 ~ 0x09C Channel n Capture/Compare Register
__IO uint32_t CHnACR[4]; //!< 0x0A0 ~ 0x0AC Channel n Asymmentric Compare Register
} TM_TypeDef;
#define TM_CNTCFR_CMSEL_MASK (3U << 16)
#define TM_CNTCFR_CMSEL_MODE_3 (3U << 16)
#define TM_CNTCFR_CMSEL_MODE_2 (2U << 16)
#define TM_CNTCFR_CMSEL_MODE_1 (1U << 16)
#define TM_CNTCFR_CMSEL_MODE_0 (0U << 16)
#define TM_CTR_CHCCDS (1U << 16)
#define TM_CTR_COMUS (1U << 9)
#define TM_CTR_COMPRE (1U << 8)
#define TM_CTR_CRBE (1U << 1)
#define TM_CTR_TME (1U << 0)
#define TM_CHnOCFR_CHnPRE (1U << 4)
#define TM_CHnOCFR_REFnCE (1U << 3)
#define TM_CHnOCFR_CHnOM(n) ((((n)>>0)&7)|((((n)>>3)&1)<<8))
#define TM_CHBRKCTR_CHMOE (1U << 4)
// Real Time Clock
// /////////////////////////////////////////////////////////////////////////////
// Watchdog Timer
// /////////////////////////////////////////////////////////////////////////////
// I2C
// /////////////////////////////////////////////////////////////////////////////
typedef struct {
__IO uint32_t CR; //!< 0x000 Control Register
__IO uint32_t IER; //!< 0x004 Interrupt Enable Register
__IO uint32_t ADDR; //!< 0x008 Address Register
__IO uint32_t SR; //!< 0x00C Status Register
__IO uint32_t SHPGR; //!< 0x010 SCL High Period Generation Register
__IO uint32_t SLPGR; //!< 0x014 SCL Low Period Generation Register
__IO uint32_t DR; //!< 0x018 Data Register
__IO uint32_t TAR; //!< 0x01C Target Register
__IO uint32_t ADDMR; //!< 0x020 Address Mask Register
__IO uint32_t ADDSR; //!< 0x024 Address Snoop Register
__IO uint32_t TOUT; //!< 0x028 Timeout Register
} I2C_TypeDef;
#define I2C_CR_SEQ_FILTER_MASK (3U << 14)
#define I2C_CR_SEQ_FILTER_2_PCLK (2U << 14)
#define I2C_CR_SEQ_FILTER_1_PCLK (1U << 14)
#define I2C_CR_SEQ_FILTER_DISABLE (0U << 14)
#define I2C_CR_COMB_FILTER_En (1U << 13)
#define I2C_CR_ENTOUT (1U << 12)
#define I2C_CR_DMANACK (1U << 10)
#define I2C_CR_RXDMAE (1U << 9)
#define I2C_CR_TXDMAE (1U << 8)
#define I2C_CR_ADRM (1U << 7)
#define I2C_CR_I2CEN (1U << 3)
#define I2C_CR_GCEN (1U << 2)
#define I2C_CR_STOP (1U << 1)
#define I2C_CR_AA (1U << 0)
#define I2C_IER_RXBFIE (1U << 18)
#define I2C_IER_TXDEIE (1U << 17)
#define I2C_IER_RXDNEIE (1U << 16)
#define I2C_IER_TOUTIE (1U << 11)
#define I2C_IER_BUSERRIE (1U << 10)
#define I2C_IER_RXNACKIE (1U << 9)
#define I2C_IER_ARBLOSIE (1U << 8)
#define I2C_IER_GCSIE (1U << 3)
#define I2C_IER_ADRSIE (1U << 2)
#define I2C_IER_STOIE (1U << 1)
#define I2C_IER_STAIE (1U << 0)
#define I2C_SR_TXNRX (1U << 21)
#define I2C_SR_MASTER (1U << 20)
#define I2C_SR_BUSBUSY (1U << 19)
#define I2C_SR_RXBF (1U << 18)
#define I2C_SR_TXDE (1U << 17)
#define I2C_SR_RXDNE (1U << 16)
#define I2C_SR_TOUTF (1U << 11)
#define I2C_SR_BUSERR (1U << 10)
#define I2C_SR_RXNACK (1U << 9)
#define I2C_SR_ARBLOS (1U << 8)
#define I2C_SR_GCS (1U << 3)
#define I2C_SR_ADRS (1U << 2)
#define I2C_SR_STO (1U << 1)
#define I2C_SR_STA (1U << 0)
#define I2C_TAR_RWD (1U << 10)
// SPI
// /////////////////////////////////////////////////////////////////////////////
typedef struct {
__IO uint32_t CR0; //!< 0x000 Control Register 0
__IO uint32_t CR1; //!< 0x004 Control Register 1
__IO uint32_t IER; //!< 0x008 Interrupt Enable Register
__IO uint32_t CPR; //!< 0x00C Clock Prescaler Register
__IO uint32_t DR; //!< 0x010 Data Register
__IO uint32_t SR; //!< 0x014 Status Register
__IO uint32_t FCR; //!< 0x018 FIFO Control Register
__IO uint32_t FSR; //!< 0x01C FIFO Status Register
__IO uint32_t FTOCR; //!< 0x020 FIFO Time Out Counter Register
} SPI_TypeDef;
#define SPI_CR0_GUADTEN (1U << 7)
#define SPI_CR0_DUALEN (1U << 6)
#define SPI_CR0_SSELC (1U << 4)
#define SPI_CR0_SELOEN (1U << 3)
#define SPI_CR0_SPIEN (1U << 0)
#define SPI_CR1_MODE (1U << 14)
#define SPI_CR1_SELM (1U << 13)
#define SPI_CR1_FIRSTBIT (1U << 12)
#define SPI_CR1_SELAP (1U << 11)
#define SPI_CR1_FORMAT_MASK (7U << 8)
#define SPI_CR1_FORMAT_MODE0 (0x1U << 8)
#define SPI_CR1_FORMAT_MODE1 (0x2U << 8)
#define SPI_CR1_FORMAT_MODE2 (0x6U << 8)
#define SPI_CR1_FORMAT_MODE3 (0x5U << 8)
#define SPI_IER_RXBNEIEN (1U << 2)
#define SPI_IER_TXBEIEN (1U << 0)
#define SPI_SR_RXBNE (1U << 2)
#define SPI_SR_TXE (1U << 1)
#define SPI_SR_TXBE (1U << 0)
#define SPI_FCR_FIFOEN (1U << 10)
#define SPI_FSR_TXFS_MASK (0xfU << 0)
#define SPI_FSR_RXFS_MASK (0xfU << 4)
// USART
// UART
// /////////////////////////////////////////////////////////////////////////////
typedef struct {
__IO uint32_t DR; //!< 0x000 Data Register
__IO uint32_t CR; //!< 0x004 Control Register
// Only USART
__IO uint32_t FCR; //!< 0x008 FIFO Control Register
__IO uint32_t IER; //!< 0x00C Interrupt Enable Register
__IO uint32_t SIFR; //!< 0x010 Status & Interrupt Flag Register
__IO uint32_t TPR; //!< 0x014 Timing Parameter Register
__IO uint32_t IrDACR; //!< 0x018 IrDA Control Register
__IO uint32_t RS485CR; //!< 0x01C RS485 Control Register
__IO uint32_t SYNCR; //!< 0x020 Synchronous Control Register
// end note
__IO uint32_t DLR; //!< 0x024 Divider Latch Register
__IO uint32_t TSTR; //!< 0x028 Debug/Test Register
} USART_TypeDef;
// USART CR
#define UART_CR_MODE_MASK (0b11 << 0)
#define UART_CR_MODE_NORMAL (0 << 0)
#define UART_CR_TRSM (1 << 2)
#define UART_CR_HFCEN (1 << 3)
#define UART_CR_URTXEN (1 << 4)
#define UART_CR_URRXEN (1 << 5)
#define UART_CR_TXDMAEN (1 << 6)
#define UART_CR_RXDMAEN (1 << 7)
#define UART_CR_WLS_MASK (0b11 << 8)
#define UART_CR_WLS_7B (0b00 << 8)
#define UART_CR_WLS_8B (0b01 << 8)
#define UART_CR_WLS_9B (0b10 << 8)
#define UART_CR_NSB (1 << 10)
#define UART_CR_PBE (1 << 11)
#define UART_CR_EPE (1 << 12)
#define UART_CR_SPE (1 << 13)
#define UART_CR_BCB (1 << 14)
#define UART_CR_RTS (1 << 15)
// USART FCR (FIFO CR)
#define USART_FCR_TXR (1 << 0)
#define USART_FCR_RXR (1 << 1)
#define USART_FCR_TXTL_MASK (0b11 << 4)
#define USART_FCR_RXTL_MASK (0b11 << 6)
#define USART_FCR_TXFS_MASK (0xF << 16)
#define USART_FCR_RXFS_MASK (0xF << 24)
// USART SIFR Status and Interrupt Flag Register
#define USART_SIFR_RXDNE (1 << 0)
#define USART_SIFR_OEI (1 << 1)
#define USART_SIFR_PEI (1 << 2)
#define USART_SIFR_FEI (1 << 3)
#define USART_SIFR_BII (1 << 4)
#define USART_SIFR_RXDR (1 << 5)
#define USART_SIFR_RXTOF (1 << 6)
#define USART_SIFR_TXDE (1 << 7)
#define USART_SIFR_TXC (1 << 8)
#define USART_SIFR_RSADDE (1 << 9)
#define USART_SIFR_CTSC (1 << 10)
#define USART_SIFR_CTSS (1 << 11)
// USART IER
#define USART_IER_RXDRIE (1 << 0)
#define USART_IER_TXDEIE (1 << 1)
#define USART_IER_TXCIE (1 << 2)
#define USART_IER_OEIE (1 << 3)
#define USART_IER_PEIE (1 << 4)
#define USART_IER_FEIE (1 << 5)
#define USART_IER_BIE (1 << 6)
#define USART_IER_RSADDIE (1 << 7)
#define USART_IER_RXTOIE (1 << 8)
#define USART_IER_CTSIE (1 << 9)
// Smart Card Interface
// /////////////////////////////////////////////////////////////////////////////
// USB
// /////////////////////////////////////////////////////////////////////////////
typedef struct {
__IO uint32_t CSR; //!< 0x000 USB Control and Status Register
__IO uint32_t IER; //!< 0x004 USB Interrupt Enable Register
__IO uint32_t ISR; //!< 0x008 USB Interrupt Status Register
__IO uint32_t FCR; //!< 0x00C USB Frame Count Register
__IO uint32_t DEVAR; //!< 0x010 USB Device Address Register
struct {
__IO uint32_t CSR; //!< 0x014 USB Endpoint n Control and Status Register
__IO uint32_t IER; //!< 0x018 USB Endpoint n Interrupt Enable Register
__IO uint32_t ISR; //!< 0x01C USB Endpoint n Interrupt Status Register
__IO uint32_t TCR; //!< 0x020 USB Endpoint n Transfer Count Register
__IO uint32_t CFGR; //!< 0x024 USB Endpoint n Configuration Register
} EP[8];
} USB_TypeDef;
// USBCSR
#define USBCSR_FRES (0x002) // Force USB Reset Control
#define USBCSR_PDWN (0x004) // Power Down Mode Control
#define USBCSR_LPMODE (0x008) // Low-Power Mode Control
#define USBCSR_GENRSM (0x020) // Resume Request Generation Control
#define USBCSR_RXDP (0x040) // Received DP Line Status
#define USBCSR_RXDM (0x080) // Received DM Line Status
#define USBCSR_ADRSET (0x100) // Device Address Setting Control
#define USBCSR_SRAMRSTC (0x200) // USB SRAM Reset Condition
#define USBCSR_DPPUEN (0x400) // DP Pull Up Enable
#define USBCSR_DPWKEN (0x800) // DP Wake Up Enable
// USBIER
#define USBIER_UGIE (0x0001) // USB global Interrupt Enable
#define USBIER_SOFIE (0x0002) // Start Of Frame Interrupt Enable
#define USBIER_URSTIE (0x0004) // USB Reset Interrupt Enable
#define USBIER_RSMIE (0x0008) // Resume Interrupt Enable
#define USBIER_SUSPIE (0x0010) // Suspend Interrupt Enable
#define USBIER_ESOFIE (0x0020) // Expected Start Of Frame Enable
#define USBIER_EP0IE (0x0100) // Endpoint 0 Interrupt Enable
#define USBIER_EP1IE (0x0200) // Endpoint 1 Interrupt Enable
#define USBIER_EP2IE (0x0400) // Endpoint 2 Interrupt Enable
#define USBIER_EP3IE (0x0800) // Endpoint 3 Interrupt Enable
#define USBIER_EP4IE (0x1000) // Endpoint 4 Interrupt Enable
#define USBIER_EP5IE (0x2000) // Endpoint 5 Interrupt Enable
#define USBIER_EP6IE (0x4000) // Endpoint 6 Interrupt Enable
#define USBIER_EP7IE (0x8000) // Endpoint 7 Interrupt Enable
// USBISR
#define USBISR_SOFIF (0x0002) // Start Of Frame Interrupt Flag
#define USBISR_URSTIF (0x0004) // USB Reset Interrupt Flag
#define USBISR_RSMIF (0x0008) // Resume Interrupt Flag
#define USBISR_SUSPIF (0x0010) // Suspend Interrupt Flag
#define USBISR_ESOFIF (0x0020) // Expected Start Of Frame Interrupt
#define USBISR_EP0IF (1U << 8) // Endpoint 0 Interrupt Flag
#define USBISR_EP1IF (1U << 9) // Endpoint 1 Interrupt Flag
#define USBISR_EP2IF (1U << 10) // Endpoint 2 Interrupt Flag
#define USBISR_EP3IF (1U << 11) // Endpoint 3 Interrupt Flag
#define USBISR_EP4IF (1U << 12) // Endpoint 4 Interrupt Flag
#define USBISR_EP5IF (1U << 13) // Endpoint 5 Interrupt Flag
#define USBISR_EP6IF (1U << 14) // Endpoint 6 Interrupt Flag
#define USBISR_EP7IF (1U << 15) // Endpoint 7 Interrupt Flag
#define USBISR_EPnIF (0xFF00) // Endpoint Interrupt Mask
// USBFCR
#define USBFCR_FRNUM (0x7FF) // Frame Number
#define USBFCR_SOFLCK (1U << 16) // Start-of-Frame Lock Flag
#define USBFCR_LSOF (0x3U << 17) // Lost Start-of-Frame Number
// USBEPnCSR
#define USBEPnCSR_DTGTX (0x01) // Data Toggle Status, for IN transfer
#define USBEPnCSR_NAKTX (0x02) // NAK Status, for IN transfer
#define USBEPnCSR_STLTX (0x04) // STALL Status, for IN transfer
#define USBEPnCSR_DTGRX (0x08) // Data Toggle Status, for OUT transfer
#define USBEPnCSR_NAKRX (0x10) // NAK Status, for OUT transfer
#define USBEPnCSR_STLRX (0x20) // STALL Status, for OUT transfer
// USBEPnIER
#define USBEPnIER_OTRXIE (0x001) // OUT Token Received Interrupt Enable
#define USBEPnIER_ODRXIE (0x002) // OUT Data Received Interrupt Enable
#define USBEPnIER_ODOVIE (0x004) // OUT Data Buffer Overrun Interrupt Enable
#define USBEPnIER_ITRXIE (0x008) // IN Token Received Interrupt Enable
#define USBEPnIER_IDTXIE (0x010) // IN Data Transmitted Interrupt Enable
#define USBEPnIER_NAKIE (0x020) // NAK Transmitted Interrupt Enable
#define USBEPnIER_STLIE (0x040) // STALL Transmitted Interrupt Enable
#define USBEPnIER_UERIE (0x080) // USB Error Interrupt Enable
#define USBEPnIER_STRXIE (0x100) // SETUP Token Received Interrupt Enable
#define USBEPnIER_SDRXIE (0x200) // SETUP Data Received Interrupt Enable
#define USBEPnIER_SDERIE (0x400) // SETUP Data Error Interrupt Enable
#define USBEPnIER_ZLRXIE (0x800) // Zero Length Data Received Interrupt Enable
// USBEPnISR
#define USBEPnISR_OTRXIF (0x001) // OUT Token Received Interrupt Flag
#define USBEPnISR_ODRXIF (0x002) // OUT Data Received Interrupt Flag
#define USBEPnISR_ODOVIF (0x004) // OUT Data Buffer Overrun Interrupt Flag
#define USBEPnISR_ITRXIF (0x008) // IN Token Received Interrupt Flag
#define USBEPnISR_IDTXIF (0x010) // IN Data Transmitted Interrupt Flag
#define USBEPnISR_NAKIF (0x020) // NAK Transmitted Interrupt Flag
#define USBEPnISR_STLIF (0x040) // STALL Transmitted Interrupt Flag
#define USBEPnISR_UERIF (0x080) // USB Error Interrupt Flag
#define USBEPnISR_STRXIF (0x100) // SETUP Token Received Interrupt Flag
#define USBEPnISR_SDRXIF (0x200) // SETUP Data Received Interrupt Flag
#define USBEPnISR_SDERIF (0x400) // SETUP Data Error Interrupt Flag
#define USBEPnISR_ZLRXIF (0x800) // Zero Length Data Received Interrupt Flag
// USBEPnTCR
#define USBEPnTCR_TCNT (0x1FF) // Transfer Byte Count
// USBEPnCFGR
#define USBEPnCFGR_EPEN (1U << 31) // Endpoint Enable
#define USBEPnCFGR_EPTYPE (1U << 29) // Transfer Type
#define USBEPnCFGR_EPDIR (1U << 28) // Transfer Direction
#define USBEPnCFGR_EPADR (0xFU << 24) // Endpoint Address
#define USBEPnCFGR_EPLEN (0x7FU << 10) // Buffer Length
#define USBEPnCFGR_EPBUFA (0x3FF) // Endpoint Buffer Address
// Peripheral Direct Memory Access
// /////////////////////////////////////////////////////////////////////////////
// Extend Bus Interface
// /////////////////////////////////////////////////////////////////////////////
// Inter-IC Sound
// /////////////////////////////////////////////////////////////////////////////
// CRC
// /////////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,93 @@
/*
* Copyright (C) Yaotian Feng, http://github.com/Codetector1374
* codetector@codetector.cn
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
* HT32F1654 memory setup
*/
MEMORY {
flash0 : org = 0x00000000, len = 32k
flash1 : org = 0x00000000, len = 0
flash2 : org = 0x00000000, len = 0
flash3 : org = 0x00000000, len = 0
flash4 : org = 0x00000000, len = 0
flash5 : org = 0x00000000, len = 0
flash6 : org = 0x00000000, len = 0
flash7 : org = 0x00000000, len = 0
ram0 : org = 0x20000000, len = 8k
ram1 : org = 0x00000000, len = 0
ram2 : org = 0x00000000, len = 0
ram3 : org = 0x00000000, len = 0
ram4 : org = 0x00000000, len = 0
ram5 : org = 0x00000000, len = 0
ram6 : org = 0x00000000, len = 0
ram7 : 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

View File

@ -0,0 +1,93 @@
/*
* Copyright (C) Yaotian Feng, http://github.com/Codetector1374
* codetector@codetector.cn
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
* HT32F1654 memory setup
*/
MEMORY {
flash0 : org = 0x00000000, len = 63k
flash1 : org = 0x00000000, len = 0
flash2 : org = 0x00000000, len = 0
flash3 : org = 0x00000000, len = 0
flash4 : org = 0x00000000, len = 0
flash5 : org = 0x00000000, len = 0
flash6 : org = 0x00000000, len = 0
flash7 : org = 0x00000000, len = 0
ram0 : org = 0x20000000, len = 16k
ram1 : org = 0x00000000, len = 0
ram2 : org = 0x00000000, len = 0
ram3 : org = 0x00000000, len = 0
ram4 : org = 0x00000000, len = 0
ram5 : org = 0x00000000, len = 0
ram6 : org = 0x00000000, len = 0
ram7 : 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

View File

@ -0,0 +1,93 @@
/*
* Copyright (C) Yaotian Feng, http://github.com/Codetector1374
* codetector@codetector.cn
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
* HT32F5234x memory setup
*/
MEMORY {
flash0 : org = 0x00000000, len = 64k
flash1 : org = 0x00000000, len = 0
flash2 : org = 0x00000000, len = 0
flash3 : org = 0x00000000, len = 0
flash4 : org = 0x00000000, len = 0
flash5 : org = 0x00000000, len = 0
flash6 : org = 0x00000000, len = 0
flash7 : org = 0x00000000, len = 0
ram0 : org = 0x20000000, len = 8k
ram1 : org = 0x00000000, len = 0
ram2 : org = 0x00000000, len = 0
ram3 : org = 0x00000000, len = 0
ram4 : org = 0x00000000, len = 0
ram5 : org = 0x00000000, len = 0
ram6 : org = 0x00000000, len = 0
ram7 : 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

View File

@ -0,0 +1,93 @@
/*
* Copyright (C) Yaotian Feng, http://github.com/Codetector1374
* codetector@codetector.cn
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
* HT32F5235x memory setup
*/
MEMORY {
flash0 : org = 0x00000000, len = 128k
flash1 : org = 0x00000000, len = 0
flash2 : org = 0x00000000, len = 0
flash3 : org = 0x00000000, len = 0
flash4 : org = 0x00000000, len = 0
flash5 : org = 0x00000000, len = 0
flash6 : org = 0x00000000, len = 0
flash7 : org = 0x00000000, len = 0
ram0 : org = 0x20000000, len = 16k
ram1 : org = 0x00000000, len = 0
ram2 : org = 0x00000000, len = 0
ram3 : org = 0x00000000, len = 0
ram4 : org = 0x00000000, len = 0
ram5 : org = 0x00000000, len = 0
ram6 : org = 0x00000000, len = 0
ram7 : 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

View File

@ -0,0 +1,22 @@
# ChibiOS/RT - Copyright (c) 2020 Yaotian Feng
# startup_ht32f165x.mk - Makefile for Holtek HT32F165x series uC.
# List of the ChibiOS generic HT32F165x 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/HT32F165x \
$(CHIBIOS)/os/common/ext/ARM/CMSIS/Core/Include \
$(CHIBIOS_CONTRIB)/os/common/ext/CMSIS/HT32/HT32F165x
STARTUPLD = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/ld
STARTUPLD_CONTRIB = $(CHIBIOS_CONTRIB)/os/common/startup/ARMCMx/compilers/GCC/ld
ALLXASMSRC += $(STARTUPASM)
ALLCSRC += $(STARTUPSRC)
ALLINC += $(STARTUPINC)

View File

@ -0,0 +1,22 @@
# ChibiOS/RT - Copyright (c) 2020 Yaotian Feng
# startup_ht32f165x.mk - Makefile for Holtek HT32F523x2 series uC.
# List of the ChibiOS generic HT32F523x2 startup and CMSIS files.
STARTUPSRC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt1.c
STARTUPASM = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt0_v6m.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/HT32F523xx \
$(CHIBIOS)/os/common/ext/ARM/CMSIS/Core/Include \
$(CHIBIOS_CONTRIB)/os/common/ext/CMSIS/HT32/HT32F523xx
STARTUPLD = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/ld
STARTUPLD_CONTRIB = $(CHIBIOS_CONTRIB)/os/common/startup/ARMCMx/compilers/GCC/ld
ALLXASMSRC += $(STARTUPASM)
ALLCSRC += $(STARTUPSRC)
ALLINC += $(STARTUPINC)

View File

@ -0,0 +1,89 @@
/*
ChibiOS/RT - Copyright (C) 2006-2014 Giovanni Di Sirio.
(C) 2015 RedoX https://github.com/RedoXyde
(C) 2017 Charlie Waters <cawiii@me.com>
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 <http://www.gnu.org/licenses/>.
*/
/**
* @file GCC/ARMCMx/HT32F165x/cmparams.h
* @brief ARM Cortex-M3 parameters for the Holtek HT32F165x
*
* @defgroup ARMCMx_HT32F165x Holtek HT32F165x Specific Parameters
* @ingroup ARMCMx_SPECIFIC
* @details This file contains the Cortex-M3 specific parameters for the
* Holtek HT32F165x platform.
* @{
*/
#ifndef _CMPARAMS_H_
#define _CMPARAMS_H_
/**
* @brief Cortex core model.
*/
#define CORTEX_MODEL 3
/**
* @brief Systick unit presence.
*/
#define CORTEX_HAS_ST TRUE
/**
* @brief Floating Point unit presence.
*/
#define CORTEX_HAS_FPU FALSE
/**
* @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 72
/* The following code is not processed when the file is included from an
asm module.*/
#if !defined(_FROM_ASM_)
#if !defined (HT32F1653) && !defined (HT32F1654) && \
!defined (HT32F1655) && !defined (HT32F1656)
#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 "ht32f165x.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_ */
/** @} */

View File

@ -0,0 +1,88 @@
/*
ChibiOS/RT - Copyright (C) 2006-2014 Giovanni Di Sirio.
(C) 2015 RedoX https://github.com/RedoXyde
(C) 2017 Charlie Waters <cawiii@me.com>
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 <http://www.gnu.org/licenses/>.
*/
/**
* @file GCC/ARMCMx/HT32F165x/cmparams.h
* @brief ARM Cortex-M3 parameters for the Holtek HT32F165x
*
* @defgroup ARMCMx_HT32F165x Holtek HT32F165x Specific Parameters
* @ingroup ARMCMx_SPECIFIC
* @details This file contains the Cortex-M3 specific parameters for the
* Holtek HT32F165x platform.
* @{
*/
#ifndef _CMPARAMS_H_
#define _CMPARAMS_H_
/**
* @brief Cortex core model.
*/
#define CORTEX_MODEL 0
/**
* @brief Systick unit presence.
*/
#define CORTEX_HAS_ST TRUE
/**
* @brief Floating Point unit presence.
*/
#define CORTEX_HAS_FPU FALSE
/**
* @brief Number of bits in priority masks.
*/
#define CORTEX_PRIORITY_BITS 8
/**
* @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 32
/* The following code is not processed when the file is included from an
asm module.*/
#if !defined(_FROM_ASM_)
#if !defined (HT32F52342) && !defined(HT32F52352)
#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 "ht32f523x2.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_ */
/** @} */

View File

@ -0,0 +1,123 @@
/*
ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
Copyright (C) 2020 Yaotian Feng
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 hal_lld.c
* @brief PLATFORM HAL subsystem low level driver source.
*
* @addtogroup HAL
* @{
*/
#include "hal.h"
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
void ht32_clock_init(void) {
// Enable backup domain. Needed for USB
CKCU->LPCR = CKCU_LPCR_BKISO;
CKCU->APBCCR1 |= CKCU_APBCCR1_BKPREN;
while (PWRCU->BAKTEST != 0x27);
#if HT32_CKCU_SW == CKCU_GCCR_SW_HSE
// Enable HSE
CKCU->GCCR |= CKCU_GCCR_HSEEN;
while ((CKCU->GCSR & CKCU_GCSR_HSERDY) == 0); // wait for HSE ready
#endif
#if HT32_CKCU_SW == CKCU_GCCR_SW_PLL
// Configure PLL
#if HT32_PLL_USE_HSE == TRUE
CKCU->GCFGR &= ~CKCU_GCFGR_PLLSRC; // HSE as PLL source
#else
CKCU->GCFGR |= CKCU_GCFGR_PLLSRC; // HSI as PLL source
#endif
CKCU->PLLCFGR = ((HT32_PLL_FBDIV & 0x3F) << 23) | ((HT32_PLL_OTDIV & 0x3) << 21);
CKCU->GCCR |= CKCU_GCCR_PLLEN; // enable PLL
while ((CKCU->GCSR & CKCU_GCSR_PLLRDY) == 0); // wait for PLL ready
#endif
// flash wait states for core clock frequencies
#if HT32_CK_AHB_FREQUENCY > 48000000
FMC->CFCR = (FMC->CFCR & ~FMC_CFCR_WAIT_MASK) | FMC_CFCR_WAIT_2;
#elif HT32_CK_AHB_FREQUENCY > 24000000
FMC->CFCR = (FMC->CFCR & ~FMC_CFCR_WAIT_MASK) | FMC_CFCR_WAIT_1;
#else
FMC->CFCR = (FMC->CFCR & ~FMC_CFCR_WAIT_MASK) | FMC_CFCR_WAIT_0;
#endif
// AHB prescaler
#if HT32_AHB_PRESCALER == 1 || HT32_AHB_PRESCALER == 2
CKCU->AHBCFGR = (CKCU->AHBCFGR & ~CKCU_AHBCFGR_AHBPRE_MASK) | (HT32_AHB_PRESCALER - 1);
#elif HT32_AHB_PRESCALER == 4
CKCU->AHBCFGR = (CKCU->AHBCFGR & ~CKCU_AHBCFGR_AHBPRE_MASK) | (2);
#elif HT32_AHB_PRESCALER == 8
CKCU->AHBCFGR = (CKCU->AHBCFGR & ~CKCU_AHBCFGR_AHBPRE_MASK) | (3);
#else
#error "Invalid AHB_PRESCALER value"
#endif
// Clock switch
CKCU->GCCR = (CKCU->GCCR & ~CKCU_GCCR_SW_MASK) | HT32_CKCU_SW;
while ((CKCU->GCCR & CKCU_GCCR_SW_MASK) != HT32_CKCU_SW); // wait for clock switch
// HSI is needed for flash erase/write for some reason.
// Only disable if you will not need to erase/write memory
// with your debug probe after this firmware has booted.
// /* CKCU->GCCR &= ~CKCU_GCCR_HSIEN; */
#if defined(HT32F1653_4)
// Peripheral prescalers are not available on HT32F1655/6
// So make sure all prescalers are 1x on HT32F1653/4
CKCU->APBPCSR0 = 0;
CKCU->APBPCSR1 = 0;
#endif
}
/**
* @brief Low level HAL driver initialization.
*
* @notapi
*/
void hal_lld_init(void) {
ht32_clock_init();
}
/** @} */

View File

@ -0,0 +1,166 @@
/*
ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
Copyright (C) 2020 Yaotian Feng
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 hal_lld.h
* @brief HT32 HAL subsystem low level driver header.
*
* @addtogroup HAL
* @{
*/
#ifndef _HAL_LLD_H_
#define _HAL_LLD_H_
#include "ht32_registry.h"
#include "nvic.h"
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/**
* @name Platform identification macros
* @{
*/
#define PLATFORM_NAME "HT32"
/** @} */
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name PLATFORM configuration options
* @{
*/
/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*
* Configuration-related checks.
*/
#if !defined(HT32F165x_MCUCONF) && !defined(HT32F1654_MCUCONF) && \
!defined(HT32F1653_MCUCONF)
#error "Using a wrong mcuconf.h file, HT32_MCUCONF not defined"
#endif
#define HT32_CK_HSI_FREQUENCY 8000000UL // 8 MHz
#if HT32_CKCU_SW == CKCU_GCCR_SW_HSI
#define HT32_CK_SYS_FREQUENCY HT32_CK_HSI_FREQUENCY
#elif HT32_CKCU_SW == CKCU_GCCR_SW_HSE
#if !defined(HT32_CK_HSE_FREQUENCY)
#error "HT32_CK_HSE_FREQUENCY must be defined"
#endif
#define HT32_CK_SYS_FREQUENCY HT32_CK_HSE_FREQUENCY
#elif HT32_CKCU_SW == CKCU_GCCR_SW_PLL
#if !defined(HT32_PLL_USE_HSE)
#error "HT32_PLL_USE_HSE must be defined"
#endif
#if HT32_PLL_USE_HSE == TRUE
#if !defined(HT32_CK_HSE_FREQUENCY)
#error "HT32_CK_HSE_FREQUENCY must be defined"
#endif
#define HT32_PLL_IN_FREQ HT32_CK_HSE_FREQUENCY
#else
#define HT32_PLL_IN_FREQ HT32_CK_HSI_FREQUENCY
#endif
#if !defined(HT32_PLL_FBDIV)
#error "HT32_PLL_FBDIV must be defined"
#endif
#if !defined(HT32_PLL_OTDIV)
#error "HT32_PLL_OTDIV must be defined"
#endif
#define HT32_CK_PLL_FREQUENCY ((HT32_PLL_IN_FREQ * HT32_PLL_FBDIV) / (1 << HT32_PLL_OTDIV))
#define HT32_CK_SYS_FREQUENCY HT32_CK_PLL_FREQUENCY
#else
#error "HT32_CKCU_SW is invalid"
#endif
#if !defined(HT32_AHB_PRESCALER)
#define HT32_AHB_PRESCALER 1
#endif
// AHB clock
#define HT32_CK_AHB_FREQUENCY (HT32_CK_SYS_FREQUENCY / HT32_AHB_PRESCALER) // Max 72 MHz
// SysTick (may also use HCLK)
#define HT32_STCLK_FREQUENCY (HT32_CK_AHB_FREQUENCY / 8) // Max 8MHz
// CPU clock
#define HT32_HCLK_FREQUENCY HT32_CK_AHB_FREQUENCY
// Peripheral clocks
#define HT32_PCLK_FREQUENCY HT32_CK_AHB_FREQUENCY
// Checks
#if HT32_CK_SYS_FREQUENCY > 144000000
#error "HT32 CK_SYS invalid"
#endif
#if HT32_CK_AHB_FREQUENCY > 72000000
#error "HT32 CK_AHB invalid"
#endif
#if (HAL_USE_UART == TRUE || HAL_USE_SERIAL == TRUE)
#define HT32_CK_USART_FREQUENCY (HT32_CK_AHB_FREQUENCY / HT32_USART_PRESCALER) // Max 72 MHz
#if HT32_CK_USART_FREQUENCY > 72000000
#error "HT32 CK_USART invalid"
#endif
#endif
#if HAL_USE_USB == TRUE
#if HT32_CKCU_SW != CKCU_GCCR_SW_PLL
#error "HT32 USB requires PLL"
#endif
#define HT32_CK_USB_FREQUENCY (HT32_CK_PLL_FREQUENCY / HT32_USB_PRESCALER) // Max 48 MHz
#if HT32_CK_USB_FREQUENCY > 48000000
#error "HT32 CK_USB invalid"
#endif
#endif
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
void hal_lld_init(void);
void ht32_clock_init(void);
#ifdef __cplusplus
}
#endif
#endif /* _HAL_LLD_H_ */
/** @} */

View File

@ -0,0 +1,134 @@
/*
ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
Copyright (C) 2020 Yaotian Feng
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 HT32F165x/ht32_registry.h
* @brief HT32F165x capabilities registry.
*
* @addtogroup HAL
* @{
*/
#ifndef HT32_REGISTRY_H
#define HT32_REGISTRY_H
/**
* @brief Sub-family identifier.
*/
#if defined(HT32F1653) || defined(HT32F1654) || \
defined(HT32F1655) || defined(HT32F1656) || \
defined(__DOXYGEN__)
#define HT32F165x
#else
#error unknown/unsupported HT32 microcontroller
#endif
/*===========================================================================*/
/* Platform capabilities. */
/*===========================================================================*/
#if defined(HT32F165x) || defined(__DOXYGEN__)
/**
* @brief Maximum system and core clock (f_SYS) frequency.
*/
#define HT32_SYSCLK_MAX 72000000L
/**
* @brief Maximum bus clock (f_BUS) frequency.
*/
#define HT32_BUSCLK_MAX 72000000L
/**
* @brief Maximum flash clock (f_FLASH) frequency.
*/
#define HT32_FLASHCLK_MAX 72000000L
/**
* @name HT32F165x attributes
* @{
*/
/* GPIO attributes.*/
#if defined(HT32F1655) || defined(HT32F1656)
#define HT32_NUM_GPIO 5
#else
#define HT32_NUM_GPIO 4
#endif
#define HT32_GPIO_INDEX_BITS 13
#define HT32_CCR_PAEN CKCU_AHBCCR_PAEN
/* EXTI attributes */
#define HT32_HAS_EXTI TRUE
#define HT32_NUM_EXTI 16
#define HT32_EVWUP_IRQ_VECTOR Vector58
#define HT32_EXTI0_IRQ_VECTOR Vector60
#define HT32_EXTI1_IRQ_VECTOR Vector64
#define HT32_EXTI2_IRQ_VECTOR Vector68
#define HT32_EXTI3_IRQ_VECTOR Vector6C
#define HT32_EXTI4_IRQ_VECTOR Vector70
#define HT32_EXTI5_IRQ_VECTOR Vector74
#define HT32_EXTI6_IRQ_VECTOR Vector78
#define HT32_EXTI7_IRQ_VECTOR Vector7C
#define HT32_EXTI8_IRQ_VECTOR Vector80
#define HT32_EXTI9_IRQ_VECTOR Vector84
#define HT32_EXTI10_IRQ_VECTOR Vector88
#define HT32_EXTI11_IRQ_VECTOR Vector8C
#define HT32_EXTI12_IRQ_VECTOR Vector90
#define HT32_EXTI13_IRQ_VECTOR Vector94
#define HT32_EXTI14_IRQ_VECTOR Vector98
#define HT32_EXTI15_IRQ_VECTOR Vector9C
/* I2C attributes.*/
#define HT32_HAS_I2C0 TRUE
#define HT32_I2C0_IRQ_VECTOR VectorEC
#define HT32_HAS_I2C1 TRUE
#define HT32_I2C1_IRQ_VECTOR VectorF0
/* SPI attributes.*/
#define HT32_HAS_SPI0 TRUE
#define HT32_SPI0_IRQ_VECTOR VectorF4
#define HT32_HAS_SPI1 TRUE
#define HT32_SPI1_IRQ_VECTOR VectorF8
/* UART attributes.*/
#define HT32_HAS_USART0 TRUE
#define HT32_USART0_IRQ_VECTOR VectorFC
#define HT32_HAS_USART1 TRUE
#define HT32_USART1_IRQ_VECTOR Vector100
#define HT32_HAS_UART0 TRUE
#define HT32_UART0_IRQ_VECTOR Vector104
#define HT32_HAS_UART1 TRUE
#define HT32_UART1_IRQ_VECTOR Vector108
/* USB attributes.*/
#define HT32_HAS_USB TRUE
#define HT32_USB_IRQ_VECTOR Vector114
#define HT32_USB0_IS_USBOTG FALSE
#define HT32_HAS_USB_CLOCK_RECOVERY FALSE
/* BFTM attributes. */
#define HT32_BFTM0_IRQ_VECTOR VectorE4
#define HT32_BFTM1_IRQ_VECTOR VectorE8
/** @} */
#endif /* defined(HT32F165x) */
#endif /* HT32_REGISTRY_H */
/** @} */

View File

@ -0,0 +1,35 @@
# List of all the platform files.
PLATFORMSRC = $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \
$(CHIBIOS_CONTRIB)/os/hal/ports/HT32/HT32F165x/hal_lld.c
# Required include directories
PLATFORMINC = $(CHIBIOS)/os/hal/ports/common/ARMCMx \
$(CHIBIOS_CONTRIB)/os/hal/ports/HT32/HT32F165x
# Optional platform files.
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/HT32/LLD/TIMv1/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/HT32/LLD/SPIv1/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/HT32/LLD/GPIOv1/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/HT32/LLD/USBv1/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/HT32/LLD/USART_F165x/driver.mk
# Shared variables
ALLCSRC += $(PLATFORMSRC)
ALLINC += $(PLATFORMINC)

View File

@ -0,0 +1,122 @@
/*
ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
Copyright (C) 2020 Yaotian Feng
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 hal_lld.c
* @brief PLATFORM HAL subsystem low level driver source.
*
* @addtogroup HAL
* @{
*/
#include "hal.h"
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
void ht32_clock_init(void) {
// Enable backup domain. Needed for USB
CKCU->LPCR = CKCU_LPCR_BKISO;
CKCU->APBCCR1 |= CKCU_APBCCR1_BKPREN;
while (PWRCU->BAKTEST != 0x27);
#if HT32_CKCU_SW == CKCU_GCCR_SW_HSE
// Enable HSE
CKCU->GCCR |= CKCU_GCCR_HSEEN;
while ((CKCU->GCSR & CKCU_GCSR_HSERDY) == 0); // wait for HSE ready
#endif
#if HT32_CKCU_SW == CKCU_GCCR_SW_PLL
// Configure PLL
#if HT32_PLL_USE_HSE == TRUE
CKCU->GCFGR &= ~CKCU_GCFGR_PLLSRC; // HSE as PLL source
#else
CKCU->GCFGR |= CKCU_GCFGR_PLLSRC; // HSI as PLL source
#endif
CKCU->PLLCFGR = ((HT32_PLL_FBDIV & 0x3F) << 23) | ((HT32_PLL_OTDIV & 0x3) << 21);
CKCU->GCCR |= CKCU_GCCR_PLLEN; // enable PLL
while ((CKCU->GCSR & CKCU_GCSR_PLLRDY) == 0); // wait for PLL ready
#endif
// flash wait states for core clock frequencies
#if HT32_CK_AHB_FREQUENCY > 24000000
FMC->CFCR = (FMC->CFCR & ~FMC_CFCR_WAIT_MASK) | FMC_CFCR_WAIT_1;
#else
FMC->CFCR = (FMC->CFCR & ~FMC_CFCR_WAIT_MASK) | FMC_CFCR_WAIT_0;
#endif
// AHB prescaler
#if HT32_AHB_PRESCALER == 1 || HT32_AHB_PRESCALER == 2
CKCU->AHBCFGR = (CKCU->AHBCFGR & ~CKCU_AHBCFGR_AHBPRE_MASK) | (HT32_AHB_PRESCALER - 1);
#elif HT32_AHB_PRESCALER == 4
CKCU->AHBCFGR = (CKCU->AHBCFGR & ~CKCU_AHBCFGR_AHBPRE_MASK) | (2);
#elif HT32_AHB_PRESCALER == 8
CKCU->AHBCFGR = (CKCU->AHBCFGR & ~CKCU_AHBCFGR_AHBPRE_MASK) | (3);
#else
#error "Invalid AHB_PRESCALER value"
#endif
// Clock switch
CKCU->GCCR = (CKCU->GCCR & ~CKCU_GCCR_SW_MASK) | HT32_CKCU_SW;
while ((CKCU->GCCR & CKCU_GCCR_SW_MASK) != HT32_CKCU_SW); // wait for clock switch
// HSI is needed for flash erase/write for some reason.
// Only disable if you will not need to erase/write memory
// with your debug probe after this firmware has booted.
// /* CKCU->GCCR &= ~CKCU_GCCR_HSIEN; */
#if defined(HT32F1653_4)
// Peripheral prescalers are not available on HT32F1655/6
// So make sure all prescalers are 1x on HT32F1653/4
CKCU->APBPCSR0 = 0;
CKCU->APBPCSR1 = 0;
#endif
}
/**
* @brief Low level HAL driver initialization.
*
* @notapi
*/
void hal_lld_init(void) {
CKCU->APBCCR0 &= ~(CKCU_APBCCR0_EXTIEN | CKCU_APBCCR0_UR0EN | CKCU_APBCCR0_USR0EN | CKCU_APBCCR0_UR1EN | CKCU_APBCCR0_USR1EN);
ht32_clock_init();
}
/** @} */

View File

@ -0,0 +1,168 @@
/*
ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
Copyright (C) 2020 Yaotian Feng
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 hal_lld.h
* @brief HT32 HAL subsystem low level driver header.
*
* @addtogroup HAL
* @{
*/
#ifndef _HAL_LLD_H_
#define _HAL_LLD_H_
#include "ht32_registry.h"
#include "nvic.h"
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/**
* @name Platform identification macros
* @{
*/
#define PLATFORM_NAME "HT32"
/** @} */
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name PLATFORM configuration options
* @{
*/
/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*
* Configuration-related checks.
*/
#if !defined(HT32F52342_MCUCONF) && !defined(HT32F52352_MCUCONF) && \
!defined(HT32F523x2_MCUCONF)
#error "Using a wrong mcuconf.h file, HT32_MCUCONF not defined"
#endif
#define HT32_CK_HSI_FREQUENCY 8000000UL // 8 MHz
#if HT32_CKCU_SW == CKCU_GCCR_SW_HSI
#define HT32_CK_SYS_FREQUENCY HT32_CK_HSI_FREQUENCY
#elif HT32_CKCU_SW == CKCU_GCCR_SW_HSE
#if !defined(HT32_CK_HSE_FREQUENCY)
#error "HT32_CK_HSE_FREQUENCY must be defined"
#endif
#define HT32_CK_SYS_FREQUENCY HT32_CK_HSE_FREQUENCY
#elif HT32_CKCU_SW == CKCU_GCCR_SW_PLL
#if !defined(HT32_PLL_USE_HSE)
#error "HT32_PLL_USE_HSE must be defined"
#endif
#if HT32_PLL_USE_HSE == TRUE
#if !defined(HT32_CK_HSE_FREQUENCY)
#error "HT32_CK_HSE_FREQUENCY must be defined"
#endif
#define HT32_PLL_IN_FREQ HT32_CK_HSE_FREQUENCY
#else
#define HT32_PLL_IN_FREQ HT32_CK_HSI_FREQUENCY
#endif
#if !defined(HT32_PLL_FBDIV)
#error "HT32_PLL_FBDIV must be defined"
#endif
#if !defined(HT32_PLL_OTDIV)
#error "HT32_PLL_OTDIV must be defined"
#endif
#define HT32_CK_PLL_FREQUENCY ((HT32_PLL_IN_FREQ * HT32_PLL_FBDIV) / (1 << HT32_PLL_OTDIV))
#define HT32_CK_SYS_FREQUENCY HT32_CK_PLL_FREQUENCY
#else
#error "HT32_CKCU_SW is invalid"
#endif
#if !defined(HT32_AHB_PRESCALER)
#define HT32_AHB_PRESCALER 1
#endif
// AHB clock
#define HT32_CK_AHB_FREQUENCY (HT32_CK_SYS_FREQUENCY / HT32_AHB_PRESCALER) // Max 48 MHz
// SysTick (may also use HCLK)
#define HT32_STCLK_FREQUENCY (HT32_CK_AHB_FREQUENCY / 8) // Max 8MHz
// CPU clock
#define HT32_HCLK_FREQUENCY HT32_CK_AHB_FREQUENCY
// Peripheral clocks
#define HT32_PCLK_FREQUENCY HT32_CK_AHB_FREQUENCY
// Checks
#if HT32_CK_SYS_FREQUENCY > 48000000
#error "HT32 CK_SYS invalid"
#endif
#if HT32_CK_AHB_FREQUENCY > 48000000
#error "HT32 CK_AHB invalid"
#endif
#if HAL_USE_UART == TRUE || HAL_USE_SERIAL == TRUE
#define HT32_CK_USART_FREQUENCY (HT32_CK_AHB_FREQUENCY / HT32_USART_PRESCALER) // Max 48 MHz
#if HT32_CK_USART_FREQUENCY > 48000000
#error "HT32 CK_USART invalid"
#endif
#endif
#if HAL_USE_USB == TRUE
#if HT32_CKCU_SW != CKCU_GCCR_SW_PLL
#error "HT32 USB requires PLL"
#endif
#define HT32_CK_USB_FREQUENCY (HT32_CK_PLL_FREQUENCY / HT32_USB_PRESCALER) // Max 48 MHz
#if HT32_CK_USB_FREQUENCY > 48000000
#error "HT32 CK_USB invalid"
#endif
#endif
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
void hal_lld_init(void);
void ht32_clock_init(void);
#ifdef __cplusplus
}
#endif
#endif /* _HAL_LLD_H_ */
/** @} */

View File

@ -0,0 +1,115 @@
/*
ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
Copyright (C) 2020 Yaotian Feng
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 HT32F165x/ht32_registry.h
* @brief HT32F165x capabilities registry.
*
* @addtogroup HAL
* @{
*/
#pragma once
/**
* @brief Sub-family identifier.
*/
#if defined(HT32F52342) || defined(HT32F52352) || \
defined(__DOXYGEN__)
#define HT32F523x2
#else
#error unknown/unsupported HT32 microcontroller
#endif
/*===========================================================================*/
/* Platform capabilities. */
/*===========================================================================*/
#if defined(HT32F523x2) || defined(__DOXYGEN__)
/**
* @brief Maximum system and core clock (f_SYS) frequency.
*/
#define HT32_SYSCLK_MAX 48000000L
/**
* @brief Maximum bus clock (f_BUS) frequency.
*/
#define HT32_BUSCLK_MAX 48000000L
/**
* @brief Maximum flash clock (f_FLASH) frequency.
*/
#define HT32_FLASHCLK_MAX 48000000L
/**
* @name HT32F52342x attributes
* @{
*/
/* GPIO attributes.*/
#define HT32_NUM_GPIO 4
#define HT32_GPIO_INDEX_BITS 13
#define HT32_CCR_PAEN CKCU_AHBCCR_PAEN
/* EXTI attributes */
#define HT32_HAS_EXTI TRUE
#define HT32_NUM_EXTI 3
#define HT32_EVWUP_IRQ_VECTOR Vector4C
#define HT32_EXTI0_1_IRQ_VECTOR Vector50
#define HT32_EXTI2_3_IRQ_VECTOR Vector54
#define HT32_EXTI4_15_IRQ_VECTOR Vector58
/* BFTM attributes. */
#define HT32_BFTM0_IRQ_VECTOR Vector84
#define HT32_BFTM1_IRQ_VECTOR Vector88
/* I2C attributes.*/
#define HT32_HAS_I2C0 TRUE
#define HT32_I2C0_IRQ_VECTOR Vector8C
#define HT32_HAS_I2C1 TRUE
#define HT32_I2C1_IRQ_VECTOR Vector90
/* SPI attributes.*/
#define HT32_HAS_SPI0 TRUE
#define HT32_SPI0_IRQ_VECTOR Vector94
#define HT32_HAS_SPI1 TRUE
#define HT32_SPI1_IRQ_VECTOR Vector98
/* UART attributes.*/
#define HT32_HAS_USART0 TRUE
#define HT32_USART0_IRQ_VECTOR Vector9C
#define HT32_HAS_USART1 TRUE
#define HT32_USART1_IRQ_VECTOR VectorA0
#define HT32_HAS_UART0 TRUE
#define HT32_UART0_IRQ_VECTOR VectorA4
#define HT32_HAS_UART1 TRUE
#define HT32_UART1_IRQ_VECTOR VectorA8
/* USB attributes.*/
#define HT32_HAS_USB TRUE
#define HT32_USB_IRQ_VECTOR VectorB4
#define HT32_USB0_IS_USBOTG FALSE
#define HT32_HAS_USB_CLOCK_RECOVERY FALSE
/** @} */
#endif /* defined(HT32F165x) */
/** @} */

View File

@ -0,0 +1,35 @@
# List of all the platform files.
PLATFORMSRC = $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \
$(CHIBIOS_CONTRIB)/os/hal/ports/HT32/HT32F523xx/hal_lld.c
# Required include directories
PLATFORMINC = $(CHIBIOS)/os/hal/ports/common/ARMCMx \
$(CHIBIOS_CONTRIB)/os/hal/ports/HT32/HT32F523xx
# Optional platform files.
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/HT32/LLD/TIMv1/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/HT32/LLD/SPIv1/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/HT32/LLD/GPIOv1/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/HT32/LLD/USBv1/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/HT32/LLD/USART_F5xxxx/driver.mk
# Shared variables
ALLCSRC += $(PLATFORMSRC)
ALLINC += $(PLATFORMINC)

View File

@ -0,0 +1,9 @@
ifeq ($(USE_SMART_BUILD),yes)
ifneq ($(findstring HAL_USE_PAL TRUE,$(HALCONF)),)
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/HT32/LLD/GPIOv1/hal_pal_lld.c
endif
else
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/HT32/LLD/GPIOv1/hal_pal_lld.c
endif
PLATFORMINC += $(CHIBIOS_CONTRIB)/os/hal/ports/HT32/LLD/GPIOv1

View File

@ -0,0 +1,162 @@
/*
Copyright (C) 2020 Yaotian Feng
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 hal_pal_lld.c
* @brief HT32 PAL subsystem low level driver source.
*
* @addtogroup PAL
* @{
*/
#include "hal.h"
#if (HAL_USE_PAL == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
static void initgpio(ioportid_t port, const struct port_setup * const setup) {
PAL_PORT(port)->DIRCR = setup->DIR;
PAL_PORT(port)->INER = setup->INE;
PAL_PORT(port)->PUR = setup->PU;
PAL_PORT(port)->PDR = setup->PD;
PAL_PORT(port)->ODR = setup->OD;
PAL_PORT(port)->DRVR = setup->DRV;
const uint32_t portidx = HT32_PAL_IDX(port);
AFIO->GPxCFGR[portidx][0] = setup->CFG[0];
AFIO->GPxCFGR[portidx][1] = setup->CFG[1];
if (setup->LOCK != 0) {
PAL_PORT(port)->LOCKR = 0x5FA00000 | setup->LOCK;
}
}
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief HT32 I/O ports configuration.
* @details Ports A-D(E, F, G, H) clocks enabled.
*
* @param[in] config the HT32 ports configuration
*
* @notapi
*/
void _pal_lld_init(const PALConfig *config) {
CKCU->AHBCCR |= (HT32_CCR_PAEN << HT32_NUM_GPIO) - HT32_CCR_PAEN;
// enable AFIO
CKCU->APBCCR0 |= CKCU_APBCCR0_AFIOEN;
if (config == NULL)
return;
for (size_t i = 0; i < HT32_NUM_GPIO; i++) {
initgpio(HT32_PAL_ID(i), &(config->setup[i]));
}
AFIO->ESSR[0] = config->ESSR[0];
AFIO->ESSR[1] = config->ESSR[1];
}
/**
* @brief Pads mode setup.
* @details This function programs a pads group belonging to the same port
* with the specified mode.
*
* @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) {
if ((mode & PAL_HT32_MODE_AFE) != 0) {
const uint32_t afn = (mode >> 8) & 0xf;
const uint32_t portidx = HT32_PAL_IDX(port);
uint32_t cfg[2];
cfg[0] = AFIO->GPxCFGR[portidx][0];
cfg[1] = AFIO->GPxCFGR[portidx][1];
for (size_t i = 0; i < PAL_IOPORTS_WIDTH; i++) {
if ((mask & (1U << i)) == 0)
continue;
cfg[i / 8] &= ~(0xfU << ((i % 8) * 4));
cfg[i / 8] |= afn << ((i % 8) * 4);
}
AFIO->GPxCFGR[portidx][0] = cfg[0];
AFIO->GPxCFGR[portidx][1] = cfg[1];
}
if ((mode & PAL_HT32_MODE_DIR) != 0) {
PAL_PORT(port)->DIRCR |= mask;
} else {
PAL_PORT(port)->DIRCR &= ~mask;
}
if ((mode & PAL_HT32_MODE_INE) != 0) {
PAL_PORT(port)->INER |= mask;
} else {
PAL_PORT(port)->INER &= ~mask;
}
if ((mode & PAL_HT32_MODE_PU) != 0) {
PAL_PORT(port)->PUR |= mask;
} else {
PAL_PORT(port)->PUR &= ~mask;
}
if ((mode & PAL_HT32_MODE_PD) != 0) {
PAL_PORT(port)->PDR |= mask;
} else {
PAL_PORT(port)->PDR &= ~mask;
}
if ((mode & PAL_HT32_MODE_OD) != 0) {
PAL_PORT(port)->ODR |= mask;
} else {
PAL_PORT(port)->ODR &= ~mask;
}
if ((mode & PAL_HT32_MODE_DRV) != 0) {
PAL_PORT(port)->DRVR |= mask;
} else {
PAL_PORT(port)->DRVR &= ~mask;
}
}
#endif /* HAL_USE_PAL == TRUE */
/** @} */

View File

@ -0,0 +1,482 @@
/*
Copyright (C) 2020 Yaotian Feng
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 hal_pal_lld.h
* @brief PLATFORM PAL subsystem low level driver header.
*
* @addtogroup PAL
* @{
*/
#ifndef HAL_PAL_LLD_H
#define HAL_PAL_LLD_H
#if (HAL_USE_PAL == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Unsupported modes and specific modes */
/*===========================================================================*/
#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
#define PAL_HT32_MODE_DIR ( 1U << 0)
#define PAL_HT32_MODE_INE ( 1U << 1)
#define PAL_HT32_MODE_PU ( 1U << 2)
#define PAL_HT32_MODE_PD ( 1U << 3)
#define PAL_HT32_MODE_OD ( 1U << 4)
#define PAL_HT32_MODE_DRV ( 1U << 5)
#define PAL_HT32_MODE_LOCK ( 1U << 6)
#define PAL_HT32_MODE_AF_MASK (15U << 8)
#define PAL_HT32_MODE_AFE ( 1U << 15)
#define PAL_HT32_MODE_AF(m) (PAL_HT32_MODE_AFE | ((m) << 8))
//#define PAL_MODE_RESET (0)
#define PAL_MODE_UNCONNECTED (PAL_HT32_MODE_LOCK)
#define PAL_MODE_INPUT (PAL_HT32_MODE_INE)
#define PAL_MODE_INPUT_PULLUP (PAL_HT32_MODE_PU|PAL_HT32_MODE_INE)
#define PAL_MODE_INPUT_PULLDOWN (PAL_HT32_MODE_PD|PAL_HT32_MODE_INE)
#define PAL_MODE_INPUT_ANALOG (PAL_HT32_MODE_AF(2))
#define PAL_MODE_OUTPUT_PUSHPULL (PAL_HT32_MODE_DIR)
#define PAL_MODE_OUTPUT_OPENDRAIN (PAL_HT32_MODE_OD|PAL_HT32_MODE_DIR)
#define PAL_MODE_HT32_AF PAL_HT32_MODE_AF
/*===========================================================================*/
/* I/O Ports Types and constants. */
/*===========================================================================*/
/**
* @name Port related definitions
* @{
*/
/**
* @brief Width, in bits, of an I/O port.
*/
#define PAL_IOPORTS_WIDTH 16U
/**
* @brief Whole port mask.
* @details This macro specifies all the valid bits into a port.
*/
#define PAL_WHOLE_PORT ((ioportmask_t)0xFFFFU)
/** @} */
/**
* @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.
*/
#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) \
((GPIO_TypeDef *)(((uint32_t)(line)) & 0xFFFFFFC0U))
/**
* @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 Generic I/O ports static initializer.
* @details An instance of this structure must be passed to @p palInit() at
* system startup time in order to initialized the digital I/O
* subsystem. This represents only the initial setup, specific pads
* or whole ports can be reprogrammed at later time.
* @note Implementations may extend this structure to contain more,
* architecture dependent, fields.
*/
struct port_setup {
uint16_t DIR;
uint16_t INE;
uint16_t PU;
uint16_t PD;
uint16_t OD;
uint16_t DRV;
uint16_t LOCK;
uint16_t OUT;
uint32_t CFG[2];
};
typedef struct {
struct port_setup setup[HT32_NUM_GPIO];
uint32_t ESSR[2];
} PALConfig;
/**
* @brief Digital I/O port sized unsigned type.
*/
typedef uint16_t ioportmask_t;
/**
* @brief Digital I/O modes.
*/
typedef uint16_t iomode_t;
/**
* @brief Type of an I/O line.
*/
typedef uintptr_t ioline_t;
/**
* @brief 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 GPIO_TypeDef * ioportid_t;
/**
* @brief Type of an pad identifier
*/
typedef uint32_t iopadid_t;
/*===========================================================================*/
/* I/O Ports Identifiers. */
/*===========================================================================*/
/**
* @brief First I/O port identifier.
* @details Low level drivers can define multiple ports, it is suggested to
* use this naming convention.
*/
#define HT32_PAL_ID(x) ((ioportid_t)(GPIO_A_BASE + (x << HT32_GPIO_INDEX_BITS)))
#define HT32_PAL_IDX(x) (((uintptr_t)(x) - GPIO_A_BASE) >> HT32_GPIO_INDEX_BITS)
#define IOPORT1 HT32_PAL_ID(0)
#define IOPORT2 HT32_PAL_ID(1)
#define IOPORT3 HT32_PAL_ID(2)
#define IOPORT4 HT32_PAL_ID(3)
#define IOPORT5 HT32_PAL_ID(4)
#define IOPORTA IOPORT1
#define IOPORTB IOPORT2
#define IOPORTC IOPORT3
#define IOPORTD IOPORT4
#define IOPORTE IOPORT5
/*===========================================================================*/
/* Implementation, some of the following macros could be implemented as */
/* functions, if so please put them in pal_lld.c. */
/*===========================================================================*/
/**
* @brief Low level PAL subsystem initialization.
*
* @param[in] config architecture-dependent ports configuration
*
* @notapi
*/
#define pal_lld_init(config) _pal_lld_init(config)
/**
* @brief Reads the physical I/O port states.
*
* @param[in] port port identifier
* @return The port bits.
*
* @notapi
*/
#define pal_lld_readport(port) (PAL_PORT(port)->DINR)
/**
* @brief Reads the output latch.
* @details The purpose of this function is to read back the latched output
* value.
*
* @param[in] port port identifier
* @return The latched logical states.
*
* @notapi
*/
#define pal_lld_readlatch(port) (PAL_PORT(port)->DOUTR)
/**
* @brief Writes a bits mask on a I/O port.
*
* @param[in] port port identifier
* @param[in] bits bits to be written on the specified port
*
* @notapi
*/
#define pal_lld_writeport(port, bits) \
do { \
PAL_PORT(port)->DOUTR = (bits); \
} while (false)
/**
* @brief Sets a bits mask on a I/O port.
* @note The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
*
* @param[in] port port identifier
* @param[in] bits bits to be ORed on the specified port
*
* @notapi
*/
#define pal_lld_setport(port, bits) \
do { \
PAL_PORT(port)->SRR = (bits); \
} while (false)
/**
* @brief Clears a bits mask on a I/O port.
* @note The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
*
* @param[in] port port identifier
* @param[in] bits bits to be cleared on the specified port
*
* @notapi
*/
#define pal_lld_clearport(port, bits) \
do { \
PAL_PORT(port)->RR = (bits); \
} while (false)
#if 0
/**
* @brief Toggles a bits mask on a I/O port.
* @note The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
*
* @param[in] port port identifier
* @param[in] bits bits to be XORed on the specified port
*
* @notapi
*/
#define pal_lld_toggleport(port, bits) \
do { \
(void)port; \
(void)bits; \
} while (false)
/**
* @brief Reads a group of bits.
* @note The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
*
* @param[in] port port identifier
* @param[in] mask group mask
* @param[in] offset group bit offset within the port
* @return The group logical states.
*
* @notapi
*/
#define pal_lld_readgroup(port, mask, offset) 0U
/**
* @brief Writes a group of bits.
* @note The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
*
* @param[in] port port identifier
* @param[in] mask group mask
* @param[in] offset 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) \
do { \
(void)port; \
(void)mask; \
(void)offset; \
(void)bits; \
} while (false)
#endif
/**
* @brief Pads group mode setup.
* @details This function programs a pads group belonging to the same port
* with the specified mode.
* @note Programming an unknown or unsupported mode is silently ignored.
*
* @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)
#if 0
/**
* @brief Reads a logical state from an I/O pad.
* @note The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
*
* @param[in] port port identifier
* @param[in] pad pad number within the port
* @return The logical state.
* @retval PAL_LOW low logical state.
* @retval PAL_HIGH high logical state.
*
* @notapi
*/
#define pal_lld_readpad(port, pad) PAL_LOW
/**
* @brief Writes a logical state on an output pad.
* @note This function is not meant to be invoked directly by the
* application code.
* @note The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
*
* @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) \
do { \
(void)port; \
(void)pad; \
(void)bit; \
} while (false)
/**
* @brief Sets a pad logical state to @p PAL_HIGH.
* @note The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
*
* @param[in] port port identifier
* @param[in] pad pad number within the port
*
* @notapi
*/
#define pal_lld_setpad(port, pad) \
do { \
(void)port; \
(void)pad; \
} while (false)
/**
* @brief Clears a pad logical state to @p PAL_LOW.
* @note The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
*
* @param[in] port port identifier
* @param[in] pad pad number within the port
*
* @notapi
*/
#define pal_lld_clearpad(port, pad) \
do { \
(void)port; \
(void)pad; \
} while (false)
/**
* @brief Toggles a pad logical state.
* @note The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
*
* @param[in] port port identifier
* @param[in] pad pad number within the port
*
* @notapi
*/
#define pal_lld_togglepad(port, pad) \
do { \
(void)port; \
(void)pad; \
} while (false)
/**
* @brief Pad mode setup.
* @details This function programs a pad with the specified mode.
* @note The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
* @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 mode
*
* @notapi
*/
#define pal_lld_setpadmode(port, pad, mode) \
do { \
(void)port; \
(void)pad; \
(void)mode; \
} while (false)
#endif
#if !defined(__DOXYGEN__)
extern const PALConfig pal_default_config;
#endif
#ifdef __cplusplus
extern "C" {
#endif
void _pal_lld_init(const PALConfig *config);
void _pal_lld_setgroupmode(ioportid_t port,
ioportmask_t mask,
iomode_t mode);
#ifdef __cplusplus
}
#endif
#endif /* HAL_USE_PAL == TRUE */
#endif /* HAL_PAL_LLD_H */
/** @} */

View File

@ -0,0 +1,9 @@
ifeq ($(USE_SMART_BUILD),yes)
ifneq ($(findstring HAL_USE_SPI TRUE,$(HALCONF)),)
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/HT32/LLD/SPIv1/hal_spi_lld.c
endif
else
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/HT32/LLD/SPIv1/hal_spi_lld.c
endif
PLATFORMINC += $(CHIBIOS_CONTRIB)/os/hal/ports/HT32/LLD/SPIv1

View File

@ -0,0 +1,320 @@
/*
ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
Copyright (C) 2020 Yaotian Feng
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 hal_spi_lld.c
* @brief HT32 SPI subsystem low level driver source.
*
* @addtogroup SPI
* @{
*/
#include "hal.h"
#if (HAL_USE_SPI == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/**
* @brief SPI0 driver identifier.
*/
#if (HT32_SPI_USE_SPI0 == TRUE) || defined(__DOXYGEN__)
SPIDriver SPID0;
#endif
#if (HT32_SPI_USE_SPI1 == TRUE) || defined(__DOXYGEN__)
SPIDriver SPID1;
#endif
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
#if (HT32_SPI_USE_SPI0 == TRUE) || (HT32_SPI_USE_SPI1 == TRUE) || defined(__DOXYGEN__)
static void spi_lld_rx(SPIDriver * const spip) {
uint32_t fd;
uint32_t sr;
while (spip->rxcnt) {
sr = spip->SPI->SR;
if ((sr & SPI_SR_RXBNE) == 0)
return;
fd = spip->SPI->DR;
if (spip->rxptr) {
*spip->rxptr++ = fd & 0xff;
}
spip->rxcnt--;
}
}
static void spi_lld_tx(SPIDriver * const spip) {
uint32_t fd;
uint32_t sr;
while (spip->txcnt) {
sr = spip->SPI->SR;
if ((sr & SPI_SR_TXBE) == 0)
return;
if (spip->txptr) {
fd = *spip->txptr++;
} else {
fd = '\xff';
}
spip->SPI->DR = fd;
spip->txcnt--;
}
}
static void spi_lld_handler(SPIDriver * const spip) {
//uint32_t sr = spip->SPI->SR; // & ((1U<<8)|spip->SPI->IER);
spi_lld_rx(spip);
spi_lld_tx(spip);
if (spip->rxcnt == 0) {
spip->SPI->IER = 0;
_spi_isr_code(spip);
}
}
#endif
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
#if (HT32_SPI_USE_SPI0 == TRUE) || defined(__DOXYGEN__)
OSAL_IRQ_HANDLER(HT32_SPI0_IRQ_VECTOR) {
OSAL_IRQ_PROLOGUE();
spi_lld_handler(&SPID0);
OSAL_IRQ_EPILOGUE();
}
#endif
#if (HT32_SPI_USE_SPI1 == TRUE) || defined(__DOXYGEN__)
OSAL_IRQ_HANDLER(HT32_SPI1_IRQ_VECTOR) {
OSAL_IRQ_PROLOGUE();
spi_lld_handler(&SPID1);
OSAL_IRQ_EPILOGUE();
}
#endif
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level SPI driver initialization.
*
* @notapi
*/
void spi_lld_init(void) {
/* Driver initialization.*/
#if HT32_SPI_USE_SPI0 == TRUE
spiObjectInit(&SPID0);
SPID0.SPI = SPI0;
// CKCU->APBCCR0 |= CKCU_APBCCR0_SPI0EN;
#endif
#if HT32_SPI_USE_SPI1 == TRUE
spiObjectInit(&SPID1);
SPID1.SPI = SPI1;
// CKCU->APBCCR0 |= CKCU_APBCCR0_SPI1EN;
#endif
}
/**
* @brief Configures and activates the SPI peripheral.
*
* @param[in] spip pointer to the @p SPIDriver object
*
* @notapi
*/
void spi_lld_start(SPIDriver *spip) {
if (spip->state == SPI_STOP) {
/* Enables the peripheral.*/
#if HT32_SPI_USE_SPI0 == TRUE
if (&SPID0 == spip) {
CKCU->APBCCR0 |= CKCU_APBCCR0_SPI0EN;
nvicEnableVector(SPI0_IRQn, HT32_SPI0_IRQ_PRIORITY);
}
#endif
#if HT32_SPI_USE_SPI1 == TRUE
if (&SPID1 == spip) {
CKCU->APBCCR0 |= CKCU_APBCCR0_SPI1EN;
nvicEnableVector(SPI1_IRQn, HT32_SPI1_IRQ_PRIORITY);
}
#endif
}
/* Configures the peripheral.*/
spip->SPI->CR0 = spip->config->cr0;
spip->SPI->CR1 = spip->config->cr1;
spip->SPI->CPR = spip->config->cpr;
//spip->SPI->FCR = 0; //SPI_FCR_FIFOEN | (1U << 4) | (1U << 0);
spip->SPI->FCR = spip->config->fcr;
spip->SPI->CR0 |= SPI_CR0_SPIEN;
}
/**
* @brief Deactivates the SPI peripheral.
*
* @param[in] spip pointer to the @p SPIDriver object
*
* @notapi
*/
void spi_lld_stop(SPIDriver *spip) {
if (spip->state == SPI_READY) {
/* Disables the peripheral.*/
#if HT32_SPI_USE_SPI0 == TRUE
if (&SPID0 == spip) {
RSTCU->APBPRSTR0 = RSTCU_APBPRSTR0_SPI0RST;
CKCU->APBCCR0 &= ~CKCU_APBCCR0_SPI0EN;
nvicDisableVector(SPI0_IRQn);
}
#endif
#if HT32_SPI_USE_SPI1 == TRUE
if (&SPID1 == spip) {
RSTCU->APBPRSTR0 = RSTCU_APBPRSTR0_SPI1RST;
CKCU->APBCCR0 &= ~CKCU_APBCCR0_SPI1EN;
nvicDisableVector(SPI1_IRQn);
}
#endif
}
}
/**
* @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) {
spip->SPI->CR0 |= SPI_CR0_SSELC;
}
/**
* @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) {
spip->SPI->CR0 &= ~SPI_CR0_SSELC;
}
/**
* @brief Ignores data on the SPI bus.
* @details This asynchronous function starts the transmission of a series of
* idle words on the SPI bus and ignores the received data.
* @post At the end of the operation the configured callback is invoked.
*
* @param[in] spip pointer to the @p SPIDriver object
* @param[in] n number of words to be ignored
*
* @notapi
*/
void spi_lld_ignore(SPIDriver *spip, size_t n) {
spi_lld_exchange(spip, n, NULL, NULL);
}
/**
* @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
*
* @notapi
*/
void spi_lld_exchange(SPIDriver *spip, size_t n,
const void *txbuf, void *rxbuf) {
spip->txptr = txbuf;
spip->rxptr = rxbuf;
spip->rxcnt = spip->txcnt = n;
spip->SPI->IER = SPI_IER_RXBNEIEN | SPI_IER_TXBEIEN;
}
/**
* @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
*
* @notapi
*/
void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) {
spi_lld_exchange(spip, n, txbuf, NULL);
}
/**
* @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
*
* @notapi
*/
void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) {
spi_lld_exchange(spip, n, NULL, rxbuf);
}
/**
* @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->DR = frame;
while((spip->SPI->SR & SPI_SR_RXBNE) == 0);
return (spip->SPI->DR & 0xffff);
}
#endif /* HAL_USE_SPI == TRUE */
/** @} */

View File

@ -0,0 +1,120 @@
/*
Copyright (C) 2020 Yaotian Feng
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 hal_spi_lld.h
* @brief HT32 SPI subsystem low level driver header.
*
* @addtogroup SPI
* @{
*/
#ifndef HAL_SPI_LLD_H
#define HAL_SPI_LLD_H
#if HAL_USE_SPI || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name HT32 configuration options
* @{
*/
/**
* @brief SPI0 driver enable switch.
* @details If set to @p TRUE the support for SPI0 is included.
* @note The default is @p FALSE.
*/
#if !defined(HT32_SPI_USE_SPI0) || defined(__DOXYGEN__)
#define HT32_SPI_USE_SPI0 FALSE
#endif
#if !defined(HT32_SPI_USE_SPI1) || defined(__DOXYGEN__)
#define HT32_SPI_USE_SPI1 FALSE
#endif
/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief Low Level fields of the SPI driver structure.
*/
#define spi_lld_driver_fields \
SPI_TypeDef *SPI; \
uint8_t *rxptr; \
const uint8_t *txptr; \
size_t rxcnt; \
size_t txcnt; \
/**
* @brief Low Level fields of the SPI configuration structure.
*/
#define spi_lld_config_fields \
uint32_t cr0; \
uint32_t cr1; \
uint32_t cpr; \
uint32_t fcr;
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#if (HT32_SPI_USE_SPI0 == TRUE) && !defined(__DOXYGEN__)
extern SPIDriver SPID0;
#endif
#if (HT32_SPI_USE_SPI1 == TRUE) && !defined(__DOXYGEN__)
extern SPIDriver SPID1;
#endif
#ifdef __cplusplus
extern "C" {
#endif
void spi_lld_init(void);
void spi_lld_start(SPIDriver *spip);
void spi_lld_stop(SPIDriver *spip);
void spi_lld_select(SPIDriver *spip);
void spi_lld_unselect(SPIDriver *spip);
void spi_lld_ignore(SPIDriver *spip, size_t n);
void spi_lld_exchange(SPIDriver *spip, size_t n,
const void *txbuf, void *rxbuf);
void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf);
void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf);
uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame);
#ifdef __cplusplus
}
#endif
#endif /* HAL_USE_SPI == TRUE */
#endif /* HAL_SPI_LLD_H */
/** @} */

View File

@ -0,0 +1,15 @@
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/HT32/LLD/TIMv1/hal_st_lld.c
ifeq ($(USE_SMART_BUILD),yes)
ifneq ($(findstring HAL_USE_GPT TRUE,$(HALCONF)),)
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/HT32/LLD/TIMv1/hal_gpt_lld.c
endif
ifneq ($(findstring HAL_USE_PWM TRUE,$(HALCONF)),)
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/HT32/LLD/TIMv1/hal_pwm_lld.c
endif
else
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/HT32/LLD/TIMv1/hal_gpt_lld.c
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/HT32/LLD/TIMv1/hal_pwm_lld.c
endif
PLATFORMINC += $(CHIBIOS_CONTRIB)/os/hal/ports/HT32/LLD/TIMv1

View File

@ -0,0 +1,213 @@
/*
Copyright (C) 2020 Yaotian Feng
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 hal_gpt_lld.c
* @brief PLATFORM GPT subsystem low level driver source.
*
* @addtogroup GPT
* @{
*/
#include "hal.h"
#if (HAL_USE_GPT == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/**
* @brief GPTD1 driver identifier.
*/
#if (HT32_GPT_USE_BFTM0 == TRUE) || defined(__DOXYGEN__)
GPTDriver GPTD_BFTM0;
#endif
#if (HT32_GPT_USE_BFTM1 == TRUE) || defined(__DOXYGEN__)
GPTDriver GPTD_BFTM1;
#endif
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
static void gpt_lld_handler(GPTDriver *gptp) {
if(gptp->BFTM->SR & BFTM_SR_MIF){
gptp->BFTM->SR = 0;
if(gptp->config->callback)
gptp->config->callback(gptp);
}
}
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
#if (HT32_GPT_USE_BFTM0 == TRUE) || defined(__DOXYGEN__)
#ifndef HT32_BFTM0_IRQ_VECTOR
#error "HT32_BFTM0_IRQ_VECTOR is not defined"
#endif
OSAL_IRQ_HANDLER(HT32_BFTM0_IRQ_VECTOR) {
OSAL_IRQ_PROLOGUE();
gpt_lld_handler(&GPTD_BFTM0);
OSAL_IRQ_EPILOGUE();
}
#endif
#if (HT32_GPT_USE_BFTM1 == TRUE) || defined(__DOXYGEN__)
OSAL_IRQ_HANDLER(HT32_BFTM1_IRQ_VECTOR) {
OSAL_IRQ_PROLOGUE();
gpt_lld_handler(&GPTD_BFTM1);
OSAL_IRQ_EPILOGUE();
}
#endif
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level GPT driver initialization.
*
* @notapi
*/
void gpt_lld_init(void) {
/* Driver initialization.*/
#if HT32_GPT_USE_BFTM0 == TRUE
gptObjectInit(&GPTD_BFTM0);
GPTD_BFTM0.BFTM = BFTM0;
#endif
#if HT32_GPT_USE_BFTM1 == TRUE
gptObjectInit(&GPTD_BFTM1);
GPTD_BFTM0.BFTM = BFTM1;
#endif
}
/**
* @brief Configures and activates the GPT peripheral.
*
* @param[in] gptp pointer to the @p GPTDriver object
*
* @notapi
*/
void gpt_lld_start(GPTDriver *gptp) {
if (gptp->state == GPT_STOP) {
/* Enables the peripheral.*/
#if HT32_GPT_USE_BFTM0 == TRUE
if (&GPTD_BFTM0 == gptp) {
CKCU->APBCCR1 |= CKCU_APBCCR1_BFTM0EN;
nvicEnableVector(BFTM0_IRQn, HT32_GPT_BFTM0_IRQ_PRIORITY);
}
#endif
#if HT32_GPT_USE_BFTM1 == TRUE
if (&GPTD_BFTM1 == gptp) {
CKCU->APBCCR1 |= CKCU_APBCCR1_BFTM1EN;
nvicEnableVector(BFTM1_IRQn, HT32_GPT_BFTM1_IRQ_PRIORITY);
}
#endif
}
/* Configures the peripheral.*/
gptp->BFTM->CR = 0;
// counter frequency depends on the AHB clock, we can't
// change anything here
}
/**
* @brief Deactivates the GPT peripheral.
*
* @param[in] gptp pointer to the @p GPTDriver object
*
* @notapi
*/
void gpt_lld_stop(GPTDriver *gptp) {
if (gptp->state == GPT_READY) {
/* Resets the peripheral.*/
/* Disables the peripheral.*/
#if HT32_GPT_USE_BFTM0 == TRUE
if (&GPTD_BFTM0 == gptp) {
RSTCU->APBPRSTR1 = RSTCU_APBPRSTR1_BFTM0RST;
CKCU->APBCCR1 &= ~CKCU_APBCCR1_BFTM0EN;
nvicDisableVector(BFTM0_IRQn);
}
#endif
#if HT32_GPT_USE_BFTM1 == TRUE
if (&GPTD_BFTM1 == gptp) {
RSTCU->APBPRSTR1 = RSTCU_APBPRSTR1_BFTM1RST;
CKCU->APBCCR1 &= ~CKCU_APBCCR1_BFTM1EN;
nvicDisableVector(BFTM1_IRQn);
}
#endif
}
}
/**
* @brief Starts the timer in continuous mode.
*
* @param[in] gptp pointer to the @p GPTDriver object
* @param[in] interval period in ticks
*
* @notapi
*/
void gpt_lld_start_timer(GPTDriver *gptp, gptcnt_t interval) {
gptp->BFTM->SR = 0;
gptp->BFTM->CNTR = 0;
gptp->BFTM->CMP = (HT32_CK_AHB_FREQUENCY / gptp->config->frequency) * interval;
gptp->BFTM->CR = BFTM_CR_CEN | BFTM_CR_MIEN;
}
/**
* @brief Stops the timer.
*
* @param[in] gptp pointer to the @p GPTDriver object
*
* @notapi
*/
void gpt_lld_stop_timer(GPTDriver *gptp) {
gptp->BFTM->CR = 0;
}
/**
* @brief Starts the timer in one shot mode and waits for completion.
* @details This function specifically polls the timer waiting for completion
* in order to not have extra delays caused by interrupt servicing,
* this function is only recommended for short delays.
*
* @param[in] gptp pointer to the @p GPTDriver object
* @param[in] interval time interval in ticks
*
* @notapi
*/
void gpt_lld_polled_delay(GPTDriver *gptp, gptcnt_t interval) {
gptp->BFTM->SR = 0;
gptp->BFTM->CNTR = 0;
gptp->BFTM->CMP = (HT32_CK_AHB_FREQUENCY / gptp->config->frequency) * interval;
gptp->BFTM->CR = BFTM_CR_CEN | BFTM_CR_OSM;
while(!(gptp->BFTM->SR & BFTM_SR_MIF));
}
#endif /* HAL_USE_GPT == TRUE */
/** @} */

View File

@ -0,0 +1,195 @@
/*
Copyright (C) 2020 Yaotian Feng
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 hal_gpt_lld.h
* @brief PLATFORM GPT subsystem low level driver header.
*
* @addtogroup GPT
* @{
*/
#ifndef HAL_GPT_LLD_H
#define HAL_GPT_LLD_H
#if (HAL_USE_GPT == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name PLATFORM configuration options
* @{
*/
/**
* @brief GPTD1 driver enable switch.
* @details If set to @p TRUE the support for GPTD1 is included.
* @note The default is @p FALSE.
*/
#if !defined(HT32_GPT_USE_BFTM0) || defined(__DOXYGEN__)
#define HT32_GPT_USE_BFTM0 FALSE
#endif
#if !defined(HT32_GPT_USE_BFTM1) || defined(__DOXYGEN__)
#define HT32_GPT_USE_BFTM1 FALSE
#endif
/**
* @brief GPTD1 interrupt priority level setting.
*/
#if !defined(HT32_GPT_BFTM0_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define HT32_GPT_BFTM0_IRQ_PRIORITY 7
#endif
#if !defined(HT32_GPT_BFTM1_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define HT32_GPT_BFTM1_IRQ_PRIORITY 7
#endif
/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief GPT frequency type.
*/
typedef uint32_t gptfreq_t;
/**
* @brief GPT counter type.
*/
typedef uint16_t gptcnt_t;
/**
* @brief Driver configuration structure.
* @note It could be empty on some architectures.
*/
typedef struct {
/**
* @brief Timer clock in Hz.
* @note The low level can use assertions in order to catch invalid
* frequency specifications.
*/
gptfreq_t frequency;
/**
* @brief Timer callback pointer.
* @note This callback is invoked on GPT counter events.
*/
gptcallback_t callback;
/* End of the mandatory fields.*/
} GPTConfig;
/**
* @brief Structure representing a GPT driver.
*/
struct GPTDriver {
/**
* @brief Driver state.
*/
gptstate_t state;
/**
* @brief Current configuration data.
*/
const GPTConfig *config;
#if defined(GPT_DRIVER_EXT_FIELDS)
GPT_DRIVER_EXT_FIELDS
#endif
/* End of the mandatory fields.*/
BFTM_TypeDef *BFTM;
};
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/**
* @brief Changes the interval of GPT peripheral.
* @details This function changes the interval of a running GPT unit.
* @pre The GPT unit must have been activated using @p gptStart().
* @pre The GPT unit must have been running in continuous mode using
* @p gptStartContinuous().
* @post The GPT unit interval is changed to the new value.
* @note The function has effect at the next cycle start.
*
* @param[in] gptp pointer to a @p GPTDriver object
* @param[in] interval new cycle time in timer ticks
* @notapi
*/
#define gpt_lld_change_interval(gptp, interval) \
((gptp)->BFTM->CMP = (HT32_CK_AHB_FREQUENCY / (gptp)->config->frequency) * (interval))
/**
* @brief Returns the interval of GPT peripheral.
* @pre The GPT unit must be running in continuous mode.
*
* @param[in] gptp pointer to a @p GPTDriver object
* @return The current interval.
* @notapi
*/
#define gpt_lld_get_interval(gptp) \
((gptcnt_t)(gptp)->BFTM->CMP / (HT32_CK_AHB_FREQUENCY / (gptp)->config->frequency))
/**
* @brief Returns the counter value of GPT peripheral.
* @pre The GPT unit must be running in continuous mode.
* @note The nature of the counter is not defined, it may count upward
* or downward, it could be continuously running or not.
*
* @param[in] gptp pointer to a @p GPTDriver object
* @return The current counter value.
* @notapi
*/
#define gpt_lld_get_counter(gptp) \
((gptcnt_t)((gptp)->BFTM->CNTR / (HT32_CK_AHB_FREQUENCY / (gptp)->config->frequency)))
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#if (HT32_GPT_USE_BFTM0 == TRUE) && !defined(__DOXYGEN__)
extern GPTDriver GPTD_BFTM0;
#endif
#if (HT32_GPT_USE_BFTM1 == TRUE) && !defined(__DOXYGEN__)
extern GPTDriver GPTD_BFTM1;
#endif
#ifdef __cplusplus
extern "C" {
#endif
void gpt_lld_init(void);
void gpt_lld_start(GPTDriver *gptp);
void gpt_lld_stop(GPTDriver *gptp);
void gpt_lld_start_timer(GPTDriver *gptp, gptcnt_t interval);
void gpt_lld_stop_timer(GPTDriver *gptp);
void gpt_lld_polled_delay(GPTDriver *gptp, gptcnt_t interval);
#ifdef __cplusplus
}
#endif
#endif /* HAL_USE_GPT == TRUE */
#endif /* HAL_GPT_LLD_H */
/** @} */

View File

@ -0,0 +1,300 @@
/*
Copyright (C) 2020 Yaotian Feng
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 hal_pwm_lld.c
* @brief HT32 PWM subsystem low level driver source.
*
* @addtogroup PWM
* @{
*/
#include "hal.h"
#if (HAL_USE_PWM == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/**
* @brief PWMD0 driver identifier.
* @note The driver PWMD0 allocates the complex timer XXX when enabled.
*/
#if (HT32_PWM_USE_MCTM0 == TRUE) || defined(__DOXYGEN__)
PWMDriver PWMD_MCTM0;
#endif
#if (HT32_PWM_USE_MCTM1 == TRUE) || defined(__DOXYGEN__)
PWMDriver PWMD_MCTM1;
#endif
#if (HT32_PWM_USE_GPTM0 == TRUE) || defined(__DOXYGEN__)
PWMDriver PWMD_GPTM0;
#endif
#if (HT32_PWM_USE_GPTM1 == TRUE) || defined(__DOXYGEN__)
PWMDriver PWMD_GPTM1;
#endif
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level PWM driver initialization.
*
* @notapi
*/
void pwm_lld_init(void) {
#if HT32_PWM_USE_MCTM0 == TRUE
/* Driver initialization.*/
pwmObjectInit(&PWMD_MCTM0);
#endif
#if HT32_PWM_USE_MCTM1 == TRUE
pwmObjectInit(&PWMD_MCTM1);
#endif
#if HT32_PWM_USE_GPTM0 == TRUE
pwmObjectInit(&PWMD_GPTM0);
#endif
#if HT32_PWM_USE_GPTM1 == TRUE
pwmObjectInit(&PWMD_GPTM1);
#endif
}
/**
* @brief Configures and activates the PWM peripheral.
* @note Starting a driver that is already in the @p PWM_READY state
* disables all the active channels.
*
* @param[in] pwmp pointer to a @p PWMDriver object
*
* @notapi
*/
void pwm_lld_start(PWMDriver *pwmp) {
if (pwmp->state == PWM_STOP) {
/* Clock activation and timer reset.*/
#if HT32_PWM_USE_MCTM0 == TRUE
if (&PWMD_MCTM0 == pwmp) {
CKCU->APBCCR1 |= CKCU_APBCCR1_MCTM0EN;
pwmp->TM = MCTM0;
}
#endif
#if HT32_PWM_USE_MCTM1 == TRUE
if (&PWMD_MCTM1 == pwmp) {
CKCU->APBCCR1 |= CKCU_APBCCR1_MCTM1EN;
pwmp->TM = MCTM1;
}
#endif
#if HT32_PWM_USE_GPTM0 == TRUE
if (&PWMD_GPTM0 == pwmp) {
CKCU->APBCCR1 |= CKCU_APBCCR1_GPTM0EN;
pwmp->TM = GPTM0;
}
#endif
#if HT32_PWM_USE_GPTM1 == TRUE
if (&PWMD_GPTM1 == pwmp) {
CKCU->APBCCR1 |= CKCU_APBCCR1_GPTM1EN;
pwmp->TM = GPTM1;
}
#endif
}
pwmp->TM->CNTCFR = TM_CNTCFR_CMSEL_MODE_0;
pwmp->TM->PSCR = (HT32_CK_AHB_FREQUENCY / pwmp->config->frequency) - 1;
pwmp->TM->CRR = pwmp->config->period;
pwmp->TM->CNTR = 0;
pwmp->TM->CTR = TM_CTR_TME;
pwmp->TM->CHCTR = 0;
#if (HT32_PWM_USE_MCTM0 == TRUE) || (HT32_PWM_USE_MCTM1 == TRUE)
if (pwmp->TM == MCTM0 || pwmp->TM == MCTM1)
pwmp->TM->CHBRKCTR = TM_CHBRKCTR_CHMOE;
#endif
for (size_t channel = 0; channel < PWM_CHANNELS; channel++) {
switch (pwmp->config->channels[channel].mode & PWM_OUTPUT_MASK) {
case PWM_OUTPUT_DISABLED:
break;
case PWM_OUTPUT_ACTIVE_HIGH:
pwmp->TM->CHPOLR &= ~(1U << (2*channel));
break;
case PWM_OUTPUT_ACTIVE_LOW:
pwmp->TM->CHPOLR |= 1U << (2*channel);
break;
default:
break;
}
pwmp->TM->CHnOCFR[channel] = TM_CHnOCFR_CHnPRE|TM_CHnOCFR_CHnOM(6);
}
}
/**
* @brief Deactivates the PWM peripheral.
*
* @param[in] pwmp pointer to a @p PWMDriver object
*
* @notapi
*/
void pwm_lld_stop(PWMDriver *pwmp) {
/* If in ready state then disables the PWM clock.*/
if (pwmp->state == PWM_READY) {
#if HT32_PWM_USE_MCTM0 == TRUE
if (&PWMD_MCTM0 == pwmp) {
CKCU->APBCCR1 &= ~CKCU_APBCCR1_MCTM0EN;
}
#endif
#if HT32_PWM_USE_MCTM1 == TRUE
if (&PWMD_MCTM1 == pwmp) {
CKCU->APBCCR1 &= ~CKCU_APBCCR1_MCTM1EN;
}
#endif
#if HT32_PWM_USE_GPTM0 == TRUE
if (&PWMD_GPTM0 == pwmp) {
CKCU->APBCCR1 &= ~CKCU_APBCCR1_GPTM0EN;
}
#endif
#if HT32_PWM_USE_GPTM1 == TRUE
if (&PWMD_GPTM1 == pwmp) {
CKCU->APBCCR1 &= ~CKCU_APBCCR1_GPTM1EN;
}
#endif
}
}
/**
* @brief Enables a PWM channel.
* @pre The PWM unit must have been activated using @p pwmStart().
* @post The channel is active using the specified configuration.
* @note The function has effect at the next cycle start.
* @note Channel notification is not enabled.
*
* @param[in] pwmp pointer to a @p PWMDriver object
* @param[in] channel PWM channel identifier (0...channels-1)
* @param[in] width PWM pulse width as clock pulses number
*
* @notapi
*/
void pwm_lld_enable_channel(PWMDriver *pwmp,
pwmchannel_t channel,
pwmcnt_t width) {
pwmp->TM->CHnCCR[channel] = width;
pwmp->TM->CHCTR |= 1U << (2*channel);
}
/**
* @brief Disables a PWM channel and its notification.
* @pre The PWM unit must have been activated using @p pwmStart().
* @post The channel is disabled and its output line returned to the
* idle state.
* @note The function has effect at the next cycle start.
*
* @param[in] pwmp pointer to a @p PWMDriver object
* @param[in] channel PWM channel identifier (0...channels-1)
*
* @notapi
*/
void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel) {
pwmp->TM->CHCTR &= ~(1U << (2*channel));
}
/**
* @brief Enables the periodic activation edge notification.
* @pre The PWM unit must have been activated using @p pwmStart().
* @note If the notification is already enabled then the call has no effect.
*
* @param[in] pwmp pointer to a @p PWMDriver object
*
* @notapi
*/
void pwm_lld_enable_periodic_notification(PWMDriver *pwmp) {
(void)pwmp;
}
/**
* @brief Disables the periodic activation edge notification.
* @pre The PWM unit must have been activated using @p pwmStart().
* @note If the notification is already disabled then the call has no effect.
*
* @param[in] pwmp pointer to a @p PWMDriver object
*
* @notapi
*/
void pwm_lld_disable_periodic_notification(PWMDriver *pwmp) {
(void)pwmp;
}
/**
* @brief Enables a channel de-activation edge notification.
* @pre The PWM unit must have been activated using @p pwmStart().
* @pre The channel must have been activated using @p pwmEnableChannel().
* @note If the notification is already enabled then the call has no effect.
*
* @param[in] pwmp pointer to a @p PWMDriver object
* @param[in] channel PWM channel identifier (0...channels-1)
*
* @notapi
*/
void pwm_lld_enable_channel_notification(PWMDriver *pwmp,
pwmchannel_t channel) {
(void)pwmp;
(void)channel;
}
/**
* @brief Disables a channel de-activation edge notification.
* @pre The PWM unit must have been activated using @p pwmStart().
* @pre The channel must have been activated using @p pwmEnableChannel().
* @note If the notification is already disabled then the call has no effect.
*
* @param[in] pwmp pointer to a @p PWMDriver object
* @param[in] channel PWM channel identifier (0...channels-1)
*
* @notapi
*/
void pwm_lld_disable_channel_notification(PWMDriver *pwmp,
pwmchannel_t channel) {
(void)pwmp;
(void)channel;
}
#endif /* HAL_USE_PWM == TRUE */
/** @} */

View File

@ -0,0 +1,244 @@
/*
Copyright (C) 2020 Yaotian Feng
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 hal_pwm_lld.h
* @brief HT32 PWM subsystem low level driver header.
*
* @addtogroup PWM
* @{
*/
#ifndef HAL_PWM_LLD_H
#define HAL_PWM_LLD_H
#if (HAL_USE_PWM == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/**
* @brief Number of PWM channels per PWM driver.
*/
#define PWM_CHANNELS 4
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name HT32 configuration options
* @{
*/
/**
* @brief PWMD1 driver enable switch.
* @details If set to @p TRUE the support for PWM1 is included.
* @note The default is @p FALSE.
*/
#if !defined(HT32_PWM_USE_MCTM0) || defined(__DOXYGEN__)
#define HT32_PWM_USE_MCTM0 FALSE
#endif
#if !defined(HT32_PWM_USE_MCTM1) || defined(__DOXYGEN__)
#define HT32_PWM_USE_MCTM1 FALSE
#endif
#if !defined(HT32_PWM_USE_GPTM0) || defined(__DOXYGEN__)
#define HT32_PWM_USE_GPTM0 FALSE
#endif
#if !defined(HT32_PWM_USE_GPTM1) || defined(__DOXYGEN__)
#define HT32_PWM_USE_GPTM1 FALSE
#endif
/** @} */
/*===========================================================================*/
/* Configuration checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief Type of a PWM mode.
*/
typedef uint32_t pwmmode_t;
/**
* @brief Type of a PWM channel.
*/
typedef uint8_t pwmchannel_t;
/**
* @brief Type of a channels mask.
*/
typedef uint32_t pwmchnmsk_t;
/**
* @brief Type of a PWM counter.
*/
typedef uint32_t pwmcnt_t;
/**
* @brief Type of a PWM driver channel configuration structure.
*/
typedef struct {
/**
* @brief Channel active logic level.
*/
pwmmode_t mode;
/**
* @brief Channel callback pointer.
* @note This callback is invoked on the channel compare event. If set to
* @p NULL then the callback is disabled.
*/
pwmcallback_t callback;
/* End of the mandatory fields.*/
} PWMChannelConfig;
/**
* @brief Type of a PWM driver configuration structure.
*/
typedef struct {
/**
* @brief Timer clock in Hz.
* @note The low level can use assertions in order to catch invalid
* frequency specifications.
*/
uint32_t frequency;
/**
* @brief PWM period in ticks.
* @note The low level can use assertions in order to catch invalid
* period specifications.
*/
pwmcnt_t period;
/**
* @brief Periodic callback pointer.
* @note This callback is invoked on PWM counter reset. If set to
* @p NULL then the callback is disabled.
*/
pwmcallback_t callback;
/**
* @brief Channels configurations.
*/
PWMChannelConfig channels[PWM_CHANNELS];
/* End of the mandatory fields.*/
} PWMConfig;
/**
* @brief Structure representing a PWM driver.
*/
struct PWMDriver {
/**
* @brief Driver state.
*/
pwmstate_t state;
/**
* @brief Current driver configuration data.
*/
const PWMConfig *config;
/**
* @brief Current PWM period in ticks.
*/
pwmcnt_t period;
/**
* @brief Mask of the enabled channels.
*/
pwmchnmsk_t enabled;
/**
* @brief Number of channels in this instance.
*/
pwmchannel_t channels;
#if defined(PWM_DRIVER_EXT_FIELDS)
PWM_DRIVER_EXT_FIELDS
#endif
/* End of the mandatory fields.*/
/**
* @brief Pointer to timer register block.
*/
TM_TypeDef *TM;
};
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/**
* @brief Changes the period the PWM peripheral.
* @details This function changes the period of a PWM unit that has already
* been activated using @p pwmStart().
* @pre The PWM unit must have been activated using @p pwmStart().
* @post The PWM unit period is changed to the new value.
* @note The function has effect at the next cycle start.
* @note If a period is specified that is shorter than the pulse width
* programmed in one of the channels then the behavior is not
* guaranteed.
*
* @param[in] pwmp pointer to a @p PWMDriver object
* @param[in] period new cycle time in ticks
*
* @notapi
*/
#define pwm_lld_change_period(pwmp, period) \
do { \
(pwmp)->TM->CRR = (period);\
} while (0)
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#if (HT32_PWM_USE_MCTM0 == TRUE) && !defined(__DOXYGEN__)
extern PWMDriver PWMD_MCTM0;
#endif
#if (HT32_PWM_USE_MCTM1 == TRUE) && !defined(__DOXYGEN__)
extern PWMDriver PWMD_MCTM1;
#endif
#if (HT32_PWM_USE_GPTM0 == TRUE) && !defined(__DOXYGEN__)
extern PWMDriver PWMD_GPTM0;
#endif
#if (HT32_PWM_USE_GPTM1 == TRUE) && !defined(__DOXYGEN__)
extern PWMDriver PWMD_GPTM1;
#endif
#ifdef __cplusplus
extern "C" {
#endif
void pwm_lld_init(void);
void pwm_lld_start(PWMDriver *pwmp);
void pwm_lld_stop(PWMDriver *pwmp);
void pwm_lld_enable_channel(PWMDriver *pwmp,
pwmchannel_t channel,
pwmcnt_t width);
void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel);
void pwm_lld_enable_periodic_notification(PWMDriver *pwmp);
void pwm_lld_disable_periodic_notification(PWMDriver *pwmp);
void pwm_lld_enable_channel_notification(PWMDriver *pwmp,
pwmchannel_t channel);
void pwm_lld_disable_channel_notification(PWMDriver *pwmp,
pwmchannel_t channel);
#ifdef __cplusplus
}
#endif
#endif /* HAL_USE_PWM == TRUE */
#endif /* HAL_PWM_LLD_H */
/** @} */

View File

@ -0,0 +1,104 @@
/*
Copyright (C) 2020 Yaotian Feng
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 hal_st_lld.c
* @brief PLATFORM ST subsystem low level driver source.
*
* @addtogroup ST
* @{
*/
#include "hal.h"
#if (OSAL_ST_MODE != OSAL_ST_MODE_NONE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
#if (OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC) || defined(__DOXYGEN__)
/**
* @brief System Timer vector.
* @details This interrupt is used for system tick in periodic mode.
*
* @isr
*/
OSAL_IRQ_HANDLER(SysTick_Handler) {
OSAL_IRQ_PROLOGUE();
osalSysLockFromISR();
osalOsTimerHandlerI();
osalSysUnlockFromISR();
OSAL_IRQ_EPILOGUE();
}
#endif /* OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC */
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level ST driver initialization.
*
* @notapi
*/
void st_lld_init(void) {
#if OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC
/* Periodic systick mode, the Cortex-Mx internal systick timer is used
in this mode.*/
#if defined(HT32_ST_USE_HCLK)
SysTick->LOAD = (HT32_HCLK_FREQUENCY / OSAL_ST_FREQUENCY) - 1;
#else
SysTick->LOAD = (HT32_STCLK_FREQUENCY / OSAL_ST_FREQUENCY) - 1;
#endif
SysTick->VAL = 0;
SysTick->CTRL =
#if defined(HT32_ST_USE_HCLK)
SysTick_CTRL_CLKSOURCE_Msk |
#endif
SysTick_CTRL_ENABLE_Msk |
SysTick_CTRL_TICKINT_Msk;
/* IRQ enabled.*/
nvicSetSystemHandlerPriority(HANDLER_SYSTICK, HT32_ST_IRQ_PRIORITY);
#endif /* OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC */
}
#endif /* OSAL_ST_MODE != OSAL_ST_MODE_NONE */
/** @} */

View File

@ -0,0 +1,159 @@
/*
Copyright (C) 2020 Yaotian Feng
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 SYST_RVRthe License.
*/
/**
* @file hal_st_lld.h
* @brief PLATFORM ST subsystem low level driver header.
* @details This header is designed to be include-able without having to
* include other files from the HAL.
*
* @addtogroup ST
* @{
*/
#ifndef HAL_ST_LLD_H
#define HAL_ST_LLD_H
#include "mcuconf.h"
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name Configuration options
* @{
*/
/**
* @brief SysTick timer IRQ priority.
*/
#if !defined(HT32_ST_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define HT32_ST_IRQ_PRIORITY 8
#endif
/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
#if (OSAL_ST_MODE != OSAL_ST_MODE_NONE) && (OSAL_ST_MODE != OSAL_ST_MODE_PERIODIC)
#error Only OSAL_ST_MODE_PERIODIC is supported
#endif
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
void st_lld_init(void);
#ifdef __cplusplus
}
#endif
/*===========================================================================*/
/* Driver inline functions. */
/*===========================================================================*/
#define SYST_CSR (*((volatile uint32_t*)0xE000E010))
#define SYST_RVR (*((volatile uint32_t*)0xE000E014))
#define SYST_CVR (*((volatile uint32_t*)0xE000E018))
#define SYST_CALIB (*((volatile uint32_t*)0xE000E01C))
/**
* @brief Returns the time counter value.
*
* @return The counter value.
*
* @notapi
*/
static inline systime_t st_lld_get_counter(void) {
return (systime_t) SYST_CVR;
}
/**
* @brief Starts the alarm.
* @note Makes sure that no spurious alarms are triggered after
* this call.
*
* @param[in] abstime the time to be set for the first alarm
*
* @notapi
*/
static inline void st_lld_start_alarm(systime_t abstime) {
SYST_RVR = (uint32_t)abstime;
SYST_CSR = 0b111;
SYST_CVR = 0; // Trigger reload
}
/**
* @brief Stops the alarm interrupt.
*
* @notapi
*/
static inline void st_lld_stop_alarm(void) {
SYST_CVR &= ~((uint32_t)0b10);
}
/**
* @brief Sets the alarm time.
*
* @param[in] abstime the time to be set for the next alarm
*
* @notapi
*/
static inline void st_lld_set_alarm(systime_t abstime) {
SYST_RVR = (uint32_t)abstime;
}
/**
* @brief Returns the current alarm time.
*
* @return The currently set alarm time.
*
* @notapi
*/
static inline systime_t st_lld_get_alarm(void) {
return (systime_t)SYST_RVR;
}
/**
* @brief Determines if the alarm is active.
*
* @return The alarm status.
* @retval false if the alarm is not active.
* @retval true is the alarm is active
*
* @notapi
*/
static inline bool st_lld_is_alarm_active(void) {
return ((SYST_CVR & 0b10) != 0);
}
#endif /* HAL_ST_LLD_H */
/** @} */

View File

@ -0,0 +1,13 @@
ifeq ($(USE_SMART_BUILD),yes)
ifneq ($(findstring HAL_USE_SERIAL TRUE,$(HALCONF)),)
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/HT32/LLD/USART_F165x/hal_serial_lld.c
endif
ifneq ($(findstring HAL_USE_UART TRUE,$(HALCONF)),)
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/HT32/LLD/USART_F165x/hal_uart_lld.c
endif
else
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/HT32/LLD/USART_F165x/hal_serial_lld.c
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/HT32/LLD/USART_F165x/hal_uart_lld.c
endif
PLATFORMINC += $(CHIBIOS_CONTRIB)/os/hal/ports/HT32/LLD/USART_F165x

View File

@ -0,0 +1,245 @@
/*
Copyright (C) 2020 Yaotian Feng
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 hal_serial_lld.c
* @brief HT32 serial subsystem low level driver source.
*
* @addtogroup SERIAL
* @{
*/
#include "hal.h"
#if (HAL_USE_SERIAL == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/** @brief USART0 serial driver identifier.*/
#if (HT32_SERIAL_USE_USART0 == TRUE) || defined(__DOXYGEN__)
SerialDriver SD0;
#endif
#if (HT32_SERIAL_USE_USART1 == TRUE) || defined(__DOXYGEN__)
SerialDriver SD1;
#endif
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/**
* @brief Driver default configuration.
*/
static const SerialConfig default_config = {
SERIAL_DEFAULT_BITRATE
};
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
static void load(SerialDriver *sdp)
{
USART_TypeDef *u = sdp->usart;
#define TFTLIE (1U << 1)
u->IER |= TFTLIE;
}
#if HT32_SERIAL_USE_USART0 == TRUE
static void notify0(io_queue_t *qp)
{
(void)qp;
load(&SD0);
}
#endif
#if HT32_SERIAL_USE_USART1 == TRUE
static void notify1(io_queue_t *qp)
{
(void)qp;
load(&SD1);
}
#endif
static void serial_interrupt(SerialDriver *sdp)
{
USART_TypeDef *u = sdp->usart;
while ((u->IIR & 1) == 0) {
switch ((u->IIR >> 1) & 7) {
case 0:
/* modem status */
break;
case 1:
/* TX FIFO level */
{
do {
msg_t b;
osalSysLockFromISR();
b = oqGetI(&sdp->oqueue);
osalSysUnlockFromISR();
if (b < MSG_OK) {
u->IER &= ~TFTLIE;
osalSysLockFromISR();
chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
osalSysUnlockFromISR();
break;
}
u->TBR = b;
} while (0);
}
break;
case 2:
/* RX FIFO level */
case 6:
/* RX FIFO timeout */
osalSysLockFromISR();
if (iqIsEmptyI(&sdp->iqueue))
chnAddFlagsI(sdp, CHN_INPUT_AVAILABLE);
osalSysUnlockFromISR();
while ((u->LSR & 1) != 0) {
osalSysLockFromISR();
if (iqPutI(&sdp->iqueue, u->RBR) < MSG_OK)
chnAddFlagsI(sdp, SD_OVERRUN_ERROR);
osalSysUnlockFromISR();
}
break;
case 3:
/* RX line status */
break;
}
}
}
static void usart_init(SerialDriver *sdp, const SerialConfig *config)
{
USART_TypeDef *u = sdp->usart;
u->DLR = (uint32_t)(HT32_CK_USART_FREQUENCY / config->speed); /* XXX */
u->LCR = 0x01; /* 8-bit, one stop, no parity */
u->FCR = 0x301;
}
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
#if HT32_SERIAL_USE_USART0 == TRUE
CH_IRQ_HANDLER(HT32_USART0_IRQ_VECTOR) {
CH_IRQ_PROLOGUE();
serial_interrupt(&SD0);
CH_IRQ_EPILOGUE();
}
#endif
#if HT32_SERIAL_USE_USART1 == TRUE
CH_IRQ_HANDLER(HT32_USART1_IRQ_VECTOR) {
CH_IRQ_PROLOGUE();
serial_interrupt(&SD1);
CH_IRQ_EPILOGUE();
}
#endif
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level serial driver initialization.
*
* @notapi
*/
void sd_lld_init(void) {
#if HT32_SERIAL_USE_USART0 == TRUE
sdObjectInit(&SD0, NULL, notify0);
SD0.usart = USART0;
#endif
#if HT32_SERIAL_USE_USART1 == TRUE
sdObjectInit(&SD1, NULL, notify1);
SD1.usart = USART1;
#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 HT32_SERIAL_USE_USART0 == TRUE
if (&SD0 == sdp) {
CKCU->APBCCR0 |= (1U << 8);
nvicEnableVector(USART0_IRQn, HT32_USART0_IRQ_PRIORITY);
}
#endif
#if HT32_SERIAL_USE_USART1 == TRUE
if (&SD1 == sdp) {
CKCU->APBCCR0 |= (1U << 9);
nvicEnableVector(USART1_IRQn, HT32_USART1_IRQ_PRIORITY);
}
#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) {
#if PLATFORM_SERIAL_USE_USART0 == TRUE
if (&SD0 == sdp) {
}
#endif
#if PLATFORM_SERIAL_USE_USART1 == TRUE
if (&SD1 == sdp) {
}
#endif
}
}
#endif /* HAL_USE_SERIAL == TRUE */
/** @} */

View File

@ -0,0 +1,127 @@
/*
Copyright (C) 2020 Yaotian Feng
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 hal_serial_lld.h
* @brief PLATFORM serial subsystem low level driver header.
*
* @addtogroup SERIAL
* @{
*/
#ifndef HAL_SERIAL_LLD_H
#define HAL_SERIAL_LLD_H
#if (HAL_USE_SERIAL == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name PLATFORM configuration options
* @{
*/
/**
* @brief USART0 driver enable switch.
* @details If set to @p TRUE the support for USART0 is included.
* @note The default is @p FALSE.
*/
#if !defined(PLATFORM_SERIAL_USE_USART0) || defined(__DOXYGEN__)
#define PLATFORM_SERIAL_USE_USART0 FALSE
#endif
#if !defined(PLATFORM_SERIAL_USE_USART1) || defined(__DOXYGEN__)
#define PLATFORM_SERIAL_USE_USART1 FALSE
#endif
/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief PLATFORM 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 {
/**
* @brief Bit rate.
*/
uint32_t speed;
/* End of the mandatory fields.*/
} 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.*/ \
USART_TypeDef *usart;
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#if (HT32_SERIAL_USE_USART0 == TRUE) && !defined(__DOXYGEN__)
extern SerialDriver SD0;
#endif
#if (HT32_SERIAL_USE_USART1 == TRUE) && !defined(__DOXYGEN__)
extern SerialDriver SD1;
#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);
#ifdef __cplusplus
}
#endif
#endif /* HAL_USE_SERIAL == TRUE */
#endif /* HAL_SERIAL_LLD_H */
/** @} */

View File

@ -0,0 +1,305 @@
/*
Copyright (C) 2020 Yaotian Feng
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 hal_uart_lld.c
* @brief PLATFORM UART subsystem low level driver source.
*
* @addtogroup UART
* @{
*/
#include "hal.h"
#if (HAL_USE_UART == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/**
* @brief UART1 driver identifier.
*/
#if (HT32_UART_USE_UART0 == TRUE) || defined(__DOXYGEN__)
UARTDriver UARTD0;
#endif
#if (HT32_UART_USE_UART1 == TRUE) || defined(__DOXYGEN__)
UARTDriver UARTD1;
#endif
#if (HT32_UART_USE_USART0 == TRUE) || defined(__DOXYGEN__)
UARTDriver USARTD0;
#endif
#if (HT32_UART_USE_USART1 == TRUE) || defined(__DOXYGEN__)
UARTDriver USARTD1;
#endif
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
static void uart_lld_handler(UARTDriver *uartp) {
}
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
#if (HT32_UART_USE_UART0 == TRUE) || defined(__DOXYGEN__)
OSAL_IRQ_HANDLER(HT32_UART0_IRQ_VECTOR) {
OSAL_IRQ_PROLOGUE();
uart_lld_handler(&UARTD0);
OSAL_IRQ_EPILOGUE();
}
#endif
#if (HT32_UART_USE_UART1 == TRUE) || defined(__DOXYGEN__)
OSAL_IRQ_HANDLER(HT32_UART1_IRQ_VECTOR) {
OSAL_IRQ_PROLOGUE();
uart_lld_handler(&UARTD1);
OSAL_IRQ_EPILOGUE();
}
#endif
#if (HT32_UART_USE_USART0 == TRUE) || defined(__DOXYGEN__)
OSAL_IRQ_HANDLER(HT32_USART0_IRQ_VECTOR) {
OSAL_IRQ_PROLOGUE();
uart_lld_handler(&USARTD0);
OSAL_IRQ_EPILOGUE();
}
#endif
#if (HT32_UART_USE_USART1 == TRUE) || defined(__DOXYGEN__)
OSAL_IRQ_HANDLER(HT32_USART1_IRQ_VECTOR) {
OSAL_IRQ_PROLOGUE();
uart_lld_handler(&USARTD1);
OSAL_IRQ_EPILOGUE();
}
#endif
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level UART driver initialization.
*
* @notapi
*/
void uart_lld_init(void) {
/* Driver initialization. */
#if HT32_UART_USE_UART0 == TRUE
uartObjectInit(&UARTD0);
UARTD0.UART = UART0;
#endif
#if HT32_UART_USE_UART1 == TRUE
uartObjectInit(&UARTD1);
UARTD1.UART = UART1;
#endif
#if HT32_UART_USE_USART0 == TRUE
uartObjectInit(&USARTD0);
USARTD0.UART = USART0;
#endif
#if HT32_UART_USE_USART1 == TRUE
uartObjectInit(&USARTD1);
USARTD1.UART = USART1;
#endif
/* Peripheral initialization. */
CKCU->GCFGR = (CKCU->GCFGR & ~CKCU_GCFGR_URPRE_MASK) | ((HT32_USART_PRESCALER - 1) << 22);
}
/**
* @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) {
/* Enables the peripheral.*/
#if HT32_UART_USE_UART0 == TRUE
if (&UARTD1 == uartp) {
CKCU->APBCCR0 |= CKCU_APBCCR0_UR0EN;
nvicEnableVector(UART0_IRQn, HT32_UART0_IRQ_PRIORITY);
}
#endif
#if HT32_UART_USE_UART1 == TRUE
if (&UARTD1 == uartp) {
CKCU->APBCCR0 |= CKCU_APBCCR0_UR1EN;
nvicEnableVector(UART1_IRQn, HT32_UART1_IRQ_PRIORITY);
}
#endif
#if HT32_UART_USE_USART0 == TRUE
if (&USARTD0 == uartp) {
CKCU->APBCCR0 |= CKCU_APBCCR0_USR0EN;
nvicEnableVector(USART0_IRQn, HT32_USART0_IRQ_PRIORITY);
}
#endif
#if HT32_UART_USE_USART1 == TRUE
if (&USARTD1 == uartp) {
CKCU->APBCCR0 |= CKCU_APBCCR0_USR1EN;
nvicEnableVector(USART1_IRQn, HT32_USART1_IRQ_PRIORITY);
}
#endif
}
/* Configures the peripheral.*/
uartp->UART->FCR = uartp->config->fcr;
uartp->UART->LCR = uartp->config->lcr;
uartp->UART->MDR = uartp->config->mdr;
// baud = ck_ahb / dlr value
uartp->UART->DLR = HT32_CK_AHB_FREQUENCY / uartp->config->baud;
}
/**
* @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) {
/* Resets the peripheral.*/
/* Disables the peripheral.*/
#if HT32_UART_USE_UART0 == TRUE
if (&UARTD0 == uartp) {
RSTCU->APBPRSTR0 = RSTCU_APBPRSTR0_UR0RST;
CKCU->APBCCR0 &= ~CKCU_APBCCR0_UR0EN;
nvicDisableVector(UART0_IRQn);
}
#endif
#if HT32_UART_USE_UART1 == TRUE
if (&UARTD1 == uartp) {
RSTCU->APBPRSTR0 = RSTCU_APBPRSTR0_UR1RST;
CKCU->APBCCR0 &= ~CKCU_APBCCR0_UR1EN;
nvicDisableVector(UART1_IRQn);
}
#endif
#if HT32_UART_USE_USART0 == TRUE
if (&USARTD0 == uartp) {
RSTCU->APBPRSTR0 = RSTCU_APBPRSTR0_USR0RST;
CKCU->APBCCR0 &= ~CKCU_APBCCR0_USR0EN;
nvicDisableVector(USART0_IRQn);
}
#endif
#if HT32_UART_USE_USART1 == TRUE
if (&USARTD1 == uartp) {
RSTCU->APBPRSTR0 = RSTCU_APBPRSTR0_USR1RST;
CKCU->APBCCR0 &= ~CKCU_APBCCR0_USR1EN;
nvicDisableVector(USART1_IRQn);
}
#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) {
if ((uartp->config->lcr & 3) == 2) {
uint16_t *txdata = (uint16_t *)txbuf;
while(n > 0){
uartp->UART->TBR = *txdata;
while(!(uartp->UART->LSR & USART_LSR_TXEMPT));
txdata++;
n--;
}
} else {
uint8_t *txdata = (uint8_t *)txbuf;
while(n > 0){
uartp->UART->TBR = *txdata;
while(!(uartp->UART->LSR & USART_LSR_TXEMPT));
txdata++;
n--;
}
}
}
/**
* @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) {
(void)uartp;
return 0;
}
/**
* @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) {
(void)uartp;
(void)n;
(void)rxbuf;
}
/**
* @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) {
(void)uartp;
return 0;
}
#endif /* HAL_USE_UART == TRUE */
/** @} */

View File

@ -0,0 +1,229 @@
/*
Copyright (C) 2020 Yaotian Feng
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 hal_uart_lld.h
* @brief PLATFORM UART subsystem low level driver header.
*
* @addtogroup UART
* @{
*/
#ifndef HAL_UART_LLD_H
#define HAL_UART_LLD_H
#if (HAL_USE_UART == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name PLATFORM configuration options
* @{
*/
/**
* @brief UART driver enable switch.
* @details If set to @p TRUE the support for UART1 is included.
* @note The default is @p FALSE.
*/
#if !defined(HT32_UART_USE_UART0) || defined(__DOXYGEN__)
#define HT32_UART_USE_UART0 FALSE
#endif
#if !defined(HT32_UART_USE_UART1) || defined(__DOXYGEN__)
#define HT32_UART_USE_UART1 FALSE
#endif
#if !defined(HT32_UART_USE_USART0) || defined(__DOXYGEN__)
#define HT32_UART_USE_USART0 FALSE
#endif
#if !defined(HT32_UART_USE_USART1) || defined(__DOXYGEN__)
#define HT32_UART_USE_USART1 FALSE
#endif
/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief UART driver condition flags type.
*/
typedef uint32_t uartflags_t;
/**
* @brief Type of structure representing an UART driver.
*/
typedef struct UARTDriver 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 triggering the
* callback
* @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 triggering the
* callback
* @param[in] e receive error mask
*/
typedef void (*uartecb_t)(UARTDriver *uartp, uartflags_t e);
/**
* @brief Driver configuration structure.
* @note Implementations may extend this structure to contain more,
* architecture dependent, fields.
*/
typedef struct {
/**
* @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.*/
uint32_t fcr;
uint32_t lcr;
uint32_t mdr;
/**
* @brief Baud rate.
*/
uint32_t baud;
} UARTConfig;
/**
* @brief Structure representing an UART driver.
* @note Implementations may extend this structure to contain more,
* architecture dependent, fields.
*/
struct UARTDriver {
/**
* @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.*/
USART_TypeDef *UART;
};
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#if (HT32_UART_USE_UART0 == TRUE) && !defined(__DOXYGEN__)
extern UARTDriver UARTD0;
#endif
#if (HT32_UART_USE_UART1 == TRUE) && !defined(__DOXYGEN__)
extern UARTDriver UARTD1;
#endif
#if (HT32_UART_USE_USART0 == TRUE) && !defined(__DOXYGEN__)
extern UARTDriver USARTD0;
#endif
#if (HT32_UART_USE_USART1 == TRUE) && !defined(__DOXYGEN__)
extern UARTDriver USARTD1;
#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);
#ifdef __cplusplus
}
#endif
#endif /* HAL_USE_UART == TRUE */
#endif /* HAL_UART_LLD_H */
/** @} */

View File

@ -0,0 +1,13 @@
ifeq ($(USE_SMART_BUILD),yes)
ifneq ($(findstring HAL_USE_SERIAL TRUE,$(HALCONF)),)
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/HT32/LLD/USART_F5xxxx/hal_serial_lld.c
endif
ifneq ($(findstring HAL_USE_UART TRUE,$(HALCONF)),)
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/HT32/LLD/USART_F5xxxx/hal_uart_lld.c
endif
else
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/HT32/LLD/USART_F5xxxx/hal_serial_lld.c
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/HT32/LLD/USART_F5xxxx/hal_uart_lld.c
endif
PLATFORMINC += $(CHIBIOS_CONTRIB)/os/hal/ports/HT32/LLD/USART_F5xxxx

View File

@ -0,0 +1,229 @@
/*
Copyright (C) 2020 Yaotian Feng
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 hal_serial_lld.c
* @brief HT32 serial subsystem low level driver source.
*
* @addtogroup SERIAL
* @{
*/
#include "hal.h"
#if (HAL_USE_SERIAL == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/** @brief USART0 serial driver identifier.*/
# if (HT32_SERIAL_USE_USART0 == TRUE) || defined(__DOXYGEN__)
SerialDriver SD0;
# endif
# if (HT32_SERIAL_USE_USART1 == TRUE) || defined(__DOXYGEN__)
SerialDriver SD1;
# endif
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/**
* @brief Driver default configuration.
*/
static const SerialConfig default_config = {SERIAL_DEFAULT_BITRATE};
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
static void load(SerialDriver *sdp) {
USART_TypeDef *u = sdp->usart;
u->IER |= (USART_IER_TXDEIE | USART_IER_TXCIE);
}
# if HT32_SERIAL_USE_USART0 == TRUE
static void notify0(io_queue_t *qp) {
(void)qp;
load(&SD0);
}
# endif
# if HT32_SERIAL_USE_USART1 == TRUE
static void notify1(io_queue_t *qp) {
(void)qp;
load(&SD1);
}
# endif
static void serialInterrupt(SerialDriver *pSd) {
USART_TypeDef *u = pSd->usart;
uint32_t sifr = u->SIFR;
// Rx has data, timeout or crossed threashold
// TX Below threash or complete
if ((sifr & USART_SIFR_TXDE) || (sifr & USART_SIFR_TXC)) {
msg_t b;
osalSysLockFromISR();
{
b = oqGetI(&(pSd->oqueue));
if (b < MSG_OK) {
u->IER &= ~(USART_IER_TXDEIE | USART_IER_TXCIE);
chnAddFlagsI(pSd, CHN_OUTPUT_EMPTY);
} else {
u->DR = b;
}
}
osalSysUnlockFromISR();
}
if (sifr & (USART_SIFR_RXDNE | USART_SIFR_RXDR | USART_SIFR_RXTOF)) {
osalSysLockFromISR();
{
if (iqIsEmptyI(&pSd->iqueue)) chnAddFlagsI(pSd, CHN_INPUT_AVAILABLE);
while ((u->SIFR) & USART_SIFR_RXDNE) {
if (iqPutI(&(pSd->iqueue), u->DR) < MSG_OK) chnAddFlagsI(pSd, SD_OVERRUN_ERROR);
}
// Clear Timeout if it occours
if (sifr & USART_SIFR_RXTOF) u->SIFR = USART_SIFR_RXTOF;
}
osalSysUnlockFromISR();
}
// Clear all remaining flags.
u->SIFR &= 0x3FF;
}
static void usartInit(SerialDriver *sdp, const SerialConfig *config) {
USART_TypeDef *u = sdp->usart;
u->DLR = (uint32_t)(HT32_CK_USART_FREQUENCY / config->speed); /* Data Rate */
u->CR = (UART_CR_MODE_NORMAL | UART_CR_URTXEN | UART_CR_URRXEN | UART_CR_WLS_8B); /* 8-bit, one stop, no parity */
u->FCR = USART_FCR_TXR | USART_FCR_RXR; // Reset FIFOs.
u->IER = USART_IER_RXDRIE | USART_IER_TXDEIE | USART_IER_TXCIE;
}
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
# if HT32_SERIAL_USE_USART0 == TRUE
CH_IRQ_HANDLER(HT32_USART0_IRQ_VECTOR) {
CH_IRQ_PROLOGUE();
serialInterrupt(&SD0);
CH_IRQ_EPILOGUE();
}
# endif
# if HT32_SERIAL_USE_USART1 == TRUE
CH_IRQ_HANDLER(HT32_USART1_IRQ_VECTOR) {
CH_IRQ_PROLOGUE();
serialInterrupt(&SD1);
CH_IRQ_EPILOGUE();
}
# endif
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level serial driver initialization.
*
* @notapi
*/
void sd_lld_init(void) {
# if HT32_SERIAL_USE_USART0 == TRUE
sdObjectInit(&SD0, NULL, notify0);
SD0.usart = USART0;
# endif
# if HT32_SERIAL_USE_USART1 == TRUE
sdObjectInit(&SD1, NULL, notify1);
SD1.usart = USART1;
# 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 HT32_SERIAL_USE_USART0 == TRUE
if (&SD0 == sdp) {
CKCU->APBCCR0 |= (1U << 8);
nvicEnableVector(USART0_IRQn, HT32_USART0_IRQ_PRIORITY);
}
# endif
# if HT32_SERIAL_USE_USART1 == TRUE
if (&SD1 == sdp) {
CKCU->APBCCR0 |= (1U << 9);
nvicEnableVector(USART1_IRQn, HT32_USART1_IRQ_PRIORITY);
}
# endif
}
usartInit(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_TypeDef *u = sdp->usart;
# if HT32_SERIAL_USE_USART0 == TRUE
if (&SD0 == sdp) {
nvicDisableVector(USART0_IRQn);
u -> IER = 0; // Disable all interrupts
}
# endif // HT32_SERIAL_USE_USART0 == TRUE
# if HT32_SERIAL_USE_USART1 == TRUE
if (&SD1 == sdp) {
nvicDisableVector(USART1_IRQn);
u -> IER = 0; // Disable all interrupts
}
# endif // HT32_SERIAL_USE_USART1 == TRUE
}
}
#endif /* HAL_USE_SERIAL == TRUE */
/** @} */

View File

@ -0,0 +1,127 @@
/*
Copyright (C) 2020 Yaotian Feng
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 hal_serial_lld.h
* @brief PLATFORM serial subsystem low level driver header.
*
* @addtogroup SERIAL
* @{
*/
#ifndef HAL_SERIAL_LLD_H
#define HAL_SERIAL_LLD_H
#if (HAL_USE_SERIAL == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name PLATFORM configuration options
* @{
*/
/**
* @brief USART0 driver enable switch.
* @details If set to @p TRUE the support for USART0 is included.
* @note The default is @p FALSE.
*/
#if !defined(PLATFORM_SERIAL_USE_USART0) || defined(__DOXYGEN__)
#define PLATFORM_SERIAL_USE_USART0 FALSE
#endif
#if !defined(PLATFORM_SERIAL_USE_USART1) || defined(__DOXYGEN__)
#define PLATFORM_SERIAL_USE_USART1 FALSE
#endif
/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief PLATFORM 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 {
/**
* @brief Bit rate.
*/
uint32_t speed;
/* End of the mandatory fields.*/
} 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.*/ \
USART_TypeDef *usart;
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#if (HT32_SERIAL_USE_USART0 == TRUE) && !defined(__DOXYGEN__)
extern SerialDriver SD0;
#endif
#if (HT32_SERIAL_USE_USART1 == TRUE) && !defined(__DOXYGEN__)
extern SerialDriver SD1;
#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);
#ifdef __cplusplus
}
#endif
#endif /* HAL_USE_SERIAL == TRUE */
#endif /* HAL_SERIAL_LLD_H */
/** @} */

View File

@ -0,0 +1,305 @@
/*
Copyright (C) 2020 Yaotian Feng
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 hal_uart_lld.c
* @brief PLATFORM UART subsystem low level driver source.
*
* @addtogroup UART
* @{
*/
#include "hal.h"
#if (HAL_USE_UART == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/**
* @brief UART1 driver identifier.
*/
#if (HT32_UART_USE_UART0 == TRUE) || defined(__DOXYGEN__)
UARTDriver UARTD0;
#endif
#if (HT32_UART_USE_UART1 == TRUE) || defined(__DOXYGEN__)
UARTDriver UARTD1;
#endif
#if (HT32_UART_USE_USART0 == TRUE) || defined(__DOXYGEN__)
UARTDriver USARTD0;
#endif
#if (HT32_UART_USE_USART1 == TRUE) || defined(__DOXYGEN__)
UARTDriver USARTD1;
#endif
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
static void uart_lld_handler(UARTDriver *uartp) {
}
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
#if (HT32_UART_USE_UART0 == TRUE) || defined(__DOXYGEN__)
OSAL_IRQ_HANDLER(HT32_UART0_IRQ_VECTOR) {
OSAL_IRQ_PROLOGUE();
uart_lld_handler(&UARTD0);
OSAL_IRQ_EPILOGUE();
}
#endif
#if (HT32_UART_USE_UART1 == TRUE) || defined(__DOXYGEN__)
OSAL_IRQ_HANDLER(HT32_UART1_IRQ_VECTOR) {
OSAL_IRQ_PROLOGUE();
uart_lld_handler(&UARTD1);
OSAL_IRQ_EPILOGUE();
}
#endif
#if (HT32_UART_USE_USART0 == TRUE) || defined(__DOXYGEN__)
OSAL_IRQ_HANDLER(HT32_USART0_IRQ_VECTOR) {
OSAL_IRQ_PROLOGUE();
uart_lld_handler(&USARTD0);
OSAL_IRQ_EPILOGUE();
}
#endif
#if (HT32_UART_USE_USART1 == TRUE) || defined(__DOXYGEN__)
OSAL_IRQ_HANDLER(HT32_USART1_IRQ_VECTOR) {
OSAL_IRQ_PROLOGUE();
uart_lld_handler(&USARTD1);
OSAL_IRQ_EPILOGUE();
}
#endif
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level UART driver initialization.
*
* @notapi
*/
void uart_lld_init(void) {
/* Driver initialization. */
#if HT32_UART_USE_UART0 == TRUE
uartObjectInit(&UARTD0);
UARTD0.UART = UART0;
#endif
#if HT32_UART_USE_UART1 == TRUE
uartObjectInit(&UARTD1);
UARTD1.UART = UART1;
#endif
#if HT32_UART_USE_USART0 == TRUE
uartObjectInit(&USARTD0);
USARTD0.UART = USART0;
#endif
#if HT32_UART_USE_USART1 == TRUE
uartObjectInit(&USARTD1);
USARTD1.UART = USART1;
#endif
/* Peripheral initialization. */
CKCU->GCFGR = (CKCU->GCFGR & ~CKCU_GCFGR_URPRE_MASK) | ((HT32_USART_PRESCALER - 1) << 22);
}
/**
* @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) {
/* Enables the peripheral.*/
#if HT32_UART_USE_UART0 == TRUE
if (&UARTD1 == uartp) {
CKCU->APBCCR0 |= CKCU_APBCCR0_UR0EN;
nvicEnableVector(UART0_IRQn, HT32_UART0_IRQ_PRIORITY);
}
#endif
#if HT32_UART_USE_UART1 == TRUE
if (&UARTD1 == uartp) {
CKCU->APBCCR0 |= CKCU_APBCCR0_UR1EN;
nvicEnableVector(UART1_IRQn, HT32_UART1_IRQ_PRIORITY);
}
#endif
#if HT32_UART_USE_USART0 == TRUE
if (&USARTD0 == uartp) {
CKCU->APBCCR0 |= CKCU_APBCCR0_USR0EN;
nvicEnableVector(USART0_IRQn, HT32_USART0_IRQ_PRIORITY);
}
#endif
#if HT32_UART_USE_USART1 == TRUE
if (&USARTD1 == uartp) {
CKCU->APBCCR0 |= CKCU_APBCCR0_USR1EN;
nvicEnableVector(USART1_IRQn, HT32_USART1_IRQ_PRIORITY);
}
#endif
}
/* Configures the peripheral.*/
uartp->UART->FCR = uartp->config->fcr;
uartp->UART->LCR = uartp->config->lcr;
uartp->UART->MDR = uartp->config->mdr;
// baud = ck_ahb / dlr value
uartp->UART->DLR = HT32_CK_AHB_FREQUENCY / uartp->config->baud;
}
/**
* @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) {
/* Resets the peripheral.*/
/* Disables the peripheral.*/
#if HT32_UART_USE_UART0 == TRUE
if (&UARTD0 == uartp) {
RSTCU->APBPRSTR0 = RSTCU_APBPRSTR0_UR0RST;
CKCU->APBCCR0 &= ~CKCU_APBCCR0_UR0EN;
nvicDisableVector(UART0_IRQn);
}
#endif
#if HT32_UART_USE_UART1 == TRUE
if (&UARTD1 == uartp) {
RSTCU->APBPRSTR0 = RSTCU_APBPRSTR0_UR1RST;
CKCU->APBCCR0 &= ~CKCU_APBCCR0_UR1EN;
nvicDisableVector(UART1_IRQn);
}
#endif
#if HT32_UART_USE_USART0 == TRUE
if (&USARTD0 == uartp) {
RSTCU->APBPRSTR0 = RSTCU_APBPRSTR0_USR0RST;
CKCU->APBCCR0 &= ~CKCU_APBCCR0_USR0EN;
nvicDisableVector(USART0_IRQn);
}
#endif
#if HT32_UART_USE_USART1 == TRUE
if (&USARTD1 == uartp) {
RSTCU->APBPRSTR0 = RSTCU_APBPRSTR0_USR1RST;
CKCU->APBCCR0 &= ~CKCU_APBCCR0_USR1EN;
nvicDisableVector(USART1_IRQn);
}
#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) {
if ((uartp->config->lcr & 3) == 2) {
uint16_t *txdata = (uint16_t *)txbuf;
while(n > 0){
uartp->UART->TBR = *txdata;
while(!(uartp->UART->LSR & USART_LSR_TXEMPT));
txdata++;
n--;
}
} else {
uint8_t *txdata = (uint8_t *)txbuf;
while(n > 0){
uartp->UART->TBR = *txdata;
while(!(uartp->UART->LSR & USART_LSR_TXEMPT));
txdata++;
n--;
}
}
}
/**
* @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) {
(void)uartp;
return 0;
}
/**
* @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) {
(void)uartp;
(void)n;
(void)rxbuf;
}
/**
* @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) {
(void)uartp;
return 0;
}
#endif /* HAL_USE_UART == TRUE */
/** @} */

View File

@ -0,0 +1,229 @@
/*
Copyright (C) 2020 Yaotian Feng
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 hal_uart_lld.h
* @brief PLATFORM UART subsystem low level driver header.
*
* @addtogroup UART
* @{
*/
#ifndef HAL_UART_LLD_H
#define HAL_UART_LLD_H
#if (HAL_USE_UART == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name PLATFORM configuration options
* @{
*/
/**
* @brief UART driver enable switch.
* @details If set to @p TRUE the support for UART1 is included.
* @note The default is @p FALSE.
*/
#if !defined(HT32_UART_USE_UART0) || defined(__DOXYGEN__)
#define HT32_UART_USE_UART0 FALSE
#endif
#if !defined(HT32_UART_USE_UART1) || defined(__DOXYGEN__)
#define HT32_UART_USE_UART1 FALSE
#endif
#if !defined(HT32_UART_USE_USART0) || defined(__DOXYGEN__)
#define HT32_UART_USE_USART0 FALSE
#endif
#if !defined(HT32_UART_USE_USART1) || defined(__DOXYGEN__)
#define HT32_UART_USE_USART1 FALSE
#endif
/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief UART driver condition flags type.
*/
typedef uint32_t uartflags_t;
/**
* @brief Type of structure representing an UART driver.
*/
typedef struct UARTDriver 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 triggering the
* callback
* @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 triggering the
* callback
* @param[in] e receive error mask
*/
typedef void (*uartecb_t)(UARTDriver *uartp, uartflags_t e);
/**
* @brief Driver configuration structure.
* @note Implementations may extend this structure to contain more,
* architecture dependent, fields.
*/
typedef struct {
/**
* @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.*/
uint32_t fcr;
uint32_t lcr;
uint32_t mdr;
/**
* @brief Baud rate.
*/
uint32_t baud;
} UARTConfig;
/**
* @brief Structure representing an UART driver.
* @note Implementations may extend this structure to contain more,
* architecture dependent, fields.
*/
struct UARTDriver {
/**
* @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.*/
USART_TypeDef *UART;
};
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#if (HT32_UART_USE_UART0 == TRUE) && !defined(__DOXYGEN__)
extern UARTDriver UARTD0;
#endif
#if (HT32_UART_USE_UART1 == TRUE) && !defined(__DOXYGEN__)
extern UARTDriver UARTD1;
#endif
#if (HT32_UART_USE_USART0 == TRUE) && !defined(__DOXYGEN__)
extern UARTDriver USARTD0;
#endif
#if (HT32_UART_USE_USART1 == TRUE) && !defined(__DOXYGEN__)
extern UARTDriver USARTD1;
#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);
#ifdef __cplusplus
}
#endif
#endif /* HAL_USE_UART == TRUE */
#endif /* HAL_UART_LLD_H */
/** @} */

View File

@ -0,0 +1,9 @@
ifeq ($(USE_SMART_BUILD),yes)
ifneq ($(findstring HAL_USE_USB TRUE,$(HALCONF)),)
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/HT32/LLD/USBv1/hal_usb_lld.c
endif
else
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/HT32/LLD/USBv1/hal_usb_lld.c
endif
PLATFORMINC += $(CHIBIOS_CONTRIB)/os/hal/ports/HT32/LLD/USBv1

View File

@ -0,0 +1,712 @@
/*
ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
Copyright (C) 2020 Yaotian Feng
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 hal_usb_lld.c
* @brief HT32 USB subsystem low level driver source.
*
* @addtogroup USB
* @{
*/
#include "hal.h"
#if (HAL_USE_USB == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
#define roundup2(x, m) (((x) + (m) - 1) & ~((m) - 1))
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/**
* @brief USB1 driver identifier.
*/
#if HT32_USB_USE_USB0 || defined(__DOXYGEN__)
USBDriver USBD1;
#endif
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/**
* @brief EP0 state.
* @note It is an union because IN and OUT endpoints are never used at the
* same time for EP0.
*/
static union {
/**
* @brief IN EP0 state.
*/
USBInEndpointState in;
/**
* @brief OUT EP0 state.
*/
USBOutEndpointState out;
} ep0_state;
/**
* @brief EP0 initialization structure.
*/
static const USBEndpointConfig ep0config = {
USB_EP_MODE_TYPE_CTRL,
_usb_ep0setup,
_usb_ep0in,
_usb_ep0out,
0x40,
0x40,
&ep0_state.in,
&ep0_state.out
};
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
static uint32_t usb_get_int_flags(void){
return USB->IER & USB->ISR;
}
static void usb_clear_int_flags(uint32_t flags){
// flags are cleared by writing 1
// except ESOFIF, which is written normally
USB->ISR = flags ^ USBISR_ESOFIF;
}
static uint32_t usb_get_ep_int_flags(int ep){
return USB->EP[ep].IER & USB->EP[ep].ISR;
}
static void usb_clear_ep_int_flags(int ep, uint32_t flags){
// flags are cleared by writing 1
USB->EP[ep].ISR = flags;
}
static size_t usb_epmem_alloc(USBDriver *usbp, size_t size) {
const size_t epmo = usbp->epmem_next;
usbp->epmem_next = roundup2(epmo + size, 4);
osalDbgAssert(usbp->epmem_next <= 0x400, "EPSRAM exhausted");
return epmo;
}
static void usb_packet_transmit(USBDriver *usbp, usbep_t ep, size_t n)
{
const USBEndpointConfig * const epc = usbp->epc[ep];
USBInEndpointState * const isp = epc->in_state;
if (n > (size_t)epc->in_maxsize)
n = (size_t)epc->in_maxsize;
if ((USB->EP[ep].TCR & 0xffffU) == 0) {
const uint32_t cfgr = USB->EP[ep].CFGR;
volatile uint32_t * const EPSRAM = (void *)(USB_SRAM_BASE + (cfgr & 0x3ff));
for (size_t i = 0; i < n; i += 4) {
uint32_t word = 0;
if (i + 0 < n)
word |= (uint32_t)isp->txbuf[i+0]<<0;
if (i + 1 < n)
word |= (uint32_t)isp->txbuf[i+1]<<8;
if (i + 2 < n)
word |= (uint32_t)isp->txbuf[i+2]<<16;
if (i + 3 < n)
word |= (uint32_t)isp->txbuf[i+3]<<24;
EPSRAM[i/4] = word;
}
USB->EP[ep].TCR = n;
isp->txlastpktlen = n;
USB->EP[ep].CSR &= USBEPnCSR_NAKTX;
}
}
static size_t usb_packet_receive(USBDriver *usbp, usbep_t ep) {
USBOutEndpointState *osp = usbp->epc[ep]->out_state;
const size_t n = USB->EP[ep].TCR >> ((ep == 0) ? 16 : 0);
const uint32_t cfgr = USB->EP[ep].CFGR;
volatile uint32_t *const EPSRAM = (void *)(USB_SRAM_BASE + (cfgr & 0x3ff) + ((ep == 0) ? ((cfgr >> 10) & 0x7f) : 0));
for (size_t i = 0; i < n; i += 4) {
if(!osp->rxbuf)
break;
const uint32_t word = EPSRAM[i/4];
if (i + 0 < n)
osp->rxbuf[i + 0] = word >> 0;
if (i + 1 < n)
osp->rxbuf[i + 1] = word >> 8;
if (i + 2 < n)
osp->rxbuf[i + 2] = word >> 16;
if (i + 3 < n)
osp->rxbuf[i + 3] = word >> 24;
}
osp->rxbuf += n;
osp->rxcnt += n;
osp->rxsize -= n;
osp->rxpkts--;
return n;
}
/*===========================================================================*/
/* Driver interrupt handlers and threads. */
/*===========================================================================*/
#if (HT32_USB_USE_USB0 == TRUE) || defined(__DOXYGEN__) || 1
/**
* @brief USB interrupt handler.
* @isr
*/
OSAL_IRQ_HANDLER(HT32_USB_IRQ_VECTOR) {
OSAL_IRQ_PROLOGUE();
USBDriver *usbp = &USBD1;
uint32_t isr = usb_get_int_flags();
// Start of Frame Interrupt
if(isr & USBISR_SOFIF){
// Start of Frame callback
_usb_isr_invoke_sof_cb(usbp);
usb_clear_int_flags(USBISR_SOFIF);
}
// Suspend Interrupt
if(isr & USBISR_SUSPIF){
usb_clear_int_flags(USBISR_SUSPIF);
// Suspend routine and event callback
_usb_suspend(usbp);
#if 0
USB->CSR &= USBCSR_DPPUEN; /* POWER_ON */
USB->CSR |= USBCSR_GENRSM;
#endif
}
// Reset Interrupt
if(isr & USBISR_URSTIF){
// Reset routine and event callback
_usb_reset(usbp);
usb_clear_int_flags(USBISR_URSTIF);
}
// Resume Interrupt
if(isr & USBISR_RSMIF){
// Resume/Wakeup routine and callback
_usb_wakeup(usbp);
usb_clear_int_flags(USBISR_RSMIF);
}
// EP0 Interrupt
if(isr & USBISR_EP0IF){
uint32_t episr = usb_get_ep_int_flags(0);
#if 0
// SETUP Token Received
if(episr & USBEPnISR_STRXIF){
usb_clear_ep_int_flags(0, USBEPnISR_STRXIF);
}
#endif
// SETUP Data Received
if(episr & USBEPnISR_SDRXIF){
// SETUP callback
_usb_isr_invoke_setup_cb(usbp, 0);
usb_clear_ep_int_flags(0, USBEPnISR_SDRXIF);
}
#if 0
// OUT Token Received
if(episr & USBEPnISR_OTRXIF){
usb_clear_ep_int_flags(0, USBEPnISR_OTRXIF);
}
#endif
// OUT Data Received
if(episr & USBEPnISR_ODRXIF){
USBOutEndpointState *osp = usbp->epc[0]->out_state;
size_t n = usb_packet_receive(usbp, 0);
if ((n < usbp->epc[0]->out_maxsize) || (osp->rxpkts == 0)) {
// OUT callback
_usb_isr_invoke_out_cb(usbp, 0);
} else {
USB->EP[0].CSR &= USBEPnCSR_NAKRX;
}
usb_clear_ep_int_flags(0, USBEPnISR_ODRXIF);
}
#if 0
// IN Token Received
if(episr & USBEPnISR_ITRXIF){
usb_clear_ep_int_flags(0, USBEPnISR_ITRXIF);
}
#endif
// IN Data Transmitted
if(episr & USBEPnISR_IDTXIF){
USBInEndpointState *isp = usbp->epc[0]->in_state;
size_t n = isp->txlastpktlen;
isp->txcnt += n;
if (isp->txcnt < isp->txsize) {
isp->txbuf += n;
osalSysLockFromISR();
usb_packet_transmit(usbp, 0, isp->txsize - isp->txcnt);
osalSysUnlockFromISR();
} else {
// IN callback
_usb_isr_invoke_in_cb(usbp, 0);
}
usb_clear_ep_int_flags(0, USBEPnISR_IDTXIF);
}
#if 0
// STALL Transmitted
if(episr & USBEPnISR_STLIF){
usb_clear_ep_int_flags(0, USBEPnISR_STLIF);
}
#endif
usb_clear_int_flags(USBISR_EP0IF);
}
// EP 1-7 Interrupt
uint32_t mask = USBISR_EP1IF;
for(int i = 1; i < 8; ++i){
// EPn Interrupt
if(isr & mask){
uint32_t episr = usb_get_ep_int_flags(i);
usb_clear_ep_int_flags(i, episr);
usb_clear_int_flags(mask);
#if 0
// OUT Token Received
if(episr & USBEPnISR_OTRXIF){
usb_clear_ep_int_flags(i, USBEPnISR_OTRXIF);
}
#endif
// OUT Data Received
if(episr & USBEPnISR_ODRXIF){
USBOutEndpointState *osp = usbp->epc[i]->out_state;
size_t n = usb_packet_receive(usbp, i);
if ((n < usbp->epc[i]->out_maxsize) || (osp->rxpkts == 0)) {
// OUT callback
_usb_isr_invoke_out_cb(usbp, i);
} else {
USB->EP[i].CSR &= USBEPnCSR_NAKRX;
}
}
#if 0
// IN Token Received
if(episr & USBEPnISR_ITRXIF){
usb_clear_ep_int_flags(i, USBEPnISR_ITRXIF);
}
#endif
// IN Data Transmitted
if(episr & USBEPnISR_IDTXIF){
USBInEndpointState *isp = usbp->epc[i]->in_state;
size_t n = isp->txlastpktlen;
isp->txcnt += n;
if (isp->txcnt < isp->txsize) {
isp->txbuf += n;
osalSysLockFromISR();
usb_packet_transmit(usbp, i, isp->txsize - isp->txcnt);
osalSysUnlockFromISR();
} else {
// IN callback
_usb_isr_invoke_in_cb(usbp, i);
}
}
#if 0
// STALL Transmitted
if(episr & USBEPnISR_STLIF){
usb_clear_ep_int_flags(i, USBEPnISR_STLIF);
}
#endif
}
mask = mask << 1;
}
OSAL_IRQ_EPILOGUE();
}
#endif
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level USB driver initialization.
*
* @notapi
*/
void usb_lld_init(void){
#if HT32_USB_USE_USB0 == TRUE
/* Driver initialization.*/
usbObjectInit(&USBD1);
// USB prescaler
CKCU->GCFGR = (CKCU->GCFGR & ~CKCU_GCFGR_USBPRE_MASK) | ((HT32_USB_PRESCALER - 1) << 22);
// enable USB clock
CKCU->AHBCCR |= CKCU_AHBCCR_USBEN;
#endif // HT32_USB_USE_USB1
}
/**
* @brief Configures and activates the USB peripheral.
*
* @param[in] usbp pointer to the @p USBDriver object
*
* @notapi
*/
void usb_lld_start(USBDriver *usbp){
if (usbp->state == USB_STOP) {
/* Enables the peripheral.*/
#if HT32_USB_USE_USB0 == TRUE
if (&USBD1 == usbp) {
// enable USB IRQ
nvicEnableVector(USB_IRQn, HT32_USB_USB0_IRQ_PRIORITY);
/* USBD_PowerUp */
USB->CSR = USBCSR_DPWKEN | USBCSR_DPPUEN | USBCSR_LPMODE | USBCSR_PDWN;
// enable usb interrupts
USB->ISR = ~0U;
USB->CSR &= ~USBCSR_DPWKEN;
USB->IER = USBIER_UGIE | USBIER_SOFIE |
USBIER_URSTIE | USBIER_RSMIE | USBIER_SUSPIE |
USBIER_EP0IE;
}
#endif // HT32_USB_USE_USB1
}
/* Configures the peripheral.*/
}
/**
* @brief Deactivates the USB peripheral.
*
* @param[in] usbp pointer to the @p USBDriver object
*
* @notapi
*/
void usb_lld_stop(USBDriver *usbp) {
if (usbp->state == USB_READY) {
/* Resets the peripheral.*/
/* Disables the peripheral.*/
#if HT32_USB_USE_USB0 == TRUE
if (&USBD1 == usbp) {
nvicDisableVector(USB_IRQn);
/* Resets the peripheral.*/
RSTCU->AHBPRSTR = RSTCU_AHBPRSTR_USBRST;
}
#endif
}
}
/**
* @brief USB low level reset routine.
*
* @param[in] usbp pointer to the @p USBDriver object
*
* @notapi
*/
void usb_lld_reset(USBDriver *usbp) {
// USB Reset
// Clear CSR, except for DP pull up
USB->CSR &= USBCSR_DPPUEN;
/* Post reset initialization.*/
usbp->epmem_next = 8;
/* EP0 initialization.*/
usbp->epc[0] = &ep0config;
usb_lld_init_endpoint(usbp, 0);
USB->IER = USBIER_UGIE | USBIER_SOFIE |
USBIER_URSTIE | USBIER_RSMIE | USBIER_SUSPIE |
USBIER_EP0IE;
}
/**
* @brief Sets the USB address.
*
* @param[in] usbp pointer to the @p USBDriver object
*
* @notapi
*/
void usb_lld_set_address(USBDriver *usbp) {
USB->CSR |= USBCSR_ADRSET;
USB->DEVAR = usbp->address & 0x7f;
}
/**
* @brief Enables an endpoint.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
*
* @notapi
*/
void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) {
if(ep > USB_MAX_ENDPOINTS)
return;
const USBEndpointConfig *epcp = usbp->epc[ep];
uint32_t cfgr = USBEPnCFGR_EPEN | ((uint32_t)ep<<24);
size_t epmo;
switch(epcp->ep_mode & USB_EP_MODE_TYPE){
case USB_EP_MODE_TYPE_CTRL:
break;
case USB_EP_MODE_TYPE_ISOC:
cfgr |= USBEPnCFGR_EPTYPE;
break;
case USB_EP_MODE_TYPE_BULK:
break;
case USB_EP_MODE_TYPE_INTR:
break;
default:
return;
}
if (epcp->in_state != NULL) {
epmo = usb_epmem_alloc(usbp, epcp->in_maxsize);
cfgr |= epmo << 0;
cfgr |= roundup2(epcp->in_maxsize, 4) << 10;
cfgr |= USBEPnCFGR_EPDIR;
}
if (epcp->out_state != NULL) {
epmo = usb_epmem_alloc(usbp, epcp->out_maxsize);
if (ep > 0) {
cfgr |= epmo << 0;
cfgr |= roundup2(epcp->out_maxsize, 4) << 10;
}
}
USB->EP[ep].CFGR = cfgr;
USB->EP[ep].IER = (ep == 0) ?
(USBEPnIER_SDRXIE|USBEPnIER_IDTXIE|USBEPnIER_ODRXIE) :
(USBEPnIER_ODRXIE|USBEPnIER_IDTXIE);
USB->IER |= (USBIER_EP0IE << ep);
}
/**
* @brief Disables all the active endpoints except the endpoint zero.
*
* @param[in] usbp pointer to the @p USBDriver object
*
* @notapi
*/
void usb_lld_disable_endpoints(USBDriver *usbp) {
for(int i = 1; i < USB_MAX_ENDPOINTS; ++i) {
USB->EP[i].CFGR &= ~USBEPnCFGR_EPEN;
USB->IER &= ~(USBIER_EP0IE << i);
}
const uint32_t cfgr = USB->EP[0].CFGR;
usbp->epmem_next = (cfgr & 0x3ff) + ((cfgr >> 10) & 0x7f);
}
/**
* @brief Returns the status of an OUT endpoint.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
* @return The endpoint status.
* @retval EP_STATUS_DISABLED The endpoint is not active.
* @retval EP_STATUS_STALLED The endpoint is stalled.
* @retval EP_STATUS_ACTIVE The endpoint is active.
*
* @notapi
*/
usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep)
{
(void)usbp;
if (ep > USB_MAX_ENDPOINTS)
return EP_STATUS_DISABLED;
if ((USB->EP[ep].CFGR & USBEPnCFGR_EPEN) == 0)
return EP_STATUS_DISABLED;
if ((USB->EP[ep].CSR & USBEPnCSR_STLRX) != 0)
return EP_STATUS_STALLED;
return EP_STATUS_ACTIVE;
}
/**
* @brief Returns the status of an IN endpoint.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
* @return The endpoint status.
* @retval EP_STATUS_DISABLED The endpoint is not active.
* @retval EP_STATUS_STALLED The endpoint is stalled.
* @retval EP_STATUS_ACTIVE The endpoint is active.
*
* @notapi
*/
usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep) {
(void)usbp;
if (ep > USB_MAX_ENDPOINTS)
return EP_STATUS_DISABLED;
if ((USB->EP[ep].CFGR & USBEPnCFGR_EPEN) == 0)
return EP_STATUS_DISABLED;
if ((USB->EP[ep].CSR & USBEPnCSR_STLRX) != 0)
return EP_STATUS_STALLED;
return EP_STATUS_ACTIVE;
}
/**
* @brief Reads a setup packet from the dedicated packet buffer.
* @details This function must be invoked in the context of the @p setup_cb
* callback in order to read the received setup packet.
* @pre In order to use this function the endpoint must have been
* initialized as a control endpoint.
* @post The endpoint is ready to accept another packet.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
* @param[out] buf buffer where to copy the packet data
*
* @notapi
*/
void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf) {
volatile uint32_t * const EPSRAM = (void *)(USB_SRAM_BASE + 0);
for (size_t i = 0; i < 8; i += 4) {
const uint32_t word = EPSRAM[i/4];
buf[i + 0] = (word>>0);
buf[i + 1] = (word>>8);
buf[i + 2] = (word>>16);
buf[i + 3] = (word>>24);
}
(void)usbp;
(void)ep;
}
/**
* @brief Starts a receive operation on an OUT endpoint.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
*
* @notapi
*/
void usb_lld_start_out(USBDriver *usbp, usbep_t ep) {
USBOutEndpointState * const osp = usbp->epc[ep]->out_state;
if (osp->rxsize == 0)
osp->rxpkts = 1;
else
osp->rxpkts = (osp->rxsize + usbp->epc[ep]->out_maxsize - 1) /
usbp->epc[ep]->out_maxsize;
USB->EP[ep].CSR &= USBEPnCSR_NAKRX;
}
/**
* @brief Starts a transmit operation on an IN endpoint.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
*
* @notapi
*/
void usb_lld_start_in(USBDriver *usbp, usbep_t ep) {
USBInEndpointState * const isp = usbp->epc[ep]->in_state;
isp->txlastpktlen = 0;
usb_packet_transmit(usbp, ep, isp->txsize);
}
/**
* @brief Brings an OUT endpoint in the stalled state.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
*
* @notapi
*/
void usb_lld_stall_out(USBDriver *usbp, usbep_t ep) {
(void)usbp;
USB->EP[ep].CSR = USBEPnCSR_STLRX;
}
/**
* @brief Brings an IN endpoint in the stalled state.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
*
* @notapi
*/
void usb_lld_stall_in(USBDriver *usbp, usbep_t ep) {
(void)usbp;
USB->EP[ep].CSR = USBEPnCSR_STLTX;
}
/**
* @brief Brings an OUT endpoint in the active state.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
*
* @notapi
*/
void usb_lld_clear_out(USBDriver *usbp, usbep_t ep) {
(void)usbp;
USB->EP[ep].CSR &= USBEPnCSR_STLRX;
}
/**
* @brief Brings an IN endpoint in the active state.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
*
* @notapi
*/
void usb_lld_clear_in(USBDriver *usbp, usbep_t ep) {
(void)usbp;
USB->EP[ep].CSR &= USBEPnCSR_STLTX;
}
#endif /* HAL_USE_USB == TRUE */
/** @} */

View File

@ -0,0 +1,395 @@
/*
ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
Copyright (C) 2020 Yaotian Feng
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 hal_usb_lld.h
* @brief HT32 USB subsystem low level driver header.
*
* @addtogroup USB
* @{
*/
#ifndef HAL_USB_LLD_H
#define HAL_USB_LLD_H
#if (HAL_USE_USB == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/**
* @brief Maximum endpoint address.
*/
#define USB_MAX_ENDPOINTS 7
/**
* @brief Status stage handling method.
*/
#define USB_EP0_STATUS_STAGE USB_EP0_STATUS_STAGE_SW
/**
* @brief The address can be changed immediately upon packet reception.
*/
#define USB_SET_ADDRESS_MODE USB_EARLY_SET_ADDRESS
/**
* @brief Method for set address acknowledge.
*/
#define USB_SET_ADDRESS_ACK_HANDLING USB_SET_ADDRESS_ACK_SW
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name HT32 configuration options
* @{
*/
/**
* @brief USB driver enable switch.
* @details If set to @p TRUE the support for USB0 is included.
* @note The default is @p FALSE.
*/
#if !defined(HT32_USB_USE_USB0) || defined(__DOXYGEN__)
#define HT32_USB_USE_USB0 FALSE
#endif
/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief Type of an IN endpoint state structure.
*/
typedef struct {
/**
* @brief Requested transmit transfer size.
*/
size_t txsize;
/**
* @brief Transmitted bytes so far.
*/
size_t txcnt;
/**
* @brief Pointer to the transmission linear buffer.
*/
const uint8_t *txbuf;
#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__)
/**
* @brief Waiting thread.
*/
thread_reference_t thread;
#endif
/* End of the mandatory fields.*/
uint16_t txlastpktlen;
} USBInEndpointState;
/**
* @brief Type of an OUT endpoint state structure.
*/
typedef struct {
/**
* @brief Requested receive transfer size.
*/
size_t rxsize;
/**
* @brief Received bytes so far.
*/
size_t rxcnt;
/**
* @brief Pointer to the receive linear buffer.
*/
uint8_t *rxbuf;
#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__)
/**
* @brief Waiting thread.
*/
thread_reference_t thread;
#endif
/* End of the mandatory fields.*/
uint16_t rxpkts;
} USBOutEndpointState;
/**
* @brief Type of an USB endpoint configuration structure.
* @note Platform specific restrictions may apply to endpoints.
*/
typedef struct {
/**
* @brief Type and mode of the endpoint.
*/
uint32_t ep_mode;
/**
* @brief Setup packet notification callback.
* @details This callback is invoked when a setup packet has been
* received.
* @post The application must immediately call @p usbReadPacket() in
* order to access the received packet.
* @note This field is only valid for @p USB_EP_MODE_TYPE_CTRL
* endpoints, it should be set to @p NULL for other endpoint
* types.
*/
usbepcallback_t setup_cb;
/**
* @brief IN endpoint notification callback.
* @details This field must be set to @p NULL if the IN endpoint is not
* used.
*/
usbepcallback_t in_cb;
/**
* @brief OUT endpoint notification callback.
* @details This field must be set to @p NULL if the OUT endpoint is not
* used.
*/
usbepcallback_t out_cb;
/**
* @brief IN endpoint maximum packet size.
* @details This field must be set to zero if the IN endpoint is not
* used.
*/
uint16_t in_maxsize;
/**
* @brief OUT endpoint maximum packet size.
* @details This field must be set to zero if the OUT endpoint is not
* used.
*/
uint16_t out_maxsize;
/**
* @brief @p USBEndpointState associated to the IN endpoint.
* @details This structure maintains the state of the IN endpoint.
*/
USBInEndpointState *in_state;
/**
* @brief @p USBEndpointState associated to the OUT endpoint.
* @details This structure maintains the state of the OUT endpoint.
*/
USBOutEndpointState *out_state;
/* End of the mandatory fields.*/
} USBEndpointConfig;
/**
* @brief Type of an USB driver configuration structure.
*/
typedef struct {
/**
* @brief USB events callback.
* @details This callback is invoked when an USB driver event is registered.
*/
usbeventcb_t event_cb;
/**
* @brief Device GET_DESCRIPTOR request callback.
* @note This callback is mandatory and cannot be set to @p NULL.
*/
usbgetdescriptor_t get_descriptor_cb;
/**
* @brief Requests hook callback.
* @details This hook allows to be notified of standard requests or to
* handle non standard requests.
*/
usbreqhandler_t requests_hook_cb;
/**
* @brief Start Of Frame callback.
*/
usbcallback_t sof_cb;
/* End of the mandatory fields.*/
} USBConfig;
/**
* @brief Structure representing an USB driver.
*/
struct USBDriver {
/**
* @brief Driver state.
*/
usbstate_t state;
/**
* @brief Current configuration data.
*/
const USBConfig *config;
/**
* @brief Bit map of the transmitting IN endpoints.
*/
uint16_t transmitting;
/**
* @brief Bit map of the receiving OUT endpoints.
*/
uint16_t receiving;
/**
* @brief Active endpoints configurations.
*/
const USBEndpointConfig *epc[USB_MAX_ENDPOINTS + 1];
/**
* @brief Fields available to user, it can be used to associate an
* application-defined handler to an IN endpoint.
* @note The base index is one, the endpoint zero does not have a
* reserved element in this array.
*/
void *in_params[USB_MAX_ENDPOINTS];
/**
* @brief Fields available to user, it can be used to associate an
* application-defined handler to an OUT endpoint.
* @note The base index is one, the endpoint zero does not have a
* reserved element in this array.
*/
void *out_params[USB_MAX_ENDPOINTS];
/**
* @brief Endpoint 0 state.
*/
usbep0state_t ep0state;
/**
* @brief Next position in the buffer to be transferred through endpoint 0.
*/
uint8_t *ep0next;
/**
* @brief Number of bytes yet to be transferred through endpoint 0.
*/
size_t ep0n;
/**
* @brief Endpoint 0 end transaction callback.
*/
usbcallback_t ep0endcb;
/**
* @brief Setup packet buffer.
*/
uint8_t setup[8];
/**
* @brief Current USB device status.
*/
uint16_t status;
/**
* @brief Assigned USB address.
*/
uint8_t address;
/**
* @brief Current USB device configuration.
*/
uint8_t configuration;
/**
* @brief State of the driver when a suspend happened.
*/
usbstate_t saved_state;
#if defined(USB_DRIVER_EXT_FIELDS)
USB_DRIVER_EXT_FIELDS
#endif
/* End of the mandatory fields.*/
uint16_t epmem_next;
};
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/**
* @brief Returns the current frame number.
*
* @param[in] usbp pointer to the @p USBDriver object
* @return The current frame number.
*
* @notapi
*/
#define usb_lld_get_frame_number(usbp) (USB->FCR & USBFCR_FRNUM)
/**
* @brief Returns the exact size of a receive transaction.
* @details The received size can be different from the size specified in
* @p usbStartReceiveI() because the last packet could have a size
* different from the expected one.
* @pre The OUT endpoint must have been configured in transaction mode
* in order to use this function.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
* @return Received data size.
*
* @notapi
*/
#define usb_lld_get_transaction_size(usbp, ep) \
((usbp)->epc[ep]->out_state->rxcnt)
/**
* @brief Connects the USB device.
*
* @api
*/
#define usb_lld_connect_bus(usbp) \
do { \
USB->CSR |= USBCSR_DPPUEN; \
} while (FALSE)
/**
* @brief Disconnect the USB device.
*
* @api
*/
#define usb_lld_disconnect_bus(usbp) \
do { \
USB->CSR &= ~USBCSR_DPPUEN; \
} while (FALSE)
/**
* @brief Start of host wake-up procedure.
*
* @notapi
*/
#define usb_lld_wakeup_host(usbp) \
do { \
USB->CSR |= USBCSR_GENRSM; \
} while (FALSE)
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#if (HT32_USB_USE_USB0 == TRUE) && !defined(__DOXYGEN__)
extern USBDriver USBD1;
#endif
#ifdef __cplusplus
extern "C" {
#endif
void usb_lld_init(void);
void usb_lld_start(USBDriver *usbp);
void usb_lld_stop(USBDriver *usbp);
void usb_lld_reset(USBDriver *usbp);
void usb_lld_set_address(USBDriver *usbp);
void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep);
void usb_lld_disable_endpoints(USBDriver *usbp);
usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep);
usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep);
void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf);
void usb_lld_start_out(USBDriver *usbp, usbep_t ep);
void usb_lld_start_in(USBDriver *usbp, usbep_t ep);
void usb_lld_stall_out(USBDriver *usbp, usbep_t ep);
void usb_lld_stall_in(USBDriver *usbp, usbep_t ep);
void usb_lld_clear_out(USBDriver *usbp, usbep_t ep);
void usb_lld_clear_in(USBDriver *usbp, usbep_t ep);
#ifdef __cplusplus
}
#endif
#endif /* HAL_USE_USB == TRUE */
#endif /* HAL_USB_LLD_H */
/** @} */

0
testhal/HT32/.keep Normal file
View File

0
testhal/LPC/.keep Normal file
View File